aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzotlabs <mike@macgirvin.com>2018-05-14 17:20:25 -0700
committerzotlabs <mike@macgirvin.com>2018-05-14 17:20:25 -0700
commitd9759ba63c8fd70c4da66669389bd19bae3333ff (patch)
treef3c79c407688a9dc41d70af1fa1057caeed08a0a
parent356c7003f2d18a283a819c22c255f03397e99fc9 (diff)
downloadvolse-hubzilla-d9759ba63c8fd70c4da66669389bd19bae3333ff.tar.gz
volse-hubzilla-d9759ba63c8fd70c4da66669389bd19bae3333ff.tar.bz2
volse-hubzilla-d9759ba63c8fd70c4da66669389bd19bae3333ff.zip
more refactor tags/mentions
-rw-r--r--Zotlabs/Module/Item.php2
-rw-r--r--include/text.php113
2 files changed, 54 insertions, 61 deletions
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
index 640b4fa5c..ef1eb3700 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -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
diff --git a/include/text.php b/include/text.php
index 7a6fb3d4e..1c4f5e2ec 100644
--- a/include/text.php
+++ b/include/text.php
@@ -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);