]> git.mxchange.org Git - friendica.git/blobdiff - src/Protocol/ActivityPub/Transmitter.php
Fixes and type-hints:
[friendica.git] / src / Protocol / ActivityPub / Transmitter.php
index 553993edca300717b225bcf6a232e2c9ba7f5063..023bd5c83cce179c8c6cd16d2f9408b099f41f72 100644 (file)
@@ -44,7 +44,6 @@ use Friendica\Protocol\ActivityPub;
 use Friendica\Protocol\Relay;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\HTTPSignature;
-use Friendica\Util\JsonLD;
 use Friendica\Util\LDSignature;
 use Friendica\Util\Map;
 use Friendica\Util\Network;
@@ -59,6 +58,10 @@ use Friendica\Util\XML;
  */
 class Transmitter
 {
+       const CACHEKEY_FEATURED = 'transmitter:getFeatured:';
+       const CACHEKEY_CONTACTS = 'transmitter:getContacts:';
+       const CACHEKEY_OUTBOX   = 'transmitter:getOutbox:';
+
        /**
         * Add relay servers to the list of inboxes
         *
@@ -146,17 +149,26 @@ class Transmitter
        /**
         * Collects a list of contacts of the given owner
         *
-        * @param array     $owner     Owner array
-        * @param int|array $rel       The relevant value(s) contact.rel should match
-        * @param string    $module    The name of the relevant AP endpoint module (followers|following)
-        * @param integer   $page      Page number
-        * @param string    $requester URL of the requester
+        * @param array   $owner     Owner array
+        * @param array   $rel       The relevant value(s) contact.rel should match
+        * @param string  $module    The name of the relevant AP endpoint module (followers|following)
+        * @param integer $page      Page number
+        * @param string  $requester URL of the requester
+        * @param boolean $nocache   Wether to bypass caching
         *
         * @return array of owners
         * @throws \Exception
         */
-       public static function getContacts($owner, $rel, $module, $page = null, string $requester = null)
+       public static function getContacts(array $owner, array $rel, string $module, int $page = null, string $requester = null, $nocache = false)
        {
+               if (empty($page)) {
+                       $cachekey = self::CACHEKEY_CONTACTS . $module . ':'. $owner['uid'];
+                       $result = DI::cache()->get($cachekey);
+                       if (!$nocache && !is_null($result)) {
+                               return $result;
+                       }
+               }
+
                $parameters = [
                        'rel' => $rel,
                        'uid' => $owner['uid'],
@@ -179,6 +191,10 @@ class Transmitter
                $data['type'] = 'OrderedCollection';
                $data['totalItems'] = $total;
 
+               if (!empty($page)) {
+                       $data['id'] .= '?' . http_build_query(['page' => $page]);
+               }
+
                // When we hide our friends we will only show the pure number but don't allow more.
                $show_contacts = empty($owner['hide-friends']);
 
@@ -188,6 +204,10 @@ class Transmitter
                }
 
                if (!$show_contacts) {
+                       if (!empty($cachekey)) {
+                               DI::cache()->set($cachekey, $data, Duration::DAY);
+                       }
+
                        return $data;
                }
 
@@ -203,7 +223,7 @@ class Transmitter
                        }
                        DBA::close($contacts);
 
-                       if (!empty($list)) {
+                       if (count($list) == 100) {
                                $data['next'] = DI::baseUrl() . $modulePath . $owner['nickname'] . '?page=' . ($page + 1);
                        }
 
@@ -212,6 +232,10 @@ class Transmitter
                        $data['orderedItems'] = $list;
                }
 
+               if (!empty($cachekey)) {
+                       DI::cache()->set($cachekey, $data, Duration::DAY);
+               }
+
                return $data;
        }
 
@@ -221,13 +245,22 @@ class Transmitter
         * @param array   $owner     Owner array
         * @param integer $page      Page number
         * @param string  $requester URL of requesting account
+        * @param boolean $nocache   Wether to bypass caching
         *
         * @return array of posts
         * @throws \Friendica\Network\HTTPException\InternalServerErrorException
         * @throws \ImagickException
         */
