more refactor tags/mentions

This commit is contained in:
zotlabs 2018-05-14 17:20:25 -07:00
parent 356c7003f2
commit d9759ba63c
2 changed files with 54 additions and 61 deletions

View file

@ -533,7 +533,7 @@ class Item extends \Zotlabs\Web\Controller {
// Look for tags and linkify them
$results = linkify_tags($a, $body, ($uid) ? $uid : $profile_uid);
logger('linkify: ' . print_r($results,true));
if($results) {
// Set permissions based on tag replacements

View file

@ -824,7 +824,7 @@ function get_tags($s) {
// match bracket mentions
if(preg_match_all('/([@!]\{.*?\})/',$s,$match)) {
if(preg_match_all('/([@!]\!?\{.*?\})/',$s,$match)) {
foreach($match[1] as $mtch) {
$ret[] = $mtch;
}
@ -833,12 +833,19 @@ function get_tags($s) {
// Pull out single word tags. These can be @nickname, @first_last
// and #hash tags.
if(preg_match_all('/(?<![a-zA-Z0-9=\pL\/\?\;])([@#\!][^ \x0D\x0A,;:\?\[\{\&]+)/u',$s,$match)) {
if(preg_match_all('/(?<![a-zA-Z0-9=\pL\/\?\;])([@#\!]\!?[^ \x0D\x0A,;:\?\[\{\&]+)/u',$s,$match)) {
foreach($match[1] as $mtch) {
// Cleanup/ignore false positives
// Just ignore these rather than try and adjust the regex to deal with them
if(in_array($mtch,[ '@!', '!!' ]))
continue;
// likewise for trailing period. Strip it off rather than complicate the regex further.
if(substr($mtch,-1,1) === '.')
$mtch = substr($mtch,0,-1);
// ignore strictly numeric tags like #1 or #^ bookmarks or ## double hash
if((strpos($mtch,'#') === 0) && ( ctype_digit(substr($mtch,1)) || substr($mtch,1,1) === '^') || substr($mtch,1,1) === '#')
if((strpos($mtch,'#') === 0) && ( ctype_digit(substr($mtch,1)) || in_array(substr($mtch,1,1), [ '^', '#' ])))
continue;
// or quote remnants from the quoted strings we already picked out earlier
if(strpos($mtch,'&quot'))
@ -863,7 +870,7 @@ function get_tags($s) {
usort($ret,'tag_sort_length');
// logger('get_tags: ' . print_r($ret,true));
// logger('get_tags: ' . print_r($ret,true));
return $ret;
}
@ -2537,9 +2544,10 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
$termtype = ((strpos($tag,'!') === 0) ? TERM_FORUM : $termtype);
$termtype = ((strpos($tag,'#^[') === 0) ? TERM_BOOKMARK : $termtype);
//is it a hash tag?
if(strpos($tag,'#') === 0) {
if(strpos($tag,'#^[') === 0) {
// Is it a hashtag of some kind?
if ( in_array($termtype, [ TERM_HASHTAG, TERM_BOOKMARK ] )) {
if($termtype === TERM_BOOKMARK) {
if(preg_match('/#\^\[(url|zrl)(.*?)\](.*?)\[\/(url|zrl)\]/',$tag,$match)) {
$basetag = $match[3];
$url = ((substr($match[2],0,1) === '=') ? substr($match[2],1) : $match[3]);
@ -2548,12 +2556,13 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
}
// if the tag is already replaced...
elseif((strpos($tag,'[zrl=')) || (strpos($tag,'[url='))) {
//...do nothing
// ...do nothing
return $replaced;
}
if(! $replaced) {
// base tag has the tags name only
// double-quoted hashtags: base tag has the htmlentity name only
if((substr($tag,0,7) === '#&quot;') && (substr($tag,-6,6) === '&quot;')) {
$basetag = substr($tag,7);
@ -2562,21 +2571,20 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
else
$basetag = substr($tag,1);
//create text for link
// create text for link
$url = z_root() . '/search?tag=' . rawurlencode($basetag);
$newtag = '#[zrl=' . z_root() . '/search?tag=' . rawurlencode($basetag) . ']' . $basetag . '[/zrl]';
//replace tag by the link. Make sure to not replace something in the middle of a word
// The '=' is needed to not replace color codes if the code is also used as a tag
// Much better would be to somehow completely avoiding things in e.g. [color]-tags.
// This would allow writing things like "my favourite tag=#foobar".
// replace tag by the link. Make sure to not replace something in the middle of a word
$body = preg_replace('/(?<![a-zA-Z0-9=])'.preg_quote($tag,'/').'/', $newtag, $body);
$replaced = true;
}
//is the link already in str_tags?
// is the link already in str_tags?
if(! stristr($str_tags,$newtag)) {
//append or set str_tags
// append or set str_tags
if(strlen($str_tags))
$str_tags .= ',';
@ -2587,43 +2595,38 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
'termtype' => $termtype,
'term' => $basetag,
'url' => $url,
'contact' => $r[0]
'contact' => []
];
}
//is it a person tag?
// END hashtags
$grouptag = false;
// BEGIN mentions
if(strpos($tag,'!') === 0) {
$grouptag = true;
}
if ( in_array($termtype, [ TERM_MENTION, TERM_FORUM ] )) {
if(strpos($tag,'@') === 0 || $grouptag) {
// The @! tag and !! tag will alter permissions
// The @! tag will alter permissions
$exclusive = (((! $grouptag) && (strpos($tag,'!') === 1) && $in_network) ? true : false);
if(($grouptag) && (strpos($tag,'!!') === 0)) {
$exclusive = true;
}
// $in_network is set to false to avoid false positives on posts originating
// on a network which does not implement privacy tags or implements them differently.
$exclusive = (((strpos($tag,'!') === 1) && $in_network) ? true : false);
//is it already replaced?
if(strpos($tag,'[zrl=') || strpos($tag,'[url='))
return $replaced;
//get the person's name
// get the channel name
// First extract the name or name fragment we are going to replace
$name = substr($tag,(($exclusive) ? 2 : 1)); // The name or name fragment we are going to replace
$newname = $name; // a copy that we can mess with
$name = substr($tag,(($exclusive) ? 2 : 1));
$newname = $name; // make a copy that we can mess with
$tagcid = 0;
$r = null;
// is it some generated name?
$forum = false;
$trailing_plus_name = false;
// is it some generated (autocompleted) name?
if(substr($name,0,1) === '{' && substr($name,-1,1) === '}') {
$newname = substr($name,1);
@ -2639,15 +2642,17 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
// look for matching names in the address book
// Two ways to deal with spaces - double quote the name or use underscores
// we see this after input filtering so quotes have been html entity encoded
// Double quote the entire mentioned term to include special characters
// such as spaces and some punctuation.
// We see this after input filtering so quotes have been html entity encoded
if((substr($name,0,6) === '&quot;') && (substr($name,-6,6) === '&quot;')) {
$newname = substr($name,6);
$newname = substr($newname,0,-6);
}
//select someone from this user's contacts by name
// select someone from this user's contacts by name
$r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash
WHERE xchan_name = '%s' AND abook_channel = %d LIMIT 1",
@ -2664,7 +2669,7 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
);
}
//select someone by attag or nick and the name passed in
// select someone by attag or nick and the name passed in
if(! $r) {
$r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash
@ -2679,7 +2684,7 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
// $r is set if we found something
$channel = App::get_channel();
if($r) {
$profile = $r[0]['xchan_url'];
$newname = $r[0]['xchan_name'];
@ -2717,23 +2722,24 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
}
}
// if there is an url for this channel
// if there is a url for this channel
if(isset($profile)) {
$replaced = true;
//create profile link
$profile = str_replace(',','%2c',$profile);
$url = $profile;
if($grouptag) {
if($termtype === TERM_FORUM) {
$newtag = '!' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
$body = str_replace('!' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
}
else {
// ( $termtype === TERM_MENTION )
$newtag = '@' . (($exclusive) ? '!' : '') . '[zrl=' . $profile . ']' . $newname . '[/zrl]';
$body = str_replace('@' . (($exclusive) ? '!' : '') . $name, $newtag, $body);
}
//append tag to str_tags
// append tag to str_tags
if(! stristr($str_tags,$newtag)) {
if(strlen($str_tags))
$str_tags .= ',';
@ -2747,14 +2753,14 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
'termtype' => $termtype,
'term' => $newname,
'url' => $url,
'contact' => $r[0]
'contact' => (($r) ? $r[0] : [])
];
}
function linkify_tags($a, &$body, $uid, $in_network = true) {
$str_tags = '';
$tagged = array();
$results = array();
$str_tags = EMPTY_STR;
$tagged = [];
$results = [];
$tags = get_tags($body);
@ -2762,19 +2768,6 @@ function linkify_tags($a, &$body, $uid, $in_network = true) {
foreach($tags as $tag) {
$access_tag = '';
// If we already tagged 'Robert Johnson', don't try and tag 'Robert'.
// Robert Johnson should be first in the $tags array
$fullnametagged = false;
for($x = 0; $x < count($tagged); $x ++) {
if(stristr($tagged[$x],$tag . ' ')) {
$fullnametagged = true;
break;
}
}
if($fullnametagged)
continue;
$success = handle_tag($a, $body, $access_tag, $str_tags, ($uid) ? $uid : App::$profile_uid , $tag, $in_network);
$results[] = array('success' => $success, 'access_tag' => $access_tag);