]> git.mxchange.org Git - friendica.git/blobdiff - src/Model/Item.php
Merge pull request #13611 from annando/languages
[friendica.git] / src / Model / Item.php
index ad93b949d9f6e01600108be8c2160b919cce3561..18b56215ce39ca9a680e64fc062f693c84dca392 100644 (file)
@@ -117,7 +117,7 @@ class Item
        const DELIVER_FIELDLIST = [
                'uid', 'id', 'parent', 'uri-id', 'uri', 'thr-parent', 'parent-uri', 'guid',
                'parent-guid', 'conversation', 'received', 'created', 'edited', 'verb', 'object-type', 'object', 'target',
-               'private', 'title', 'body', 'raw-body', 'location', 'coord', 'app',
+               'private', 'title', 'body', 'raw-body', 'language', 'location', 'coord', 'app',
                'inform', 'deleted', 'extid', 'post-type', 'post-reason', 'gravity',
                'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid',
                'author-id', 'author-addr', 'author-link', 'author-name', 'author-avatar', 'owner-id', 'owner-link', 'contact-uid',
@@ -330,7 +330,7 @@ class Item
         */
        public static function markForDeletionById(int $item_id, int $priority = Worker::PRIORITY_HIGH): bool
        {
-               Logger::info('Mark item for deletion by id', ['id' => $item_id, 'callstack' => System::callstack()]);
+               Logger::info('Mark item for deletion by id', ['id' => $item_id]);
                // locate item to be deleted
                $fields = [
                        'id', 'uri', 'uri-id', 'uid', 'parent', 'parent-uri-id', 'origin',
@@ -795,7 +795,7 @@ class Item
                }
 
                if (!DBA::isResult($parent)) {
-                       Logger::notice('item parent was not found - ignoring item', ['uri-id' => $item['uri-id'], 'thr-parent-id' => $item['thr-parent-id'], 'uid' => $item['uid'], 'callstack' => System::callstack(20)]);
+                       Logger::notice('item parent was not found - ignoring item', ['uri-id' => $item['uri-id'], 'thr-parent-id' => $item['thr-parent-id'], 'uid' => $item['uid']]);
                        return [];
                }
 
@@ -880,6 +880,10 @@ class Item
                        if (is_int($notify) && in_array($notify, Worker::PRIORITIES)) {
                                $priority = $notify;
                        }
+
+                       // Mastodon style API visibility
+                       $copy_permissions = ($item['visibility'] ?? 'private') == 'private';
+                       unset($item['visibility']);
                } else {
                        $item['network'] = trim(($item['network'] ?? '') ?: Protocol::PHANTOM);
                }
@@ -1038,10 +1042,12 @@ class Item
 
                        // Reshares have to keep their permissions to allow groups to work
                        if (!$defined_permissions && (!$item['origin'] || ($item['verb'] != Activity::ANNOUNCE))) {
-                               $item['allow_cid']     = $toplevel_parent['allow_cid'];
-                               $item['allow_gid']     = $toplevel_parent['allow_gid'];
-                               $item['deny_cid']      = $toplevel_parent['deny_cid'];
-                               $item['deny_gid']      = $toplevel_parent['deny_gid'];
+                               // Don't store the permissions on pure AP posts
+                               $store_permissions = ($item['network'] != Protocol::ACTIVITYPUB) || $item['origin'] || !empty($item['diaspora_signed_text']);
+                               $item['allow_cid'] = $store_permissions ? $toplevel_parent['allow_cid'] : '';
+                               $item['allow_gid'] = $store_permissions ? $toplevel_parent['allow_gid'] : '';
+                               $item['deny_cid']  = $store_permissions ? $toplevel_parent['deny_cid'] : '';
+                               $item['deny_gid']  = $store_permissions ? $toplevel_parent['deny_gid'] : '';
                        }
 
                        $parent_origin         = $toplevel_parent['origin'];
@@ -1183,7 +1189,7 @@ class Item
                        if (!empty($quote_id)) {
                                // This is one of these "should not happen" situations.
                                // The protocol implementations should already have done this job.
-                               Logger::notice('Quote-uri-id detected in post', ['id' => $quote_id, 'guid' => $item['guid'], 'uri-id' => $item['uri-id'], 'callstack' => System::callstack(20)]);
+                               Logger::notice('Quote-uri-id detected in post', ['id' => $quote_id, 'guid' => $item['guid'], 'uri-id' => $item['uri-id']]);
                                $item['quote-uri-id'] = $quote_id;
                        }
                }
@@ -1359,6 +1365,9 @@ class Item
 
                if ($notify) {
                        DI::contentItem()->postProcessPost($posted_item);
+                       if ($copy_permissions && ($posted_item['thr-parent-id'] != $posted_item['uri-id']) && ($posted_item['private'] == self::PRIVATE)) {
+                               DI::contentItem()->copyPermissions($posted_item['thr-parent-id'], $posted_item['uri-id']);
+                       }
                } else {
                        Hook::callAll('post_remote_end', $posted_item);
                }
