2013-01-11 01:20:16 +01:00
< ? php
2017-12-04 14:33:49 +01:00
/**
* @ file include / tags . php
*/
2017-04-30 06:07:00 +02:00
use Friendica\App ;
2017-12-04 15:04:36 +01:00
use Friendica\Content\Feature ;
2018-01-21 19:33:59 +01:00
use Friendica\Core\L10n ;
2017-08-26 08:04:21 +02:00
use Friendica\Core\System ;
2017-11-22 21:29:07 +01:00
use Friendica\Database\DBM ;
2017-12-07 15:04:24 +01:00
use Friendica\Model\Contact ;
2017-04-30 06:07:00 +02:00
2018-01-01 21:57:29 +01:00
function create_tags_from_item ( $itemid )
{
2017-08-26 09:32:10 +02:00
$profile_base = System :: baseUrl ();
2013-01-13 14:50:55 +01:00
$profile_data = parse_url ( $profile_base );
2018-01-01 21:57:29 +01:00
$profile_path = defaults ( $profile_data , 'path' , '' );
$profile_base_friendica = $profile_data [ 'host' ] . $profile_path . '/profile/' ;
$profile_base_diaspora = $profile_data [ 'host' ] . $profile_path . '/u/' ;
2013-01-13 14:50:55 +01:00
2015-03-07 21:24:39 +01:00
$messages = q ( " SELECT `guid`, `uid`, `id`, `edited`, `deleted`, `created`, `received`, `title`, `body`, `tag`, `parent` FROM `item` WHERE `id` = %d LIMIT 1 " , intval ( $itemid ));
2013-01-11 01:20:16 +01:00
if ( ! $messages )
return ;
$message = $messages [ 0 ];
// Clean up all tags
2013-01-13 14:50:55 +01:00
q ( " DELETE FROM `term` WHERE `otype` = %d AND `oid` = %d AND `type` IN (%d, %d) " ,
intval ( TERM_OBJ_POST ),
intval ( $itemid ),
intval ( TERM_HASHTAG ),
intval ( TERM_MENTION ));
2013-01-11 01:20:16 +01:00
2018-01-01 21:57:29 +01:00
if ( $message [ 'deleted' ]) {
2013-01-11 01:20:16 +01:00
return ;
2018-01-01 21:57:29 +01:00
}
2013-01-11 01:20:16 +01:00
2018-01-01 21:57:29 +01:00
$taglist = explode ( ',' , $message [ 'tag' ]);
2013-01-11 01:20:16 +01:00
2018-01-01 21:57:29 +01:00
$tags = '' ;
foreach ( $taglist as $tag ) {
if (( substr ( trim ( $tag ), 0 , 1 ) == '#' ) || ( substr ( trim ( $tag ), 0 , 1 ) == '@' )) {
$tags .= ' ' . trim ( $tag );
} else {
$tags .= ' #' . trim ( $tag );
}
}
2013-01-11 01:20:16 +01:00
2018-01-01 21:57:29 +01:00
$data = ' ' . $message [ 'title' ] . ' ' . $message [ 'body' ] . ' ' . $tags . ' ' ;
2013-01-11 01:20:16 +01:00
2015-03-22 17:12:51 +01:00
// ignore anything in a code block
2018-01-01 21:57:29 +01:00
$data = preg_replace ( '/\[code\](.*?)\[\/code\]/sm' , '' , $data );
2015-03-22 17:12:51 +01:00
2018-01-15 14:05:12 +01:00
$tags = [];
2013-01-11 01:20:16 +01:00
2018-01-01 21:57:29 +01:00
$pattern = '/\W\#([^\[].*?)[\s\'".,:;\?!\[\]\/]/ism' ;
if ( preg_match_all ( $pattern , $data , $matches )) {
foreach ( $matches [ 1 ] as $match ) {
$tags [ '#' . strtolower ( $match )] = '' ;
}
}
2013-01-11 01:20:16 +01:00
2018-01-01 21:57:29 +01:00
$pattern = '/\W([\#@])\[url\=(.*?)\](.*?)\[\/url\]/ism' ;
2013-01-11 01:20:16 +01:00
if ( preg_match_all ( $pattern , $data , $matches , PREG_SET_ORDER )) {
2018-01-01 21:57:29 +01:00
foreach ( $matches as $match ) {
$tags [ $match [ 1 ] . strtolower ( trim ( $match [ 3 ], ',.:;[]/\"?!' ))] = $match [ 2 ];
}
2013-01-11 01:20:16 +01:00
}
2018-01-01 21:57:29 +01:00
foreach ( $tags as $tag => $link ) {
if ( substr ( trim ( $tag ), 0 , 1 ) == '#' ) {
2013-06-26 13:58:54 +02:00
// try to ignore #039 or #1 or anything like that
2018-01-01 21:57:29 +01:00
if ( ctype_digit ( substr ( trim ( $tag ), 1 )))
2013-06-26 13:58:54 +02:00
continue ;
// try to ignore html hex escapes, e.g. #x2317
2018-01-01 21:57:29 +01:00
if (( substr ( trim ( $tag ), 1 , 1 ) == 'x' || substr ( trim ( $tag ), 1 , 1 ) == 'X' ) && ctype_digit ( substr ( trim ( $tag ), 2 )))
2013-06-21 14:00:30 +02:00
continue ;
2013-01-13 14:50:55 +01:00
$type = TERM_HASHTAG ;
$term = substr ( $tag , 1 );
2018-01-01 21:57:29 +01:00
} elseif ( substr ( trim ( $tag ), 0 , 1 ) == '@' ) {
2013-01-13 14:50:55 +01:00
$type = TERM_MENTION ;
$term = substr ( $tag , 1 );
} else { // This shouldn't happen
$type = TERM_HASHTAG ;
2013-08-03 21:18:41 +02:00
$term = $tag ;
2013-01-13 14:50:55 +01:00
}
2018-01-01 21:57:29 +01:00
if ( $message [ 'uid' ] == 0 ) {
2015-03-08 03:27:14 +01:00
$global = true ;
q ( " UPDATE `term` SET `global` = 1 WHERE `otype` = %d AND `guid` = '%s' " ,
2018-01-01 21:57:29 +01:00
intval ( TERM_OBJ_POST ), dbesc ( $message [ 'guid' ]));
2015-03-08 03:27:14 +01:00
} else {
$isglobal = q ( " SELECT `global` FROM `term` WHERE `uid` = 0 AND `otype` = %d AND `guid` = '%s' " ,
2018-01-01 21:57:29 +01:00
intval ( TERM_OBJ_POST ), dbesc ( $message [ 'guid' ]));
2015-03-08 03:27:14 +01:00
$global = ( count ( $isglobal ) > 0 );
}
2018-01-04 03:12:19 +01:00
q ( " INSERT INTO `term` (`uid`, `oid`, `otype`, `type`, `term`, `url`, `guid`, `created`, `received`, `global`)
2015-03-08 03:27:14 +01:00
VALUES ( % d , % d , % d , % d , '%s' , '%s' , '%s' , '%s' , '%s' , % d ) " ,
2018-01-01 21:57:29 +01:00
intval ( $message [ 'uid' ]), intval ( $itemid ), intval ( TERM_OBJ_POST ), intval ( $type ), dbesc ( $term ),
dbesc ( $link ), dbesc ( $message [ 'guid' ]), dbesc ( $message [ 'created' ]), dbesc ( $message [ 'received' ]), intval ( $global ));
2013-01-13 14:50:55 +01:00
// Search for mentions
2017-06-08 04:00:59 +02:00
if (( substr ( $tag , 0 , 1 ) == '@' ) && ( strpos ( $link , $profile_base_friendica ) || strpos ( $link , $profile_base_diaspora ))) {
2013-01-13 14:50:55 +01:00
$users = q ( " SELECT `uid` FROM `contact` WHERE self AND (`url` = '%s' OR `nurl` = '%s') " , $link , $link );
foreach ( $users AS $user ) {
2018-01-01 21:57:29 +01:00
if ( $user [ 'uid' ] == $message [ 'uid' ]) {
2013-01-13 14:50:55 +01:00
q ( " UPDATE `item` SET `mention` = 1 WHERE `id` = %d " , intval ( $itemid ));
2014-03-09 09:19:14 +01:00
2018-01-01 21:57:29 +01:00
q ( " UPDATE `thread` SET `mention` = 1 WHERE `iid` = %d " , intval ( $message [ 'parent' ]));
2014-03-09 09:19:14 +01:00
}
2013-01-13 14:50:55 +01:00
}
}
}
2013-01-11 01:20:16 +01:00
}
2018-01-01 21:57:29 +01:00
function create_tags_from_itemuri ( $itemuri , $uid )
{
2013-01-11 01:20:16 +01:00
$messages = q ( " SELECT `id` FROM `item` WHERE uri ='%s' AND uid=%d " , dbesc ( $itemuri ), intval ( $uid ));
2017-04-04 19:48:25 +02:00
if ( count ( $messages )) {
foreach ( $messages as $message ) {
2018-01-01 21:57:29 +01:00
create_tags_from_item ( $message [ 'id' ]);
2017-04-04 19:48:25 +02:00
}
2013-04-17 17:32:31 +02:00
}
2013-01-11 01:20:16 +01:00
}
2018-01-01 21:57:29 +01:00
function update_items ()
{
2017-04-24 23:02:51 +02:00
$messages = dba :: p ( " SELECT `oid`,`item`.`guid`, `item`.`created`, `item`.`received` FROM `term` INNER JOIN `item` ON `item`.`id`=`term`.`oid` WHERE `term`.`otype` = 1 AND `term`.`guid` = '' " );
2015-03-07 21:24:39 +01:00
2018-01-01 21:57:29 +01:00
logger ( 'fetched messages: ' . dba :: num_rows ( $messages ));
2017-04-24 23:02:51 +02:00
while ( $message = dba :: fetch ( $messages )) {
2018-01-01 21:57:29 +01:00
if ( $message [ 'uid' ] == 0 ) {
2015-03-08 03:27:14 +01:00
$global = true ;
q ( " UPDATE `term` SET `global` = 1 WHERE `otype` = %d AND `guid` = '%s' " ,
2018-01-01 21:57:29 +01:00
intval ( TERM_OBJ_POST ), dbesc ( $message [ 'guid' ]));
2015-03-08 03:27:14 +01:00
} else {
$isglobal = q ( " SELECT `global` FROM `term` WHERE `uid` = 0 AND `otype` = %d AND `guid` = '%s' " ,
2018-01-01 21:57:29 +01:00
intval ( TERM_OBJ_POST ), dbesc ( $message [ 'guid' ]));
2015-03-08 03:27:14 +01:00
$global = ( count ( $isglobal ) > 0 );
}
2015-03-09 00:45:53 +01:00
2015-03-08 03:27:14 +01:00
q ( " UPDATE `term` SET `guid` = '%s', `created` = '%s', `received` = '%s', `global` = %d WHERE `otype` = %d AND `oid` = %d " ,
2018-01-01 21:57:29 +01:00
dbesc ( $message [ 'guid' ]), dbesc ( $message [ 'created' ]), dbesc ( $message [ 'received' ]),
intval ( $global ), intval ( TERM_OBJ_POST ), intval ( $message [ 'oid' ]));
2015-03-07 21:24:39 +01:00
}
2017-04-24 23:02:51 +02:00
dba :: close ( $messages );
2015-03-09 00:45:53 +01:00
2017-04-24 23:02:51 +02:00
$messages = dba :: p ( " SELECT `guid` FROM `item` WHERE `uid` = 0 " );
2015-03-09 00:45:53 +01:00
2018-01-01 21:57:29 +01:00
logger ( 'fetched messages: ' . dba :: num_rows ( $messages ));
2017-04-24 23:02:51 +02:00
while ( $message = dba :: fetch ( messages )) {
2018-01-01 21:57:29 +01:00
q ( " UPDATE `item` SET `global` = 1 WHERE `guid` = '%s' " , dbesc ( $message [ 'guid' ]));
2015-03-09 00:45:53 +01:00
}
2017-04-24 23:02:51 +02:00
dba :: close ( $messages );
2013-01-11 01:20:16 +01:00
}
2017-11-22 21:29:07 +01:00
2017-11-26 04:33:21 +01:00
/**
* @ brief Get alphabetical sorted array of used tags / terms of an user including
* a weighting by frequency of use .
2017-12-07 15:04:24 +01:00
*
2017-11-26 04:33:21 +01:00
* @ param int $uid The user ID .
* @ param int $count Max number of displayed tags / terms .
* @ param int $owner_id The contact id of the owner of the tagged items .
* @ param string $flags Special item flags .
* @ param int $type The tag / term type .
2017-12-07 15:04:24 +01:00
*
2017-11-26 04:33:21 +01:00
* @ return arr Alphabetical sorted array of used tags of an user .
*/
2018-01-01 21:57:29 +01:00
function tagadelic ( $uid , $count = 0 , $owner_id = 0 , $flags = '' , $type = TERM_HASHTAG )
{
require_once 'include/security.php' ;
2017-11-22 21:29:07 +01:00
$item_condition = item_condition ();
$sql_options = item_permissions_sql ( $uid );
2018-01-01 21:57:29 +01:00
$limit = $count ? sprintf ( 'LIMIT %d' , intval ( $count )) : '' ;
2017-11-26 16:14:16 +01:00
2017-11-22 21:29:07 +01:00
if ( $flags ) {
if ( $flags === 'wall' ) {
2018-01-01 21:57:29 +01:00
$sql_options .= ' AND `item`.`wall` ' ;
2017-11-22 21:29:07 +01:00
}
}
2017-11-22 23:18:01 +01:00
2017-11-23 00:59:20 +01:00
if ( $owner_id ) {
2018-01-01 21:57:29 +01:00
$sql_options .= ' AND `item`.`owner-id` = ' . intval ( $owner_id ) . ' ' ;
2017-11-22 21:29:07 +01:00
}
// Fetch tags
2017-11-26 16:14:16 +01:00
$r = dba :: p ( " SELECT `term`, COUNT(`term`) AS `total` FROM `term`
2017-11-22 21:29:07 +01:00
LEFT JOIN `item` ON `term` . `oid` = `item` . `id`
2017-11-26 16:14:16 +01:00
WHERE `term` . `uid` = ? AND `term` . `type` = ?
AND `term` . `otype` = ?
2017-11-23 03:43:39 +01:00
AND $item_condition $sql_options
2017-11-26 16:24:26 +01:00
GROUP BY `term` ORDER BY `total` DESC $limit " ,
2017-11-26 16:14:16 +01:00
$uid ,
$type ,
TERM_OBJ_POST
2017-11-22 21:29:07 +01:00
);
2018-01-01 21:57:29 +01:00
if ( ! DBM :: is_result ( $r )) {
2018-01-15 14:05:12 +01:00
return [];
2017-11-22 21:29:07 +01:00
}
2017-12-07 15:04:24 +01:00
2017-11-22 21:29:07 +01:00
return tag_calc ( $r );
}
2017-11-26 04:33:21 +01:00
/**
* @ brief Construct a tag / term cloud block for an user .
2017-12-07 15:04:24 +01:00
*
2017-11-26 04:33:21 +01:00
* @ param int $uid The user ID .
* @ param int $count Max number of displayed tags / terms .
* @ param int $owner_id The contact ID of the owner of the tagged items .
* @ param string $flags Special item flags .
* @ param int $type The tag / term type .
2017-12-07 15:04:24 +01:00
*
2017-11-26 04:33:21 +01:00
* @ return string HTML formatted output .
*/
2018-01-01 21:57:29 +01:00
function wtagblock ( $uid , $count = 0 , $owner_id = 0 , $flags = '' , $type = TERM_HASHTAG )
{
2017-11-22 21:29:07 +01:00
$o = '' ;
2017-11-23 00:59:20 +01:00
$r = tagadelic ( $uid , $count , $owner_id , $flags , $type );
2017-11-26 04:33:21 +01:00
if ( count ( $r )) {
2018-01-10 14:36:02 +01:00
$contact = dba :: selectFirst ( 'contact' , [ 'url' ], [ 'id' => $uid ]);
2017-11-23 00:59:20 +01:00
$url = System :: removedBaseUrl ( $contact [ 'url' ]);
2017-11-22 21:29:07 +01:00
foreach ( $r as $rr ) {
$tag [ 'level' ] = $rr [ 2 ];
2018-01-01 21:57:29 +01:00
$tag [ 'url' ] = $url . '?tag=' . urlencode ( $rr [ 0 ]);
2017-11-22 21:29:07 +01:00
$tag [ 'name' ] = $rr [ 0 ];
$tags [] = $tag ;
}
2018-01-01 21:57:29 +01:00
$tpl = get_markup_template ( 'tagblock_widget.tpl' );
2018-01-15 14:05:12 +01:00
$o = replace_macros ( $tpl , [
2018-01-21 19:33:59 +01:00
'$title' => L10n :: t ( 'Tags' ),
2018-01-01 21:57:29 +01:00
'$tags' => $tags
2018-01-15 14:05:12 +01:00
]);
2017-11-22 21:29:07 +01:00
}
return $o ;
}
2017-11-26 04:33:21 +01:00
/**
* @ brief Calculate weighting of tags according to the frequency of use .
2017-12-07 15:04:24 +01:00
*
2017-11-26 04:33:21 +01:00
* @ param array $arr Array of tags / terms with tag / term name and total count of use .
* @ return array Alphabetical sorted array of used tags / terms of an user .
*/
2018-01-01 21:57:29 +01:00
function tag_calc ( $arr )
{
2018-01-15 14:05:12 +01:00
$tags = [];
2017-11-22 21:29:07 +01:00
$min = 1e9 ;
$max = - 1e9 ;
$x = 0 ;
if ( ! $arr ) {
2018-01-15 14:05:12 +01:00
return [];
2017-11-22 21:29:07 +01:00
}
foreach ( $arr as $rr ) {
$tags [ $x ][ 0 ] = $rr [ 'term' ];
$tags [ $x ][ 1 ] = log ( $rr [ 'total' ]);
$tags [ $x ][ 2 ] = 0 ;
$min = min ( $min , $tags [ $x ][ 1 ]);
$max = max ( $max , $tags [ $x ][ 1 ]);
$x ++ ;
}
2017-11-22 23:18:01 +01:00
usort ( $tags , 'tags_sort' );
2017-11-22 21:29:07 +01:00
$range = max ( . 01 , $max - $min ) * 1.0001 ;
for ( $x = 0 ; $x < count ( $tags ); $x ++ ) {
$tags [ $x ][ 2 ] = 1 + floor ( 9 * ( $tags [ $x ][ 1 ] - $min ) / $range );
}
return $tags ;
}
2017-11-26 04:33:21 +01:00
/**
* @ brief Compare function to sort tags / terms alphabetically .
2017-12-07 15:04:24 +01:00
*
2017-11-26 04:33:21 +01:00
* @ param type $a
* @ param type $b
2017-12-07 15:04:24 +01:00
*
2017-11-26 04:33:21 +01:00
* @ return int
*/
2018-01-01 21:57:29 +01:00
function tags_sort ( $a , $b )
{
2017-11-22 21:29:07 +01:00
if ( strtolower ( $a [ 0 ]) == strtolower ( $b [ 0 ])) {
return 0 ;
}
2017-11-26 04:33:21 +01:00
return (( strtolower ( $a [ 0 ]) < strtolower ( $b [ 0 ])) ? - 1 : 1 );
2017-11-22 21:29:07 +01:00
}
2017-11-26 04:33:21 +01:00
/**
* @ brief Insert a tag cloud widget for the present profile .
2017-12-07 15:04:24 +01:00
*
2017-11-26 04:33:21 +01:00
* @ param int $limit Max number of displayed tags .
* @ return string HTML formattat output .
*/
2018-01-01 21:57:29 +01:00
function tagcloud_wall_widget ( $limit = 50 )
{
2017-11-22 21:29:07 +01:00
$a = get_app ();
2018-01-01 21:57:29 +01:00
if ( ! $a -> profile [ 'profile_uid' ] || ! $a -> profile [ 'url' ]) {
return '' ;
2017-11-22 21:29:07 +01:00
}
2018-01-01 21:57:29 +01:00
if ( Feature :: isEnabled ( $a -> profile [ 'profile_uid' ], 'tagadelic' )) {
2017-11-22 21:29:07 +01:00
$owner_id = Contact :: getIdForURL ( $a -> profile [ 'url' ]);
2017-11-22 23:18:01 +01:00
2018-01-01 21:57:29 +01:00
if ( ! $owner_id ) {
return '' ;
2017-11-22 21:29:07 +01:00
}
2017-11-22 23:18:01 +01:00
return wtagblock ( $a -> profile [ 'profile_uid' ], $limit , $owner_id , 'wall' );
2017-11-22 21:29:07 +01:00
}
2018-01-01 21:57:29 +01:00
return '' ;
2017-11-22 21:29:07 +01:00
}