-       public static function getOutbox($owner, $page = null, $requester = '')
+       public static function getOutbox(array $owner, int $page = null, string $requester = '', $nocache = false)
        {
+               if (empty($page)) {
+                       $cachekey = self::CACHEKEY_OUTBOX . $owner['uid'];
+                       $result = DI::cache()->get($cachekey);
+                       if (!$nocache && !is_null($result)) {
+                               return $result;
+                       }
+               }
+
                $condition = ['private' => [Item::PUBLIC, Item::UNLISTED]];
 
                if (!empty($requester)) {
@@ -258,6 +291,10 @@ class Transmitter
                $data['type'] = 'OrderedCollection';
                $data['totalItems'] = $count;
 
+               if (!empty($page)) {
+                       $data['id'] .= '?' . http_build_query(['page' => $page]);
+               }
+
                if (empty($page)) {
                        $data['first'] = DI::baseUrl() . '/outbox/' . $owner['nickname'] . '?page=1';
                } else {
@@ -276,7 +313,7 @@ class Transmitter
                        }
                        DBA::close($items);
 
-                       if (!empty($list)) {
+                       if (count($list) == 20) {
                                $data['next'] = DI::baseUrl() . '/outbox/' . $owner['nickname'] . '?page=' . ($page + 1);
                        }
 
@@ -285,6 +322,94 @@ class Transmitter
                        $data['orderedItems'] = $list;
                }
 
+               if (!empty($cachekey)) {
+                       DI::cache()->set($cachekey, $data, Duration::DAY);
+               }
+
+               return $data;
+       }
+
+       /**
+        * Public posts for the given owner
+        *
+        * @param array   $owner   Owner array
+        * @param integer $page    Page number
+        * @param boolean $nocache Wether to bypass caching
+        *
+        * @return array of posts
+        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+        * @throws \ImagickException
+        */
+       public static function getFeatured(array $owner, int $page = null, $nocache = false)
+       {
+               if (empty($page)) {
+                       $cachekey = self::CACHEKEY_FEATURED . $owner['uid'];
+                       $result = DI::cache()->get($cachekey);
+                       if (!$nocache && !is_null($result)) {
+                               return $result;
+                       }
+               }
+
+               $owner_cid = Contact::getIdForURL($owner['url'], 0, false);
+
+               $condition = ["`uri-id` IN (SELECT `uri-id` FROM `collection-view` WHERE `cid` = ? AND `type` = ?)",
+                       $owner_cid, Post\Collection::FEATURED];
+
+               $condition = DBA::mergeConditions($condition,
+                       ['uid'           => $owner['uid'],
+                       'author-id'      => $owner_cid,
+                       'private'        => [Item::PUBLIC, Item::UNLISTED],
+                       'gravity'        => [GRAVITY_PARENT, GRAVITY_COMMENT],
+                       'network'        => Protocol::FEDERATED,
+                       'parent-network' => Protocol::FEDERATED,
+                       'origin'         => true,
+                       'deleted'        => false,
+                       'visible'        => true]);
+
+               $count = Post::count($condition);
+
+               $data = ['@context' => ActivityPub::CONTEXT];
+               $data['id'] = DI::baseUrl() . '/featured/' . $owner['nickname'];
+               $data['type'] = 'OrderedCollection';
+               $data['totalItems'] = $count;
+
+               if (!empty($page)) {
+                       $data['id'] .= '?' . http_build_query(['page' => $page]);
+               }
+
+               if (empty($page)) {
+                       $items = Post::select(['id'], $condition, ['limit' => 20, 'order' => ['created' => true]]);
+               } else {
+                       $data['type'] = 'OrderedCollectionPage';
+                       $items = Post::select(['id'], $condition, ['limit' => [($page - 1) * 20, 20], 'order' => ['created' => true]]);
+               }
+               $list = [];
+
+               while ($item = Post::fetch($items)) {
+                       $activity = self::createActivityFromItem($item['id'], true);
+                       $activity['type'] = $activity['type'] == 'Update' ? 'Create' : $activity['type'];
+
+                       // Only list "Create" activity objects here, no reshares
+                       if (!empty($activity['object']) && ($activity['type'] == 'Create')) {
+                               $list[] = $activity['object'];
+                       }
+               }
+               DBA::close($items);
+
+               if (count($list) == 20) {
+                       $data['next'] = DI::baseUrl() . '/featured/' . $owner['nickname'] . '?page=' . ($page + 1);
+               }
+
+               if (!empty($page)) {
+                       $data['partOf'] = DI::baseUrl() . '/featured/' . $owner['nickname'];
+               }
+
+               $data['orderedItems'] = $list;
+
+               if (!empty($cachekey)) {
+                       DI::cache()->set($cachekey, $data, Duration::DAY);
+               }
+
                return $data;
        }
 
@@ -328,8 +453,9 @@ class Transmitter
                if ($uid != 0) {
                        $data['following'] = DI::baseUrl() . '/following/' . $owner['nick'];
                        $data['followers'] = DI::baseUrl() . '/followers/' . $owner['nick'];
-                       $data['inbox'] = DI::baseUrl() . '/inbox/' . $owner['nick'];
-                       $data['outbox'] = DI::baseUrl() . '/outbox/' . $owner['nick'];
+                       $data['inbox']     = DI::baseUrl() . '/inbox/' . $owner['nick'];
+                       $data['outbox']    = DI::baseUrl() . '/outbox/' . $owner['nick'];
+                       $data['featured']  = DI::baseUrl() . '/featured/' . $owner['nick'];
                } else {
                        $data['inbox'] = DI::baseUrl() . '/friendica/inbox';
                }
@@ -1165,6 +1291,7 @@ class Transmitter
 
                if (in_array($data['type'], ['Create', 'Update', 'Delete'])) {
                        $data['object'] = $object ?? self::createNote($item);
+                       $data['published'] = DateTimeFormat::utcNow(DateTimeFormat::ATOM);
                } elseif ($data['type'] == 'Add') {
                        $data = self::createAddTag($item, $data);
                } elseif ($data['type'] == 'Announce') {