From b9ea7adbda751286ec0892771671fa1ee96c36e5 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 04:48:22 +0000 Subject: [PATCH 01/13] Issue 10966: Perform forum handling with the unified format --- mod/item.php | 52 ++++++++++++++++++++++++++++------------------- src/Model/Tag.php | 28 ++++++++++++++++++++----- 2 files changed, 54 insertions(+), 26 deletions(-) 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; } From 0e5ee88c43dd74601cbb7319d2d3de0b7abf75f9 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 08:48:09 +0000 Subject: [PATCH 02/13] Only use mention and exclusive mention --- mod/item.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/item.php b/mod/item.php index 30cb010608..fd284fa2d0 100644 --- a/mod/item.php +++ b/mod/item.php @@ -422,7 +422,7 @@ function item_post(App $a) { // Search for forum mentions if (!$toplevel_item_id) { - foreach (Tag::getFromBody($body) as $tag) { + foreach (Tag::getFromBody($body, Tag::TAG_CHARACTER[Tag::MENTION] . Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION]) as $tag) { $contact = Contact::getByURL($tag[2], false, [], $profile_uid); if ($contact['contact-type'] != Contact::TYPE_COMMUNITY) { continue; From 8034a48ffe6deef939172c8e659cbd3e0d497464 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 10:56:13 +0000 Subject: [PATCH 03/13] "inform" functionality moved / unified functionality --- mod/item.php | 72 ++++++++++++++----------------------- src/Content/Item.php | 13 +------ src/Content/Text/BBCode.php | 5 ++- 3 files changed, 29 insertions(+), 61 deletions(-) diff --git a/mod/item.php b/mod/item.php index fd284fa2d0..d47a78053f 100644 --- a/mod/item.php +++ b/mod/item.php @@ -394,57 +394,37 @@ function item_post(App $a) { // Personal notes must never be altered to a forum post. if ($posttype != Item::PT_PERSONAL_NOTE) { // 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 = []; - - 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; - } - } - - ItemHelper::replaceTag($body, $inform, local_user() ? local_user() : $profile_uid, $tag, $network); - } - - return $body; - }); + $body = BBCode::setMentions($body, local_user() ? local_user() : $profile_uid, $network); // Search for forum mentions - if (!$toplevel_item_id) { - foreach (Tag::getFromBody($body, Tag::TAG_CHARACTER[Tag::MENTION] . Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION]) as $tag) { - $contact = Contact::getByURL($tag[2], false, [], $profile_uid); - if ($contact['contact-type'] != Contact::TYPE_COMMUNITY) { - continue; - } + foreach (Tag::getFromBody($body, Tag::TAG_CHARACTER[Tag::MENTION] . Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION]) as $tag) { + $contact = Contact::getByURL($tag[2], false, [], $profile_uid); + if (!empty($inform)) { + $inform .= ','; + } + $inform .= 'cid:' . $contact['id']; - 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]]); - } + if (!$toplevel_item_id || ($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]]); } } + Logger::info('Got inform', ['inform' => $inform]); } $original_contact_id = $contact_id; diff --git a/src/Content/Item.php b/src/Content/Item.php index 694ef52d96..5037be80e2 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 4c895f5337..0bb55215ec 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -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; } } From df9ed6af0e4aa4a1f30aac14ab00bf1c12d9b225 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 13:46:11 +0000 Subject: [PATCH 04/13] Notifications for non contacts --- mod/item.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/item.php b/mod/item.php index d47a78053f..7cf2e53d49 100644 --- a/mod/item.php +++ b/mod/item.php @@ -398,13 +398,13 @@ function item_post(App $a) { // Search for forum mentions foreach (Tag::getFromBody($body, Tag::TAG_CHARACTER[Tag::MENTION] . Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION]) as $tag) { - $contact = Contact::getByURL($tag[2], false, [], $profile_uid); + $contact = Contact::getByURLForUser($tag[2], $profile_uid); if (!empty($inform)) { $inform .= ','; } $inform .= 'cid:' . $contact['id']; - if (!$toplevel_item_id || ($contact['contact-type'] != Contact::TYPE_COMMUNITY)) { + if (!$toplevel_item_id || empty($contact['cid']) || ($contact['contact-type'] != Contact::TYPE_COMMUNITY)) { continue; } From 72f755ce910ce646233063bae95ffebb239e75f7 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 15:12:07 +0000 Subject: [PATCH 05/13] Empty test function added --- tests/src/Model/TagTest.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/src/Model/TagTest.php diff --git a/tests/src/Model/TagTest.php b/tests/src/Model/TagTest.php new file mode 100644 index 0000000000..0b091e7f3e --- /dev/null +++ b/tests/src/Model/TagTest.php @@ -0,0 +1,36 @@ +. + * + */ + +namespace Friendica\Test\src\Model; + +use PHPUnit\Framework\TestCase; + +class TagTest extends TestCase +{ + /** + * + */ + public function testGetFromBody() + { + self::markTestIncomplete('Needs knowledge.'); + } + +} From 3fab53d3358e89bae24ce9bbd86385319ab8d329 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 15:17:27 +0000 Subject: [PATCH 06/13] Fix whitespace --- tests/src/Model/TagTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Model/TagTest.php b/tests/src/Model/TagTest.php index 0b091e7f3e..942110362c 100644 --- a/tests/src/Model/TagTest.php +++ b/tests/src/Model/TagTest.php @@ -26,7 +26,7 @@ use PHPUnit\Framework\TestCase; class TagTest extends TestCase { /** - * + * */ public function testGetFromBody() { From 71959bb9fc858e2ad116d9b63a97676f58b4f562 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 15:57:54 +0000 Subject: [PATCH 07/13] Added some testable data --- tests/src/Model/TagTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/src/Model/TagTest.php b/tests/src/Model/TagTest.php index 942110362c..4d60023ef1 100644 --- a/tests/src/Model/TagTest.php +++ b/tests/src/Model/TagTest.php @@ -21,6 +21,7 @@ namespace Friendica\Test\src\Model; +use Friendica\Model\Tag; use PHPUnit\Framework\TestCase; class TagTest extends TestCase @@ -30,6 +31,9 @@ class TagTest extends TestCase */ public function testGetFromBody() { + $body = '![url=https://pirati.ca/profile/test1]Testgruppe 1b[/url] Test, please ignore'; + $tags = Tag::getFromBody($body); + // Some expectations here self::markTestIncomplete('Needs knowledge.'); } From baf8951745f8841beff1c596b0dd405c5d76f8ed Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 16:00:17 +0000 Subject: [PATCH 08/13] Converted in tabs --- tests/src/Model/TagTest.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/src/Model/TagTest.php b/tests/src/Model/TagTest.php index 4d60023ef1..c40778660a 100644 --- a/tests/src/Model/TagTest.php +++ b/tests/src/Model/TagTest.php @@ -26,15 +26,15 @@ 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); - // Some expectations here - self::markTestIncomplete('Needs knowledge.'); - } + /** + * + */ + public function testGetFromBody() + { + $body = '![url=https://pirati.ca/profile/test1]Testgruppe 1b[/url] Test, please ignore'; + $tags = Tag::getFromBody($body); + // Some expectations here + self::markTestIncomplete('Needs knowledge.'); + } } From 95664a6824ec0591264b668537eef4a3bd5bb829 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 16:06:19 +0000 Subject: [PATCH 09/13] Removed empty line --- tests/src/Model/TagTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/src/Model/TagTest.php b/tests/src/Model/TagTest.php index c40778660a..1bd1933523 100644 --- a/tests/src/Model/TagTest.php +++ b/tests/src/Model/TagTest.php @@ -36,5 +36,4 @@ class TagTest extends TestCase // Some expectations here self::markTestIncomplete('Needs knowledge.'); } - } From 4f60b1660eb2cab4c31873347fbd0999a625adb3 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 16:21:07 +0000 Subject: [PATCH 10/13] Added test data --- tests/src/Model/TagTest.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/src/Model/TagTest.php b/tests/src/Model/TagTest.php index 1bd1933523..aed2db319a 100644 --- a/tests/src/Model/TagTest.php +++ b/tests/src/Model/TagTest.php @@ -33,7 +33,15 @@ class TagTest extends TestCase { $body = '![url=https://pirati.ca/profile/test1]Testgruppe 1b[/url] Test, please ignore'; $tags = Tag::getFromBody($body); - // Some expectations here - self::markTestIncomplete('Needs knowledge.'); + $expected = [ + [ + '![url=https://pirati.ca/profile/test1]Testgruppe 1b[/url]', + '!', + 'https://pirati.ca/profile/test1', + 'Testgruppe 1b' + ] + ]; + + self::assertEquals($expected, $tags); } } From 273f4c352e9c521444cda44cf95b10b72cabab11 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 16:26:29 +0000 Subject: [PATCH 11/13] Spaces --- tests/src/Model/TagTest.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/src/Model/TagTest.php b/tests/src/Model/TagTest.php index aed2db319a..c85b173acd 100644 --- a/tests/src/Model/TagTest.php +++ b/tests/src/Model/TagTest.php @@ -33,15 +33,15 @@ class TagTest extends TestCase { $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' - ] - ]; + $expected = [ + [ + '![url=https://pirati.ca/profile/test1]Testgruppe 1b[/url]', + '!', + 'https://pirati.ca/profile/test1', + 'Testgruppe 1b' + ] + ]; - self::assertEquals($expected, $tags); + self::assertEquals($expected, $tags); } } From 7f59dc07c4da1216e50bbfeed036d198f3b56a3f Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Jan 2022 16:30:49 +0000 Subject: [PATCH 12/13] New lines added --- tests/src/Model/TagTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/src/Model/TagTest.php b/tests/src/Model/TagTest.php index c85b173acd..7858cec954 100644 --- a/tests/src/Model/TagTest.php +++ b/tests/src/Model/TagTest.php @@ -32,7 +32,9 @@ 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]', From 54d474d0e461c05d8c5455c5ac60a68cc9298b6f Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 31 Jan 2022 05:47:18 +0000 Subject: [PATCH 13/13] function documentation clarified --- src/Content/Text/BBCode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 0bb55215ec..e676673fc1 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