diff --git a/src/Factory/Api/Mastodon/StatusSource.php b/src/Factory/Api/Mastodon/StatusSource.php index 13d6145ca6..170b66e1b0 100644 --- a/src/Factory/Api/Mastodon/StatusSource.php +++ b/src/Factory/Api/Mastodon/StatusSource.php @@ -38,7 +38,7 @@ class StatusSource extends BaseFactory */ public function createFromUriId(int $uriId, int $uid): \Friendica\Object\Api\Mastodon\StatusSource { - $post = Post::selectFirst(['uri-id', 'raw-body', 'body', 'title'], ['uri-id' => $uriId, 'uid' => [0, $uid]]); + $post = Post::selectOriginal(['uri-id', 'raw-body', 'body', 'title'], ['uri-id' => $uriId, 'uid' => [0, $uid]]); $spoiler_text = $post['title'] ?: BBCode::toPlaintext(BBCode::getAbstract($post['body'], Protocol::ACTIVITYPUB)); $body = BBCode::toMarkdown(Post\Media::removeFromEndOfBody($post['body'])); diff --git a/src/Model/Post.php b/src/Model/Post.php index 062f22db9c..770ab08317 100644 --- a/src/Model/Post.php +++ b/src/Model/Post.php @@ -226,6 +226,46 @@ class Post } } + /** + * Retrieve a single record from the post-user-view view and returns it in an associative array + * When the requested record is a reshare activity, the system fetches the reshared original post. + * Otherwise the function reacts similar to selectFirst + * + * @param array $fields + * @param array $condition + * @param array $params + * @param bool $user_mode true = post-user-view, false = post-view + * @return bool|array + * @throws \Exception + * @see DBA::select + */ + public static function selectOriginal(array $fields = [], array $condition = [], array $params = []) + { + $original_fields = $fields; + $remove = []; + if (!empty($fields)) { + foreach (['gravity', 'verb', 'thr-parent-id', 'uid'] as $field) { + if (!in_array($field, $fields)) { + $fields[] = $field; + $remove[] = $field; + } + } + } + $result = self::selectFirst($fields, $condition, $params); + if (empty($result)) { + return $result; + } + + if (($result['gravity'] != Item::GRAVITY_ACTIVITY) || ($result['verb'] != Activity::ANNOUNCE)) { + foreach ($remove as $field) { + unset($result[$field]); + } + return $result; + } + + return self::selectFirst($original_fields, ['uri-id' => $result['thr-parent-id'], 'uid' => [0, $result['uid']]], $params); + } + /** * Retrieve a single record from the post-view view and returns it in an associative array * @@ -505,6 +545,46 @@ class Post } } + /** + * Retrieve a single record from the post-user-view view for a given user and returns it in an associative array + * When the requested record is a reshare activity, the system fetches the reshared original post. + * Otherwise the function reacts similar to selectFirstForUser + * + * @param integer $uid User ID + * @param array $selected + * @param array $condition + * @param array $params + * @return bool|array + * @throws \Exception + * @see DBA::select + */ + public static function selectOriginalForUser(int $uid, array $selected = [], array $condition = [], array $params = []) + { + $original_selected = $selected; + $remove = []; + if (!empty($selected)) { + foreach (['gravity', 'verb', 'thr-parent-id'] as $field) { + if (!in_array($field, $selected)) { + $selected[] = $field; + $remove[] = $field; + } + } + } + $result = self::selectFirstForUser($uid, $selected, $condition, $params); + if (empty($result)) { + return $result; + } + + if (($result['gravity'] != Item::GRAVITY_ACTIVITY) || ($result['verb'] != Activity::ANNOUNCE)) { + foreach ($remove as $field) { + unset($result[$field]); + } + return $result; + } + + return self::selectFirstForUser($uid, $original_selected, ['uri-id' => $result['thr-parent-id'], 'uid' => [0, $uid]], $params); + } + /** * Update existing post entries * diff --git a/src/Module/Api/Mastodon/Statuses.php b/src/Module/Api/Mastodon/Statuses.php index a232112de8..72641235d7 100644 --- a/src/Module/Api/Mastodon/Statuses.php +++ b/src/Module/Api/Mastodon/Statuses.php @@ -268,7 +268,7 @@ class Statuses extends BaseApi } if ($request['in_reply_to_id']) { - $parent = Post::selectFirst(['uri'], ['uri-id' => $request['in_reply_to_id'], 'uid' => [0, $uid]]); + $parent = Post::selectOriginal(['uri'], ['uri-id' => $request['in_reply_to_id'], 'uid' => [0, $uid]]); if (empty($parent)) { throw new HTTPException\NotFoundException('Item with URI ID ' . $request['in_reply_to_id'] . ' not found for user ' . $uid . '.'); } diff --git a/src/Module/Api/Mastodon/Statuses/Bookmark.php b/src/Module/Api/Mastodon/Statuses/Bookmark.php index b5e8a540d0..255b459c33 100644 --- a/src/Module/Api/Mastodon/Statuses/Bookmark.php +++ b/src/Module/Api/Mastodon/Statuses/Bookmark.php @@ -42,7 +42,7 @@ class Bookmark extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $item = Post::selectFirst(['uid', 'id', 'gravity'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]], ['order' => ['uid' => true]]); + $item = Post::selectOriginal(['uid', 'id', 'gravity'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]], ['order' => ['uid' => true]]); if (!DBA::isResult($item)) { DI::mstdnError()->RecordNotFound(); } @@ -52,7 +52,7 @@ class Bookmark extends BaseApi } if ($item['uid'] == 0) { - $stored = Item::storeForUserByUriId($this->parameters['id'], $uid, ['post-reason' => Item::PR_ACTIVITY]); + $stored = Item::storeForUserByUriId($item['id'], $uid, ['post-reason' => Item::PR_ACTIVITY]); if (!empty($stored)) { $item = Post::selectFirst(['id', 'gravity'], ['id' => $stored]); if (!DBA::isResult($item)) { diff --git a/src/Module/Api/Mastodon/Statuses/Card.php b/src/Module/Api/Mastodon/Statuses/Card.php index e1012d8ec3..6d29ee879e 100644 --- a/src/Module/Api/Mastodon/Statuses/Card.php +++ b/src/Module/Api/Mastodon/Statuses/Card.php @@ -43,13 +43,11 @@ class Card extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $id = $this->parameters['id']; - - if (!Post::exists(['uri-id' => $id, 'uid' => [0, $uid]])) { - throw new HTTPException\NotFoundException('Item with URI ID ' . $id . ' not found' . ($uid ? ' for user ' . $uid : '.')); + if (!$post = Post::selectOriginal(['id'], ['uri-id' => $this->parameters['id'], 'uid' => [0, $uid]])) { + throw new HTTPException\NotFoundException('Item with URI ID ' . $this->parameters['id'] . ' not found' . ($uid ? ' for user ' . $uid : '.')); } - $card = DI::mstdnCard()->createFromUriId($id); + $card = DI::mstdnCard()->createFromUriId($post['id']); System::jsonExit($card->toArray()); } diff --git a/src/Module/Api/Mastodon/Statuses/Context.php b/src/Module/Api/Mastodon/Statuses/Context.php index f683b01751..0b2e7bda6d 100644 --- a/src/Module/Api/Mastodon/Statuses/Context.php +++ b/src/Module/Api/Mastodon/Statuses/Context.php @@ -57,8 +57,9 @@ class Context extends BaseApi $parents = []; $children = []; - $parent = Post::selectFirst(['parent-uri-id'], ['uri-id' => $id]); + $parent = Post::selectOriginal(['uri-id', 'parent-uri-id'], ['uri-id' => $id]); if (DBA::isResult($parent)) { + $id = $parent['uri-id']; $params = ['order' => ['uri-id' => true]]; $condition = ['parent-uri-id' => $parent['parent-uri-id'], 'gravity' => [Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT]]; diff --git a/src/Module/Api/Mastodon/Statuses/Favourite.php b/src/Module/Api/Mastodon/Statuses/Favourite.php index de4c0feec0..d1a68862ca 100644 --- a/src/Module/Api/Mastodon/Statuses/Favourite.php +++ b/src/Module/Api/Mastodon/Statuses/Favourite.php @@ -42,7 +42,7 @@ class Favourite extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $item = Post::selectFirstForUser($uid, ['id'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); + $item = Post::selectOriginalForUser($uid, ['id'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); if (!DBA::isResult($item)) { DI::mstdnError()->RecordNotFound(); } diff --git a/src/Module/Api/Mastodon/Statuses/FavouritedBy.php b/src/Module/Api/Mastodon/Statuses/FavouritedBy.php index 8f9fe02f17..326e48d823 100644 --- a/src/Module/Api/Mastodon/Statuses/FavouritedBy.php +++ b/src/Module/Api/Mastodon/Statuses/FavouritedBy.php @@ -44,12 +44,11 @@ class FavouritedBy extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $id = $this->parameters['id']; - if (!Post::exists(['uri-id' => $id, 'uid' => [0, $uid]])) { + if (!$post = Post::selectOriginal(['id'], ['uri-id' => $this->parameters['id'], 'uid' => [0, $uid]])) { DI::mstdnError()->RecordNotFound(); } - $activities = Post::selectPosts(['author-id'], ['thr-parent-id' => $id, 'gravity' => Item::GRAVITY_ACTIVITY, 'verb' => Activity::LIKE, 'deleted' => false]); + $activities = Post::selectPosts(['author-id'], ['thr-parent-id' => $post['id'], 'gravity' => Item::GRAVITY_ACTIVITY, 'verb' => Activity::LIKE, 'deleted' => false]); $accounts = []; diff --git a/src/Module/Api/Mastodon/Statuses/Mute.php b/src/Module/Api/Mastodon/Statuses/Mute.php index fa6cd120e9..0c1068490c 100644 --- a/src/Module/Api/Mastodon/Statuses/Mute.php +++ b/src/Module/Api/Mastodon/Statuses/Mute.php @@ -42,7 +42,7 @@ class Mute extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $item = Post::selectFirstForUser($uid, ['id', 'gravity'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); + $item = Post::selectOriginalForUser($uid, ['id', 'gravity'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); if (!DBA::isResult($item)) { DI::mstdnError()->RecordNotFound(); } @@ -51,7 +51,7 @@ class Mute extends BaseApi DI::mstdnError()->UnprocessableEntity(DI::l10n()->t('Only starting posts can be muted')); } - Post\ThreadUser::setIgnored($this->parameters['id'], $uid, true); + Post\ThreadUser::setIgnored($item['id'], $uid, true); System::jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes())->toArray()); } diff --git a/src/Module/Api/Mastodon/Statuses/Pin.php b/src/Module/Api/Mastodon/Statuses/Pin.php index aa692c6b76..d092b4255f 100644 --- a/src/Module/Api/Mastodon/Statuses/Pin.php +++ b/src/Module/Api/Mastodon/Statuses/Pin.php @@ -41,12 +41,12 @@ class Pin extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $item = Post::selectFirstForUser($uid, ['id', 'gravity', 'author-id'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); + $item = Post::selectOriginalForUser($uid, ['id', 'gravity', 'author-id'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); if (!DBA::isResult($item)) { DI::mstdnError()->RecordNotFound(); } - Post\Collection::add($this->parameters['id'], Post\Collection::FEATURED, $item['author-id'], $uid); + Post\Collection::add($item['id'], Post\Collection::FEATURED, $item['author-id'], $uid); System::jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes())->toArray()); } diff --git a/src/Module/Api/Mastodon/Statuses/Reblog.php b/src/Module/Api/Mastodon/Statuses/Reblog.php index 254144df98..f1922d7271 100644 --- a/src/Module/Api/Mastodon/Statuses/Reblog.php +++ b/src/Module/Api/Mastodon/Statuses/Reblog.php @@ -45,7 +45,7 @@ class Reblog extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $item = Post::selectFirstForUser($uid, ['id', 'network'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); + $item = Post::selectOriginalForUser($uid, ['id', 'network'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); if (!DBA::isResult($item)) { DI::mstdnError()->RecordNotFound(); } diff --git a/src/Module/Api/Mastodon/Statuses/RebloggedBy.php b/src/Module/Api/Mastodon/Statuses/RebloggedBy.php index d247a28566..b225d17439 100644 --- a/src/Module/Api/Mastodon/Statuses/RebloggedBy.php +++ b/src/Module/Api/Mastodon/Statuses/RebloggedBy.php @@ -44,12 +44,11 @@ class RebloggedBy extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $id = $this->parameters['id']; - if (!Post::exists(['uri-id' => $id, 'uid' => [0, $uid]])) { + if (!$post = Post::selectOriginal(['id'], ['uri-id' => $this->parameters['id'], 'uid' => [0, $uid]])) { DI::mstdnError()->RecordNotFound(); } - $activities = Post::selectPosts(['author-id'], ['thr-parent-id' => $id, 'gravity' => Item::GRAVITY_ACTIVITY, 'verb' => Activity::ANNOUNCE]); + $activities = Post::selectPosts(['author-id'], ['thr-parent-id' => $post['id'], 'gravity' => Item::GRAVITY_ACTIVITY, 'verb' => Activity::ANNOUNCE]); $accounts = []; diff --git a/src/Module/Api/Mastodon/Statuses/Unbookmark.php b/src/Module/Api/Mastodon/Statuses/Unbookmark.php index dd6a59fed2..4f6db11fd3 100644 --- a/src/Module/Api/Mastodon/Statuses/Unbookmark.php +++ b/src/Module/Api/Mastodon/Statuses/Unbookmark.php @@ -42,7 +42,7 @@ class Unbookmark extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $item = Post::selectFirst(['uid', 'id', 'gravity'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]], ['order' => ['uid' => true]]); + $item = Post::selectOriginal(['uid', 'id', 'gravity'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]], ['order' => ['uid' => true]]); if (!DBA::isResult($item)) { DI::mstdnError()->RecordNotFound(); } @@ -52,7 +52,7 @@ class Unbookmark extends BaseApi } if ($item['uid'] == 0) { - $stored = Item::storeForUserByUriId($this->parameters['id'], $uid, ['post-reason' => Item::PR_ACTIVITY]); + $stored = Item::storeForUserByUriId($item['id'], $uid, ['post-reason' => Item::PR_ACTIVITY]); if (!empty($stored)) { $item = Post::selectFirst(['id', 'gravity'], ['id' => $stored]); if (!DBA::isResult($item)) { diff --git a/src/Module/Api/Mastodon/Statuses/Unfavourite.php b/src/Module/Api/Mastodon/Statuses/Unfavourite.php index 06b5c6c615..a3760b4544 100644 --- a/src/Module/Api/Mastodon/Statuses/Unfavourite.php +++ b/src/Module/Api/Mastodon/Statuses/Unfavourite.php @@ -42,7 +42,7 @@ class Unfavourite extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $item = Post::selectFirstForUser($uid, ['id'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); + $item = Post::selectOriginalForUser($uid, ['id'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); if (!DBA::isResult($item)) { DI::mstdnError()->RecordNotFound(); } diff --git a/src/Module/Api/Mastodon/Statuses/Unmute.php b/src/Module/Api/Mastodon/Statuses/Unmute.php index 658b6be8ba..b7a24beed2 100644 --- a/src/Module/Api/Mastodon/Statuses/Unmute.php +++ b/src/Module/Api/Mastodon/Statuses/Unmute.php @@ -42,7 +42,7 @@ class Unmute extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $item = Post::selectFirstForUser($uid, ['id', 'gravity'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); + $item = Post::selectOriginalForUser($uid, ['id', 'gravity'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); if (!DBA::isResult($item)) { DI::mstdnError()->RecordNotFound(); } @@ -51,7 +51,7 @@ class Unmute extends BaseApi DI::mstdnError()->UnprocessableEntity(DI::l10n()->t('Only starting posts can be unmuted')); } - Post\ThreadUser::setIgnored($this->parameters['id'], $uid, false); + Post\ThreadUser::setIgnored($item['id'], $uid, false); System::jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes())->toArray()); } diff --git a/src/Module/Api/Mastodon/Statuses/Unpin.php b/src/Module/Api/Mastodon/Statuses/Unpin.php index f9efcdee66..523ce4d554 100644 --- a/src/Module/Api/Mastodon/Statuses/Unpin.php +++ b/src/Module/Api/Mastodon/Statuses/Unpin.php @@ -41,12 +41,12 @@ class Unpin extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $item = Post::selectFirstForUser($uid, ['id', 'gravity'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); + $item = Post::selectOriginalForUser($uid, ['id', 'gravity'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); if (!DBA::isResult($item)) { DI::mstdnError()->RecordNotFound(); } - Post\Collection::remove($this->parameters['id'], Post\Collection::FEATURED, $uid); + Post\Collection::remove($item['id'], Post\Collection::FEATURED, $uid); System::jsonExit(DI::mstdnStatus()->createFromUriId($this->parameters['id'], $uid, self::appSupportsQuotes())->toArray()); } diff --git a/src/Module/Api/Mastodon/Statuses/Unreblog.php b/src/Module/Api/Mastodon/Statuses/Unreblog.php index 94de3e9c6a..54a18823a7 100644 --- a/src/Module/Api/Mastodon/Statuses/Unreblog.php +++ b/src/Module/Api/Mastodon/Statuses/Unreblog.php @@ -44,7 +44,7 @@ class Unreblog extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - $item = Post::selectFirstForUser($uid, ['id', 'network'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); + $item = Post::selectOriginalForUser($uid, ['id', 'network'], ['uri-id' => $this->parameters['id'], 'uid' => [$uid, 0]]); if (!DBA::isResult($item)) { DI::mstdnError()->RecordNotFound(); }