From f853d58198b3ebee1af85bc76982e7552c2701e8 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 2 Mar 2022 06:59:07 +0000 Subject: [PATCH] API: Forum mentions are now working --- mod/item.php | 93 ++++++---------------- src/Content/Item.php | 73 ++++++++++++++++- src/Module/Api/Twitter/Statuses/Update.php | 7 +- 3 files changed, 98 insertions(+), 75 deletions(-) diff --git a/mod/item.php b/mod/item.php index bc35282e33..855e7de3f2 100644 --- a/mod/item.php +++ b/mod/item.php @@ -383,69 +383,34 @@ function item_post(App $a) { $contact_record = DBA::selectFirst('contact', [], ['uid' => $profile_uid, 'self' => true]) ?: []; } - // Look for any tags and linkify them - $inform = ''; - $private_forum = false; - $private_id = null; - $only_to_forum = false; - $forum_contact = []; - // 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::setMentions($body, local_user() ? local_user() : $profile_uid, $network); + // Look for any tags and linkify them + $item = [ + 'uid' => local_user() ? local_user() : $profile_uid, + 'gravity' => $toplevel_item_id ? GRAVITY_COMMENT : GRAVITY_PARENT, + 'network' => $network, + 'body' => $body, + 'postopts' => $postopts, + 'private' => $private, + 'allow_cid' => $str_contact_allow, + 'allow_gid' => $str_group_allow, + 'deny_cid' => $str_contact_deny, + 'deny_gid' => $str_group_deny, + ]; - // 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']; + $item = DI::contentItem()->expandTags($item); - if ($toplevel_item_id || empty($contact['cid']) || ($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; - - if (!$toplevel_item_id && !empty($forum_contact) && ($private_forum || $only_to_forum)) { - // we tagged a forum in a top level post. Now we change the post - $private = $private_forum ? Item::PRIVATE : Item::UNLISTED; - - if ($only_to_forum) { - $postopts = ''; - } - - $str_contact_deny = ''; - $str_group_deny = ''; - - if ($private_forum) { - $str_contact_allow = '<' . $private_id . '>'; - $str_group_allow = '<' . Group::getIdForForum($forum_contact['id']) . '>'; - } else { - $str_contact_allow = ''; - $str_group_allow = ''; - } + $body = $item['body']; + $inform = $item['inform']; + $postopts = $item['postopts']; + $private = $item['private']; + $str_contact_allow = $item['allow_cid']; + $str_group_allow = $item['allow_gid']; + $str_contact_deny = $item['deny_cid']; + $str_group_deny = $item['deny_gid']; + } else { + $inform = ''; } /* @@ -460,7 +425,7 @@ function item_post(App $a) { $match = null; - if (!$preview && Photo::setPermissionFromBody($body, $uid, $original_contact_id, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny)) { + if (!$preview && Photo::setPermissionFromBody($body, $uid, $contact_id, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny)) { $objecttype = Activity\ObjectType::IMAGE; } @@ -475,7 +440,7 @@ function item_post(App $a) { if (count($attaches)) { foreach ($attaches as $attach) { // Ensure to only modify attachments that you own - $srch = '<' . intval($original_contact_id) . '>'; + $srch = '<' . intval($contact_id) . '>'; $condition = ['allow_cid' => $srch, 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '', 'id' => $attach]; @@ -797,12 +762,6 @@ function item_post(App $a) { } } - // When we are doing some forum posting via ! we have to start the notifier manually. - // These kind of posts don't initiate the notifier call in the item class. - if ($only_to_forum) { - Worker::add(['priority' => PRIORITY_HIGH, 'dont_fork' => false], "Notifier", Delivery::POST, (int)$datarray['uri-id'], (int)$datarray['uid']); - } - Logger::info('post_complete'); if ($api_source) { diff --git a/src/Content/Item.php b/src/Content/Item.php index 5037be80e2..334507861b 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -21,12 +21,15 @@ namespace Friendica\Content; +use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\L10n; +use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\Session; use Friendica\Database\DBA; use Friendica\Model\Contact; +use Friendica\Model\Group; use Friendica\Model\Item as ModelItem; use Friendica\Model\Tag; use Friendica\Model\Post; @@ -53,7 +56,7 @@ class Item $this->activity = $activity; $this->l10n = $l10n; } - + /** * Return array with details for categories and folders for an item * @@ -479,7 +482,7 @@ class Item if (empty($item['verb']) || $this->activity->isHidden($item['verb'])) { return false; } - + // @TODO below if() block can be rewritten to a single line: $isVisible = allConditionsHere; if ($this->activity->match($item['verb'], Activity::FOLLOW) && $item['object-type'] === Activity\ObjectType::NOTE && @@ -487,7 +490,71 @@ class Item $item['uid'] == local_user()) { return false; } - + return true; } + + public function expandTags(array $item) + { + // Look for any tags and linkify them + $item['inform'] = ''; + $private_forum = false; + $private_id = null; + $only_to_forum = false; + $forum_contact = []; + + // Convert mentions in the body to a unified format + $item['body'] = BBCode::setMentions($item['body'], $item['uid'], $item['network']); + + // Search for forum mentions + foreach (Tag::getFromBody($item['body'], Tag::TAG_CHARACTER[Tag::MENTION] . Tag::TAG_CHARACTER[Tag::EXCLUSIVE_MENTION]) as $tag) { + $contact = Contact::getByURLForUser($tag[2], $item['uid']); + if (!empty($item['inform'])) { + $item['inform'] .= ','; + } + $item['inform'] .= 'cid:' . $contact['id']; + + if (($item['gravity'] == GRAVITY_COMMENT) || empty($contact['cid']) || ($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 ($item['allow_cid'] == '<' . $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' => $item['inform']]); + + if (($item['gravity'] == GRAVITY_PARENT) && !empty($forum_contact) && ($private_forum || $only_to_forum)) { + // we tagged a forum in a top level post. Now we change the post + $item['private'] = $private_forum ? ModelItem::PRIVATE : ModelItem::UNLISTED; + + if ($only_to_forum) { + $item['postopts'] = ''; + } + + $item['deny_cid'] = ''; + $item['deny_gid'] = ''; + + if ($private_forum) { + $item['allow_cid'] = '<' . $private_id . '>'; + $item['allow_gid'] = '<' . Group::getIdForForum($forum_contact['id']) . '>'; + } else { + $item['allow_cid'] = ''; + $item['allow_gid'] = ''; + } + } + return $item; + } } diff --git a/src/Module/Api/Twitter/Statuses/Update.php b/src/Module/Api/Twitter/Statuses/Update.php index 45e56cea85..6ee305d19d 100644 --- a/src/Module/Api/Twitter/Statuses/Update.php +++ b/src/Module/Api/Twitter/Statuses/Update.php @@ -78,11 +78,6 @@ class Update extends BaseApi $body = Markdown::toBBCode($request['status']); } - // Avoids potential double expansion of existing links - $body = BBCode::performWithEscapedTags($body, ['url'], function ($body) { - return BBCode::expandTags($body); - }); - $item = []; $item['uid'] = $uid; $item['verb'] = Activity::POST; @@ -127,6 +122,8 @@ class Update extends BaseApi $item['object-type'] = Activity\ObjectType::NOTE; } + $item = DI::contentItem()->expandTags($item); + if (!empty($request['media_ids'])) { $ids = explode(',', $request['media_ids']); } elseif (!empty($_FILES['media'])) {