diff --git a/mod/item.php b/mod/item.php index 7d9cdb028..7cf2e53d4 100644 --- a/mod/item.php +++ b/mod/item.php @@ -393,48 +393,38 @@ function item_post(App $a) { // Personal notes must never be altered to a forum post. if ($posttype != Item::PT_PERSONAL_NOTE) { - $body = BBCode::performWithEscapedTags($body, ['noparse', 'pre', 'code', 'img'], function ($body) use ($profile_uid, $network, $str_contact_allow, &$inform, &$private_forum, &$private_id, &$only_to_forum, &$forum_contact) { - $tags = BBCode::getTags($body); + // Convert mentions in the body to a unified format + $body = BBCode::setMentions($body, local_user() ? local_user() : $profile_uid, $network); - $tagged = []; + // Search for forum mentions + foreach (Tag::getFromBody($body, Tag::TAG_CHARACTER[Tag::MENTION] . Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION]) as $tag) { + $contact = Contact::getByURLForUser($tag[2], $profile_uid); + if (!empty($inform)) { + $inform .= ','; + } + $inform .= 'cid:' . $contact['id']; - foreach ($tags as $tag) { - $tag_type = substr($tag, 0, 1); - - if ($tag_type == Tag::TAG_CHARACTER[Tag::HASHTAG]) { - continue; - } - - /* If we already tagged 'Robert Johnson', don't try and tag 'Robert'. - * Robert Johnson should be first in the $tags array - */ - foreach ($tagged as $nextTag) { - if (stristr($nextTag, $tag . ' ')) { - continue 2; - } - } - - if ($success = ItemHelper::replaceTag($body, $inform, local_user() ? local_user() : $profile_uid, $tag, $network)) { - if ($success['replaced']) { - $tagged[] = $tag; - } - // When the forum is private or the forum is addressed with a "!" make the post private - if (!empty($success['contact']['prv']) || ($tag_type == Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION])) { - $private_forum = $success['contact']['prv']; - $only_to_forum = ($tag_type == Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION]); - $private_id = $success['contact']['id']; - $forum_contact = $success['contact']; - } elseif (!empty($success['contact']['forum']) && ($str_contact_allow == '<' . $success['contact']['id'] . '>')) { - $private_forum = false; - $only_to_forum = true; - $private_id = $success['contact']['id']; - $forum_contact = $success['contact']; - } - } + if (!$toplevel_item_id || empty($contact['cid']) || ($contact['contact-type'] != Contact::TYPE_COMMUNITY)) { + continue; } - return $body; - }); + if (!empty($contact['prv']) || ($tag[1] == Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION])) { + $private_forum = $contact['prv']; + $only_to_forum = ($tag[1] == Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION]); + $private_id = $contact['id']; + $forum_contact = $contact; + Logger::info('Private forum or exclusive mention', ['url' => $tag[2], 'mention' => $tag[1]]); + } elseif ($str_contact_allow == '<' . $contact['id'] . '>') { + $private_forum = false; + $only_to_forum = true; + $private_id = $contact['id']; + $forum_contact = $contact; + Logger::info('Public forum', ['url' => $tag[2], 'mention' => $tag[1]]); + } else { + Logger::info('Post with forum mention will not be converted to a forum post', ['url' => $tag[2], 'mention' => $tag[1]]); + } + } + Logger::info('Got inform', ['inform' => $inform]); } $original_contact_id = $contact_id; diff --git a/src/Content/Item.php b/src/Content/Item.php index 694ef52d9..5037be80e 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -135,7 +135,6 @@ class Item * the appropriate link. * * @param string $body the text to replace the tag in - * @param string $inform a comma-seperated string containing everybody to inform * @param integer $profile_uid the user id to replace the tag for (0 = anyone) * @param string $tag the tag to replace * @param string $network The network of the post @@ -144,7 +143,7 @@ class Item * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function replaceTag(&$body, &$inform, $profile_uid, $tag, $network = '') + public static function replaceTag(&$body, $profile_uid, $tag, $network = '') { $replaced = false; @@ -218,16 +217,6 @@ class Item // Check if $contact has been successfully loaded if (DBA::isResult($contact)) { - if (strlen($inform) && (isset($contact['notify']) || isset($contact['id']))) { - $inform .= ','; - } - - if (isset($contact['id'])) { - $inform .= 'cid:' . $contact['id']; - } elseif (isset($contact['notify'])) { - $inform .= $contact['notify']; - } - $profile = $contact['url']; $newname = ($contact['name'] ?? '') ?: $contact['nick']; } diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 4c895f533..e676673fc 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -2346,7 +2346,7 @@ class BBCode } /** - * Replaces mentions in the provided message body for the provided user and network if any + * Replaces mentions in the provided message body in BBCode links for the provided user and network if any * * @param $body * @param $profile_uid @@ -2358,11 +2358,10 @@ class BBCode public static function setMentions($body, $profile_uid = 0, $network = '') { DI::profiler()->startRecording('rendering'); - self::performWithEscapedTags($body, ['noparse', 'pre', 'code', 'img'], function ($body) use ($profile_uid, $network) { + $body = self::performWithEscapedTags($body, ['noparse', 'pre', 'code', 'img'], function ($body) use ($profile_uid, $network) { $tags = self::getTags($body); $tagged = []; - $inform = ''; foreach ($tags as $tag) { $tag_type = substr($tag, 0, 1); @@ -2381,7 +2380,7 @@ class BBCode } } - if (($success = Item::replaceTag($body, $inform, $profile_uid, $tag, $network)) && $success['replaced']) { + if (($success = Item::replaceTag($body, $profile_uid, $tag, $network)) && $success['replaced']) { $tagged[] = $tag; } } diff --git a/src/Model/Tag.php b/src/Model/Tag.php index 3020a2f29..17a68f120 100644 --- a/src/Model/Tag.php +++ b/src/Model/Tag.php @@ -206,6 +206,27 @@ class Tag self::store($uriid, $type, $name, $url, $probing); } + /** + * Get tags and mentions from the body + * + * @param string $body Body of the post + * @param string $tags Accepted tags + * + * @return array Tag list + */ + public static function getFromBody(string $body, string $tags = null) + { + if (is_null($tags)) { + $tags = self::TAG_CHARACTER[self::HASHTAG] . self::TAG_CHARACTER[self::MENTION] . self::TAG_CHARACTER[self::EXCLUSIVE_MENTION]; + } + + if (!preg_match_all("/([" . $tags . "])\[url\=([^\[\]]*)\]([^\[\]]*)\[\/url\]/ism", $body, $result, PREG_SET_ORDER)) { + return []; + } + + return $result; + } + /** * Store tags and mentions from the body * @@ -216,13 +237,10 @@ class Tag */ public static function storeFromBody(int $uriid, string $body, string $tags = null, $probing = true) { - if (is_null($tags)) { - $tags = self::TAG_CHARACTER[self::HASHTAG] . self::TAG_CHARACTER[self::MENTION] . self::TAG_CHARACTER[self::EXCLUSIVE_MENTION]; - } - Logger::info('Check for tags', ['uri-id' => $uriid, 'hash' => $tags, 'callstack' => System::callstack()]); - if (!preg_match_all("/([" . $tags . "])\[url\=([^\[\]]*)\]([^\[\]]*)\[\/url\]/ism", $body, $result, PREG_SET_ORDER)) { + $result = self::getFromBody($body, $tags); + if (empty($result)) { return; } diff --git a/tests/src/Model/TagTest.php b/tests/src/Model/TagTest.php new file mode 100644 index 000000000..7858cec95 --- /dev/null +++ b/tests/src/Model/TagTest.php @@ -0,0 +1,49 @@ +. + * + */ + +namespace Friendica\Test\src\Model; + +use Friendica\Model\Tag; +use PHPUnit\Framework\TestCase; + +class TagTest extends TestCase +{ + /** + * + */ + public function testGetFromBody() + { + $body = '![url=https://pirati.ca/profile/test1]Testgruppe 1b[/url] Test, please ignore'; + + $tags = Tag::getFromBody($body); + + $expected = [ + [ + '![url=https://pirati.ca/profile/test1]Testgruppe 1b[/url]', + '!', + 'https://pirati.ca/profile/test1', + 'Testgruppe 1b' + ] + ]; + + self::assertEquals($expected, $tags); + } +}