@@ -1475,6 +1484,10 @@ class Item
         */
        private static function setOwnerforResharedItem(array $item)
        {
+               if ($item['uid'] == 0) {
+                       return;
+               }
+
                $parent = Post::selectFirst(
                        ['id', 'causer-id', 'owner-id', 'author-id', 'author-link', 'origin', 'post-reason'],
                        ['uri-id' => $item['thr-parent-id'], 'uid' => $item['uid']]
@@ -2025,15 +2038,12 @@ class Item
                        return [];
                }
 
-               $availableLanguages = DI::l10n()->getAvailableLanguages(true);
-               $availableLanguages = DI::l10n()->convertForLanguageDetection($availableLanguages);
-
-               $ld = new Language(array_keys($availableLanguages));
+               $ld = new Language(DI::l10n()->getDetectableLanguages());
 
                $result = [];
 
                foreach (self::splitByBlocks($searchtext) as $block) {
-                       $languages = $ld->detect($block)->limit(0, $count)->close() ?: [];
+                       $languages = $ld->detect($block)->close() ?: [];
 
                        $data = [
                                'text'      => $block,
@@ -2048,10 +2058,32 @@ class Item
                        }
                }
 
+               $result = self::compactLanguages($result);
+
                arsort($result);
-               $result = array_slice($result, 0, $count);
+               return array_slice($result, 0, $count);
+       }
 
-               return $result;
+       /**
+        * Concert the language code in the detection result to ISO 639-1.
+        * On duplicates the system uses the higher quality value.
+        *
+        * @param array $result
+        * @return array
+        */
+       private static function compactLanguages(array $result): array
+       {
+               $languages = [];
+               foreach ($result as $language => $quality) {
+                       if ($quality == 0) {
+                               continue;
+                       }
+                       $code = DI::l10n()->toISO6391($language);
+                       if (empty($languages[$code]) || ($languages[$code] < $quality)) {
+                               $languages[$code] = $quality;
+                       }
+               }
+               return $languages;
        }
 
        /**
@@ -2063,7 +2095,7 @@ class Item
         */
        private static function splitByBlocks(string $body): array
        {
-               if (class_exists('IntlChar')) {
+               if (!class_exists('IntlChar')) {
                        return [$body];
                }
 
@@ -2134,7 +2166,15 @@ class Item
 
                $used_languages = '';
                foreach (json_decode($item['language'], true) as $language => $reliability) {
-                       $used_languages .= $iso639->languageByCode1($language) . ' (' . $language . "): " . number_format($reliability, 5) . '\n';
+                       $code = DI::l10n()->toISO6391($language);
+
+                       $native   = $iso639->nativeByCode1($code);
+                       $language = $iso639->languageByCode1($code);
+                       if ($native != $language) {
+                               $used_languages .= DI::l10n()->t('%s (%s - %s): %s', $native, $language, $code, number_format($reliability, 5)) . '\n';
+                       } else {
+                               $used_languages .= DI::l10n()->t('%s (%s): %s', $native, $code, number_format($reliability, 5)) . '\n';
+                       }
                }
                $used_languages = DI::l10n()->t('Detected languages in this post:\n%s', $used_languages);
                return $used_languages;
@@ -2162,7 +2202,7 @@ class Item
 
                $hostPart = $host ?: $parsed['host'] ?? '';
                if (!$hostPart) {
-                       Logger::warning('Empty host GUID part', ['uri' => $uri, 'host' => $host, 'parsed' => $parsed, 'callstack' => System::callstack(10)]);
+                       Logger::warning('Empty host GUID part', ['uri' => $uri, 'host' => $host, 'parsed' => $parsed]);
                }
 
                // Glue it together to be able to make a hash from it
@@ -3483,11 +3523,8 @@ class Item
                                continue;
                        }
 
-                       if ($PostMedia->mimetype->type == 'image') {
-                               $preview_size = $PostMedia->width > $PostMedia->height ? Proxy::SIZE_MEDIUM : Proxy::SIZE_LARGE;
-                               $preview_url = DI::baseUrl() . $PostMedia->getPreviewPath($preview_size);
-                       } elseif ($PostMedia->preview) {
-                               $preview_size = Proxy::SIZE_LARGE;
+                       if ($PostMedia->mimetype->type == 'image' || $PostMedia->preview) {
+                               $preview_size = Proxy::SIZE_MEDIUM;
                                $preview_url = DI::baseUrl() . $PostMedia->getPreviewPath($preview_size);
                        } else {
                                $preview_size = 0;
@@ -3908,11 +3945,12 @@ class Item
         * Fetches item for given URI or plink
         *
         * @param string $uri
-        * @param integer $uid
+        * @param int    $uid
+        * @param int    $completion
         *
         * @return integer item id
         */
-       public static function fetchByLink(string $uri, int $uid = 0): int
+       public static function fetchByLink(string $uri, int $uid = 0, int $completion = ActivityPub\Receiver::COMPLETION_MANUAL): int
        {
                Logger::info('Trying to fetch link', ['uid' => $uid, 'uri' => $uri]);
                $item_id = self::searchByLink($uri, $uid);
@@ -3933,7 +3971,7 @@ class Item
                        return is_numeric($hookData['item_id']) ? $hookData['item_id'] : 0;
                }
 
-               $fetched_uri = ActivityPub\Processor::fetchMissingActivity($uri, [], '', ActivityPub\Receiver::COMPLETION_MANUAL, $uid);
+               $fetched_uri = ActivityPub\Processor::fetchMissingActivity($uri, [], '', $completion, $uid);
 
                if ($fetched_uri) {
                        $item_id = self::searchByLink($fetched_uri, $uid);
@@ -3993,7 +4031,7 @@ class Item
                }
 
                $url = $shared['message_id'] ?: $shared['link'];
-               $id = self::fetchByLink($url);
+               $id = self::fetchByLink($url, 0, ActivityPub\Receiver::COMPLETION_ASYNC);
                if (!$id) {
                        Logger::notice('Post could not be fetched.', ['url' => $url, 'uid' => $uid]);
                        return 0;