diff --git a/mod/item.php b/mod/item.php index 7d9cdb0286..30cb010608 100644 --- a/mod/item.php +++ b/mod/item.php @@ -393,7 +393,8 @@ 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) { + // Convert mentions in the body to a unified format + $body = BBCode::performWithEscapedTags($body, ['noparse', 'pre', 'code', 'img'], function ($body) use ($profile_uid, $network, &$inform) { $tags = BBCode::getTags($body); $tagged = []; @@ -405,36 +406,45 @@ function item_post(App $a) { continue; } - /* If we already tagged 'Robert Johnson', don't try and tag 'Robert'. - * Robert Johnson should be first in the $tags array - */ + // 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']; - } - } + ItemHelper::replaceTag($body, $inform, local_user() ? local_user() : $profile_uid, $tag, $network); } return $body; }); + + // Search for forum mentions + if (!$toplevel_item_id) { + foreach (Tag::getFromBody($body) as $tag) { + $contact = Contact::getByURL($tag[2], false, [], $profile_uid); + if ($contact['contact-type'] != Contact::TYPE_COMMUNITY) { + continue; + } + + 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]]); + } + } + } } $original_contact_id = $contact_id; diff --git a/src/Model/Tag.php b/src/Model/Tag.php index 3020a2f293..17a68f120f 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; }