]> git.mxchange.org Git - friendica.git/blobdiff - src/Protocol/ActivityPub/Processor.php
Clarified return values
[friendica.git] / src / Protocol / ActivityPub / Processor.php
index 25f064fd6ae5d7e30f75a4ba2a6c998484e06787..c38cba28f187419258727c62693323538b5edc03 100644 (file)
@@ -65,7 +65,7 @@ class Processor
         * @param array   $implicit_mentions List of profile URLs to skip
         * @return string with tags
         */
-       private static function constructTagString($tags, $sensitive, array $implicit_mentions)
+       private static function constructTagString(array $tags, $sensitive)
        {
                if (empty($tags)) {
                        return '';
@@ -73,7 +73,7 @@ class Processor
 
                $tag_text = '';
                foreach ($tags as $tag) {
-                       if (in_array(defaults($tag, 'type', ''), ['Mention', 'Hashtag']) && !in_array($tag['href'], $implicit_mentions)) {
+                       if (in_array(defaults($tag, 'type', ''), ['Mention', 'Hashtag'])) {
                                if (!empty($tag_text)) {
                                        $tag_text .= ',';
                                }
@@ -129,7 +129,7 @@ class Processor
         */
        public static function updateItem($activity)
        {
-               $item = Item::selectFirst(['uri', 'parent-uri', 'gravity'], ['uri' => $activity['id']]);
+               $item = Item::selectFirst(['uri', 'thr-parent', 'gravity'], ['uri' => $activity['id']]);
                if (!DBA::isResult($item)) {
                        Logger::warning('Unknown item', ['uri' => $activity['id']]);
                        return;
@@ -137,28 +137,12 @@ class Processor
 
                $item['changed'] = DateTimeFormat::utcNow();
                $item['edited'] = $activity['updated'];
-               $item['title'] = HTML::toBBCode($activity['name']);
-               $item['content-warning'] = HTML::toBBCode($activity['summary']);
-
-               $content = HTML::toBBCode($activity['content']);
-               $content = self::replaceEmojis($content, $activity['emojis']);
-               $content = self::convertMentions($content);
-
-               $implicit_mentions = [];
-               if (($item['parent-uri'] != $item['uri']) && ($item['gravity'] == GRAVITY_COMMENT)) {
-                       $parent = Item::selectFirst(['id', 'author-link', 'alias'], ['uri' => $item['parent-uri']]);
-                       if (!DBA::isResult($parent)) {
-                               Logger::warning('Unknown parent item.', ['uri' => $item['parent-uri']]);
-                               return;
-                       }
 
-                       $implicit_mentions = self::getImplicitMentionList($parent);
-                       $content = self::removeImplicitMentionsFromBody($content, $implicit_mentions);
+               $item = self::processContent($activity, $item);
+               if (empty($item)) {
+                       return;
                }
 
-               $item['body'] = $content;
-               $item['tag'] = self::constructTagString($activity['tags'], $activity['sensitive'], $implicit_mentions);
-
                Item::update($item, ['uri' => $activity['id']]);
        }
 
@@ -173,7 +157,7 @@ class Processor
        {
                $item = [];
                $item['verb'] = ACTIVITY_POST;
-               $item['parent-uri'] = $activity['reply-to-id'];
+               $item['thr-parent'] = $activity['reply-to-id'];
 
                if ($activity['reply-to-id'] == $activity['id']) {
                        $item['gravity'] = GRAVITY_PARENT;
@@ -220,7 +204,7 @@ class Processor
        {
                $item = [];
                $item['verb'] = $verb;
-               $item['parent-uri'] = $activity['object_id'];
+               $item['thr-parent'] = $activity['object_id'];
                $item['gravity'] = GRAVITY_ACTIVITY;
                $item['object-type'] = ACTIVITY_OBJ_NOTE;
 
@@ -263,6 +247,62 @@ class Processor
                Logger::log('Event '.$event_id.' was stored', Logger::DEBUG);
        }
 
+       /**
+        * Process the content
+        *
+        * @param array $activity Activity array
+        * @param array $item
+        * @return array|bool Returns the item array or false if there was an unexpected occurrence
+        * @throws \Exception
+        */
+       private static function processContent($activity, $item)
+       {
+               $item['title'] = HTML::toBBCode($activity['name']);
+
+               if (!empty($activity['source'])) {
+                       $item['body'] = $activity['source'];
+               } else {
+                       $content = HTML::toBBCode($activity['content']);
+                       $content = self::replaceEmojis($content, $activity['emojis']);
+                       $content = self::convertMentions($content);
+
+                       if (($item['thr-parent'] != $item['uri']) && ($item['gravity'] == GRAVITY_COMMENT)) {
+                               $item_private = !in_array(0, $activity['item_receiver']);
+                               $parent = Item::selectFirst(['id', 'private', 'author-link', 'alias'], ['uri' => $item['thr-parent']]);
+                               if (!DBA::isResult($parent)) {
+                                       Logger::warning('Unknown parent item.', ['uri' => $item['thr-parent']]);
+                                       return false;
+                               }
+                               if ($item_private && !$parent['private']) {
+                                       Logger::warning('Item is private but the parent is not. Dropping.', ['item-uri' => $item['uri'], 'thr-parent' => $item['thr-parent']]);
+                                       return false;
+                               }
+
+                               $potential_implicit_mentions = self::getImplicitMentionList($parent);
+                               $content = self::removeImplicitMentionsFromBody($content, $potential_implicit_mentions);
+                               $activity['tags'] = self::convertImplicitMentionsInTags($activity['tags'], $potential_implicit_mentions);
+                       }
+                       $item['content-warning'] = HTML::toBBCode($activity['summary']);
+                       $item['body'] = $content;
+
+                       if (($activity['object_type'] == 'as:Video') && !empty($activity['alternate-url'])) {
+                               $item['body'] .= "\n[video]" . $activity['alternate-url'] . '[/video]';
+                       }
+               }
+
+               $item['tag'] = self::constructTagString($activity['tags'], $activity['sensitive']);
+
+               $item['location'] = $activity['location'];
+
+               if (!empty($item['latitude']) && !empty($item['longitude'])) {
+                       $item['coord'] = $item['latitude'] . ' ' . $item['longitude'];
+               }
+
+               $item['app'] = $activity['generator'];
+
+               return $item;
+       }
+
        /**
         * Creates an item post
         *
@@ -275,8 +315,8 @@ class Processor
        {
                /// @todo What to do with $activity['context']?
 
-               if (($item['gravity'] != GRAVITY_PARENT) && !Item::exists(['uri' => $item['parent-uri']])) {
-                       Logger::log('Parent ' . $item['parent-uri'] . ' not found, message will be discarded.', Logger::DEBUG);
+               if (($item['gravity'] != GRAVITY_PARENT) && !Item::exists(['uri' => $item['thr-parent']])) {
+                       Logger::info('Parent not found, message will be discarded.', ['thr-parent' => $item['thr-parent']]);
                        return;
                }
 
@@ -289,60 +329,26 @@ class Processor
                        $item['owner-link'] = $activity['actor'];
                        $item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true);
                } else {
-                       Logger::log('Ignoring actor because of thread completion.', Logger::DEBUG);
+                       Logger::info('Ignoring actor because of thread completion.');
                        $item['owner-link'] = $item['author-link'];
                        $item['owner-id'] = $item['author-id'];
                }
 
                $item['uri'] = $activity['id'];
-               $content = HTML::toBBCode($activity['content']);
-               $content = self::replaceEmojis($content, $activity['emojis']);
-               $content = self::convertMentions($content);
-
-               $implicit_mentions = [];
-
-               if (($item['parent-uri'] != $item['uri']) && ($item['gravity'] == GRAVITY_COMMENT)) {
-                       $item_private = !in_array(0, $activity['item_receiver']);
-                       $parent = Item::selectFirst(['id', 'private', 'author-link', 'alias'], ['uri' => $item['parent-uri']]);
-                       if (!DBA::isResult($parent)) {
-                               return;
-                       }
-                       if ($item_private && !$parent['private']) {
-                               Logger::log('Item ' . $item['uri'] . ' is private but the parent ' . $item['parent-uri'] . ' is not. So we drop it.');
-                               return;
-                       }
-
-                       $implicit_mentions = self::getImplicitMentionList($parent);
-                       $content = self::removeImplicitMentionsFromBody($content, $implicit_mentions);
-               }
 
                $item['created'] = $activity['published'];
                $item['edited'] = $activity['updated'];
                $item['guid'] = $activity['diaspora:guid'];
-               $item['title'] = HTML::toBBCode($activity['name']);
-               $item['content-warning'] = HTML::toBBCode($activity['summary']);
-               $item['body'] = $content;
 
-               if (($activity['object_type'] == 'as:Video') && !empty($activity['alternate-url'])) {
-                       $item['body'] .= "\n[video]" . $activity['alternate-url'] . '[/video]';
-               }
-
-               $item['location'] = $activity['location'];
-
-               if (!empty($item['latitude']) && !empty($item['longitude'])) {
-                       $item['coord'] = $item['latitude'] . ' ' . $item['longitude'];
+               $item = self::processContent($activity, $item);
+               if (empty($item)) {
+                       return;
                }
 
-               $item['tag'] = self::constructTagString($activity['tags'], $activity['sensitive'], $implicit_mentions);
-               $item['app'] = $activity['generator'];
                $item['plink'] = defaults($activity, 'alternate-url', $item['uri']);
 
                $item = self::constructAttachList($activity['attachments'], $item);
 
-               if (!empty($activity['source'])) {
-                       $item['body'] = $activity['source'];
-               }
-
                $stored = false;
 
                foreach ($activity['receiver'] as $receiver) {
@@ -358,7 +364,11 @@ class Processor
                        }
 
                        $item_id = Item::insert($item);
-                       Logger::log('Storing for user ' . $item['uid'] . ': ' . $item_id);
+                       if ($item_id) {
+                               Logger::info('Item insertion successful', ['user' => $item['uid'], 'item_id' => $item_id]);
+                       } else {
+                               Logger::notice('Item insertion aborted', ['user' => $item['uid']]);
+                       }
 
                        if ($item['uid'] == 0) {
                                $stored = $item_id;
@@ -658,13 +668,24 @@ class Processor
         */
        private static function getImplicitMentionList(array $parent)
        {
-               $parent_terms = Term::tagArrayFromItemId($parent['id'], [TERM_MENTION]);
+               if (Config::get('system', 'disable_implicit_mentions')) {
+                       return [];
+               }
 
-               $implicit_mentions = [
-                       $parent['author-link']
-               ];
+               $parent_terms = Term::tagArrayFromItemId($parent['id'], [Term::MENTION, Term::IMPLICIT_MENTION]);
+
+               $parent_author = Contact::getDetailsByURL($parent['author-link'], 0);
+
+               $implicit_mentions = [];
+               if (empty($parent_author)) {
+                       Logger::notice('Author public contact unknown.', ['author-link' => $parent['author-link'], 'item-id' => $parent['id']]);
+               } else {
+                       $implicit_mentions[] = $parent_author['url'];
+                       $implicit_mentions[] = $parent_author['nurl'];
+                       $implicit_mentions[] = $parent_author['alias'];
+               }
 
-               if ($parent['alias']) {
+               if (!empty($parent['alias'])) {
                        $implicit_mentions[] = $parent['alias'];
                }
 
@@ -684,16 +705,20 @@ class Processor
         * Strips from the body prepended implicit mentions
         *
         * @param string $body
-        * @param array  $implicit_mentions List of profile URLs
+        * @param array $potential_mentions
         * @return string
         */
-       private static function removeImplicitMentionsFromBody($body, array $implicit_mentions)
+       private static function removeImplicitMentionsFromBody($body, array $potential_mentions)
        {
+               if (Config::get('system', 'disable_implicit_mentions')) {
+                       return $body;
+               }
+
                $kept_mentions = [];
 
                // Extract one prepended mention at a time from the body
-               while(preg_match('#^(@\[url=([^\]]+)].*?\[\/url]\s)(.*)#mi', $body, $matches)) {
-                       if (!in_array($matches[2], $implicit_mentions) ) {
+               while(preg_match('#^(@\[url=([^\]]+)].*?\[\/url]\s)(.*)#is', $body, $matches)) {
+                       if (!in_array($matches[2], $potential_mentions) ) {
                                $kept_mentions[] = $matches[1];
                        }
 
@@ -705,4 +730,24 @@ class Processor
 
                return implode('', $kept_mentions);
        }
+
+       private static function convertImplicitMentionsInTags($activity_tags, array $potential_mentions)
+       {
+               if (Config::get('system', 'disable_implicit_mentions')) {
+                       return $activity_tags;
+               }
+
+               foreach ($activity_tags as $index => $tag) {
+                       if (in_array($tag['href'], $potential_mentions)) {
+                               $activity_tags[$index]['name'] = preg_replace(
+                                       '/' . preg_quote(Term::TAG_CHARACTER[Term::MENTION], '/') . '/',
+                                       Term::TAG_CHARACTER[Term::IMPLICIT_MENTION],
+                                       $activity_tags[$index]['name'],
+                                       1
+                               );
+                       }
+               }
+
+               return $activity_tags;
+       }
 }