diff --git a/src/Factory/Api/Mastodon/Status.php b/src/Factory/Api/Mastodon/Status.php index 19f3866cd4..642c9efe83 100644 --- a/src/Factory/Api/Mastodon/Status.php +++ b/src/Factory/Api/Mastodon/Status.php @@ -99,7 +99,7 @@ class Status extends BaseFactory public function createFromUriId(int $uriId, int $uid = 0, bool $display_quote = false, bool $reblog = true, bool $in_reply_status = true): \Friendica\Object\Api\Mastodon\Status { $fields = ['uri-id', 'uid', 'author-id', 'causer-id', 'author-uri-id', 'author-link', 'causer-uri-id', 'post-reason', 'starred', 'app', 'title', 'body', 'raw-body', 'content-warning', 'question-id', - 'created', 'network', 'thr-parent-id', 'parent-author-id', 'language', 'uri', 'plink', 'private', 'vid', 'gravity', 'featured', 'has-media', 'quote-uri-id', + 'created', 'edited', 'commented', 'received', 'changed', 'network', 'thr-parent-id', 'parent-author-id', 'language', 'uri', 'plink', 'private', 'vid', 'gravity', 'featured', 'has-media', 'quote-uri-id', 'delivery_queue_count', 'delivery_queue_done','delivery_queue_failed']; $item = Post::selectFirst($fields, ['uri-id' => $uriId, 'uid' => [0, $uid]], ['order' => ['uid' => true]]); if (!$item) { @@ -289,7 +289,7 @@ class Status extends BaseFactory } $delivery_data = new FriendicaDeliveryData($item['delivery_queue_count'], $item['delivery_queue_done'], $item['delivery_queue_failed']); - $friendica = new FriendicaExtension($item['title'], $counts->dislikes, $delivery_data); + $friendica = new FriendicaExtension($item['title'], $item['changed'], $item['commented'], $item['edited'], $item['received'], $counts->dislikes, $delivery_data); return new \Friendica\Object\Api\Mastodon\Status($item, $account, $counts, $userAttributes, $sensitive, $application, $mentions, $tags, $card, $attachments, $in_reply, $reshare, $friendica, $quote, $poll); } @@ -355,7 +355,7 @@ class Status extends BaseFactory $attachments = []; $in_reply = []; $reshare = []; - $friendica = new FriendicaExtension('', 0, new FriendicaDeliveryData(0, 0, 0)); + $friendica = new FriendicaExtension('', null, null, null, null, 0, new FriendicaDeliveryData(0, 0, 0)); return new \Friendica\Object\Api\Mastodon\Status($item, $account, $counts, $userAttributes, $sensitive, $application, $mentions, $tags, $card, $attachments, $in_reply, $reshare, $friendica); } diff --git a/src/Module/Api/Mastodon/Timelines/Home.php b/src/Module/Api/Mastodon/Timelines/Home.php index 7fc179297c..6d0b7a3340 100644 --- a/src/Module/Api/Mastodon/Timelines/Home.php +++ b/src/Module/Api/Mastodon/Timelines/Home.php @@ -29,6 +29,7 @@ use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException; +use Friendica\Object\Api\Mastodon\TimelineOrderByTypes; /** * @see https://docs.joinmastodon.org/methods/timelines/ @@ -44,39 +45,27 @@ class Home extends BaseApi $uid = self::getCurrentUserID(); $request = $this->getRequest([ - 'max_id' => 0, // Return results older than id - 'since_id' => 0, // Return results newer than id - 'min_id' => 0, // Return results immediately newer than id + 'max_id' => null, // Return results older than id + 'since_id' => null, // Return results newer than id + 'min_id' => null, // Return results immediately newer than id 'limit' => 20, // Maximum number of results to return. Defaults to 20. 'local' => false, // Return only local statuses? 'with_muted' => false, // Pleroma extension: return activities by muted (not by blocked!) users. 'only_media' => false, // Show only statuses with media attached? Defaults to false. 'remote' => false, // Show only remote statuses? Defaults to false. 'exclude_replies' => false, // Don't show comments + 'friendica_order' => TimelineOrderByTypes::ID, // Sort order options (defaults to ID) ], $request); - $params = ['order' => ['uri-id' => true], 'limit' => $request['limit']]; - $condition = ['gravity' => [Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT], 'uid' => $uid]; + $condition = $this->addPagingConditions($request, $condition); + $params = $this->buildOrderAndLimitParams($request); + if ($request['local']) { $condition = DBA::mergeConditions($condition, ["`uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `origin`)"]); } - if (!empty($request['max_id'])) { - $condition = DBA::mergeConditions($condition, ["`uri-id` < ?", $request['max_id']]); - } - - if (!empty($request['since_id'])) { - $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", $request['since_id']]); - } - - if (!empty($request['min_id'])) { - $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", $request['min_id']]); - - $params['order'] = ['uri-id']; - } - if ($request['only_media']) { $condition = DBA::mergeConditions($condition, ["`uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?))", Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO]); @@ -96,11 +85,12 @@ class Home extends BaseApi $statuses = []; while ($item = Post::fetch($items)) { - self::setBoundaries($item['uri-id']); try { - $statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); - } catch (\Exception $exception) { - Logger::info('Post not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'exception' => $exception]); + $status = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); + $this->updateBoundaries($status, $item, $request['friendica_order']); + $statuses[] = $status; + } catch (\Throwable $th) { + Logger::info('Post not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'error' => $th]); } } DBA::close($items); @@ -109,7 +99,8 @@ class Home extends BaseApi $statuses = array_reverse($statuses); } - self::setLinkHeader(); + + self::setLinkHeader($request['friendica_order'] != TimelineOrderByTypes::ID); System::jsonExit($statuses); } } diff --git a/src/Module/Api/Mastodon/Timelines/ListTimeline.php b/src/Module/Api/Mastodon/Timelines/ListTimeline.php index 1e9a5810c1..eeffeba885 100644 --- a/src/Module/Api/Mastodon/Timelines/ListTimeline.php +++ b/src/Module/Api/Mastodon/Timelines/ListTimeline.php @@ -29,6 +29,7 @@ use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException; +use Friendica\Object\Api\Mastodon\TimelineOrderByTypes; /** * @see https://docs.joinmastodon.org/methods/timelines/ @@ -48,35 +49,23 @@ class ListTimeline extends BaseApi } $request = $this->getRequest([ - 'max_id' => 0, // Return results older than id - 'since_id' => 0, // Return results newer than id - 'min_id' => 0, // Return results immediately newer than id + 'max_id' => null, // Return results older than id + 'since_id' => null, // Return results newer than id + 'min_id' => null, // Return results immediately newer than id 'limit' => 20, // Maximum number of results to return. Defaults to 20.Return results older than this ID. 'with_muted' => false, // Pleroma extension: return activities by muted (not by blocked!) users. 'only_media' => false, // Show only statuses with media attached? Defaults to false. 'local' => false, // Show only local statuses? Defaults to false. 'remote' => false, // Show only remote statuses? Defaults to false. 'exclude_replies' => false, // Don't show comments + 'friendica_order' => TimelineOrderByTypes::ID, // Sort order options (defaults to ID) ], $request); - $params = ['order' => ['uri-id' => true], 'limit' => $request['limit']]; - $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `contact-id` IN (SELECT `contact-id` FROM `group_member` WHERE `gid` = ?)", $uid, Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT, $this->parameters['id']]; - if (!empty($request['max_id'])) { - $condition = DBA::mergeConditions($condition, ["`uri-id` < ?", $request['max_id']]); - } - - if (!empty($request['since_id'])) { - $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", $request['since_id']]); - } - - if (!empty($request['min_id'])) { - $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", $request['min_id']]); - - $params['order'] = ['uri-id']; - } + $condition = $this->addPagingConditions($request, $condition); + $params = $this->buildOrderAndLimitParams($request); if ($request['only_media']) { $condition = DBA::mergeConditions($condition, ["`uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?))", @@ -101,11 +90,12 @@ class ListTimeline extends BaseApi $statuses = []; while ($item = Post::fetch($items)) { - self::setBoundaries($item['uri-id']); try { - $statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); - } catch (\Exception $exception) { - Logger::info('Post not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'exception' => $exception]); + $status = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); + $this->updateBoundaries($status, $item, $request['friendica_order']); + $statuses[] = $status; + } catch (\Throwable $th) { + Logger::info('Post not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'error' => $th]); } } DBA::close($items); diff --git a/src/Module/Api/Mastodon/Timelines/PublicTimeline.php b/src/Module/Api/Mastodon/Timelines/PublicTimeline.php index 31750d4a5c..1f58a6a69f 100644 --- a/src/Module/Api/Mastodon/Timelines/PublicTimeline.php +++ b/src/Module/Api/Mastodon/Timelines/PublicTimeline.php @@ -30,6 +30,7 @@ use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException; +use Friendica\Object\Api\Mastodon\TimelineOrderByTypes; /** * @see https://docs.joinmastodon.org/methods/timelines/ @@ -44,22 +45,24 @@ class PublicTimeline extends BaseApi $uid = self::getCurrentUserID(); $request = $this->getRequest([ + 'max_id' => null, // Return results older than id + 'since_id' => null, // Return results newer than id + 'min_id' => null, // Return results immediately newer than id + 'limit' => 20, // Maximum number of results to return. Defaults to 20. 'local' => false, // Show only local statuses? Defaults to false. 'remote' => false, // Show only remote statuses? Defaults to false. 'only_media' => false, // Show only statuses with media attached? Defaults to false. - 'max_id' => 0, // Return results older than this id - 'since_id' => 0, // Return results newer than this id - 'min_id' => 0, // Return results immediately newer than this id - 'limit' => 20, // Maximum number of results to return. Defaults to 20. 'with_muted' => false, // Pleroma extension: return activities by muted (not by blocked!) users. 'exclude_replies' => false, // Don't show comments + 'friendica_order' => TimelineOrderByTypes::ID, // Sort order options (defaults to ID) ], $request); - $params = ['order' => ['uri-id' => true], 'limit' => $request['limit']]; - $condition = ['gravity' => [Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT], 'private' => Item::PUBLIC, 'network' => Protocol::FEDERATED, 'author-blocked' => false, 'author-hidden' => false]; + $condition = $this->addPagingConditions($request, $condition); + $params = $this->buildOrderAndLimitParams($request); + if ($request['local']) { $condition = DBA::mergeConditions($condition, ["`uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `origin`)"]); } @@ -73,19 +76,6 @@ class PublicTimeline extends BaseApi Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO]); } - if (!empty($request['max_id'])) { - $condition = DBA::mergeConditions($condition, ["`uri-id` < ?", $request['max_id']]); - } - - if (!empty($request['since_id'])) { - $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", $request['since_id']]); - } - - if (!empty($request['min_id'])) { - $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", $request['min_id']]); - $params['order'] = ['uri-id']; - } - if ($request['exclude_replies']) { $condition = DBA::mergeConditions($condition, ['gravity' => Item::GRAVITY_PARENT]); } @@ -96,13 +86,15 @@ class PublicTimeline extends BaseApi $statuses = []; while ($item = Post::fetch($items)) { - self::setBoundaries($item['uri-id']); try { - $statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); - } catch (\Exception $exception) { - Logger::info('Post not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'exception' => $exception]); + $status = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, $display_quotes); + $this->updateBoundaries($status, $item, $request['friendica_order']); + $statuses[] = $status; + } catch (\Throwable $th) { + Logger::info('Post not fetchable', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'error' => $th]); } } + DBA::close($items); if (!empty($request['min_id'])) { diff --git a/src/Module/Api/Mastodon/Timelines/Tag.php b/src/Module/Api/Mastodon/Timelines/Tag.php index 476c9c2b94..4943b51b07 100644 --- a/src/Module/Api/Mastodon/Timelines/Tag.php +++ b/src/Module/Api/Mastodon/Timelines/Tag.php @@ -107,7 +107,7 @@ class Tag extends BaseApi if (!empty($uid)) { $condition = DBA::mergeConditions( $condition, - ["NOT `parent-author-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND (`blocked` OR `ignored`) AND `cid` = `parent-author-id`)", $uid] + ["NOT `author-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND (`blocked` OR `ignored`) AND `cid` = `author-id`)", $uid] ); } diff --git a/src/Module/BaseApi.php b/src/Module/BaseApi.php index f8524b524e..10e64044f3 100644 --- a/src/Module/BaseApi.php +++ b/src/Module/BaseApi.php @@ -21,12 +21,14 @@ namespace Friendica\Module; +use DateTime; use Friendica\App; use Friendica\App\Router; use Friendica\BaseModule; use Friendica\Core\L10n; use Friendica\Core\Logger; use Friendica\Core\System; +use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; use Friendica\Model\Item; @@ -35,6 +37,8 @@ use Friendica\Model\User; use Friendica\Module\Api\ApiResponse; use Friendica\Module\Special\HTTPException as ModuleHTTPException; use Friendica\Network\HTTPException; +use Friendica\Object\Api\Mastodon\Status; +use Friendica\Object\Api\Mastodon\TimelineOrderByTypes; use Friendica\Security\BasicAuth; use Friendica\Security\OAuth; use Friendica\Util\DateTimeFormat; @@ -101,6 +105,140 @@ class BaseApi extends BaseModule return parent::run($httpException, $request); } + /** + * Processes data from GET requests and sets paging conditions + * + * @param array $request Custom REQUEST array + * @param array $condition Existing conditions to merge + * @return array paging data condition parameters data + * @throws \Exception + */ + protected function addPagingConditions(array $request, array $condition): array + { + $requested_order = $request['friendica_order']; + if ($requested_order == TimelineOrderByTypes::ID) { + if (!empty($request['max_id'])) { + $condition = DBA::mergeConditions($condition, ["`uri-id` < ?", intval($request['max_id'])]); + } + + if (!empty($request['since_id'])) { + $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", intval($request['since_id'])]); + } + + if (!empty($request['min_id'])) { + $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", intval($request['min_id'])]); + } + } else { + switch ($requested_order) { + case TimelineOrderByTypes::RECEIVED: + case TimelineOrderByTypes::CHANGED: + case TimelineOrderByTypes::EDITED: + case TimelineOrderByTypes::CREATED: + case TimelineOrderByTypes::COMMENTED: + $order_field = $requested_order; + break; + default: + throw new \Exception("Unrecognized request order: $requested_order"); + } + + if (!empty($request['max_id'])) { + $condition = DBA::mergeConditions($condition, ["`$order_field` < ?", DateTimeFormat::convert($request['max_id'], DateTimeFormat::MYSQL)]); + } + + if (!empty($request['since_id'])) { + $condition = DBA::mergeConditions($condition, ["`$order_field` > ?", DateTimeFormat::convert($request['since_id'], DateTimeFormat::MYSQL)]); + } + + if (!empty($request['min_id'])) { + $condition = DBA::mergeConditions($condition, ["`$order_field` > ?", DateTimeFormat::convert($request['min_id'], DateTimeFormat::MYSQL)]); + } + } + + return $condition; + } + + /** + * Processes data from GET requests and sets paging conditions + * + * @param array $request Custom REQUEST array + * @param array $params Existing $params element to build on + * @return array ordering data added to the params blocks that was passed in + * @throws \Exception + */ + protected function buildOrderAndLimitParams(array $request, array $params = []): array + { + $requested_order = $request['friendica_order']; + switch ($requested_order) { + case TimelineOrderByTypes::CHANGED: + case TimelineOrderByTypes::CREATED: + case TimelineOrderByTypes::COMMENTED: + case TimelineOrderByTypes::EDITED: + case TimelineOrderByTypes::RECEIVED: + $order_field = $requested_order; + break; + case TimelineOrderByTypes::ID: + default: + $order_field = 'uri-id'; + } + + if (!empty($request['min_id'])) { + $params['order'] = [$order_field]; + } else { + $params['order'] = [$order_field => true]; + } + + $params['limit'] = $request['limit']; + + return $params; + } + + /** + * Update the ID/time boundaries for this result set. Used for building Link Headers + * + * @param Status $status + * @param array $post_item + * @param string $order + * @return void + * @throws \Exception + */ + protected function updateBoundaries(Status $status, array $post_item, string $order) + { + try { + switch ($order) { + case TimelineOrderByTypes::CHANGED: + if (!empty($status->friendicaExtension()->changedAt())) { + self::setBoundaries(new DateTime(DateTimeFormat::utc($status->friendicaExtension()->changedAt(), DateTimeFormat::JSON))); + } + break; + case TimelineOrderByTypes::CREATED: + if (!empty($status->createdAt())) { + self::setBoundaries(new DateTime(DateTimeFormat::utc($status->createdAt(), DateTimeFormat::JSON))); + } + break; + case TimelineOrderByTypes::COMMENTED: + if (!empty($status->friendicaExtension()->commentedAt())) { + self::setBoundaries(new DateTime(DateTimeFormat::utc($status->friendicaExtension()->commentedAt(), DateTimeFormat::JSON))); + } + break; + case TimelineOrderByTypes::EDITED: + if (!empty($status->friendicaExtension()->editedAt())) { + self::setBoundaries(new DateTime(DateTimeFormat::utc($status->friendicaExtension()->editedAt(), DateTimeFormat::JSON))); + } + break; + case TimelineOrderByTypes::RECEIVED: + if (!empty($status->friendicaExtension()->receivedAt())) { + self::setBoundaries(new DateTime(DateTimeFormat::utc($status->friendicaExtension()->receivedAt(), DateTimeFormat::JSON))); + } + break; + case TimelineOrderByTypes::ID: + default: + self::setBoundaries($post_item['uri-id']); + } + } catch (\Exception $e) { + Logger::debug('Error processing page boundary calculation, skipping', ['error' => $e]); + } + } + /** * Processes data from GET requests and sets defaults * @@ -123,9 +261,9 @@ class BaseApi extends BaseModule /** * Set boundaries for the "link" header * @param array $boundaries - * @param int $id + * @param int|\DateTime $id */ - protected static function setBoundaries(int $id) + protected static function setBoundaries($id) { if (!isset(self::$boundaries['min'])) { self::$boundaries['min'] = $id; @@ -143,7 +281,7 @@ class BaseApi extends BaseModule * Get the "link" header with "next" and "prev" links * @return string */ - protected static function getLinkHeader(): string + protected static function getLinkHeader(bool $asDate = false): string { if (empty(self::$boundaries)) { return ''; @@ -157,8 +295,15 @@ class BaseApi extends BaseModule $prev_request = $next_request = $request; - $prev_request['min_id'] = self::$boundaries['max']; - $next_request['max_id'] = self::$boundaries['min']; + if ($asDate) { + $max_date = self::$boundaries['max']; + $min_date = self::$boundaries['min']; + $prev_request['min_id'] = $max_date->format(DateTimeFormat::JSON); + $next_request['max_id'] = $min_date->format(DateTimeFormat::JSON); + } else { + $prev_request['min_id'] = self::$boundaries['max']; + $next_request['max_id'] = self::$boundaries['min']; + } $command = DI::baseUrl() . '/' . DI::args()->getCommand(); @@ -200,9 +345,9 @@ class BaseApi extends BaseModule * Set the "link" header with "next" and "prev" links * @return void */ - protected static function setLinkHeader() + protected static function setLinkHeader(bool $asDate = false) { - $header = self::getLinkHeader(); + $header = self::getLinkHeader($asDate); if (!empty($header)) { header($header); } diff --git a/src/Object/Api/Mastodon/Status.php b/src/Object/Api/Mastodon/Status.php index 2e7a0877d4..5563981f13 100644 --- a/src/Object/Api/Mastodon/Status.php +++ b/src/Object/Api/Mastodon/Status.php @@ -38,7 +38,7 @@ class Status extends BaseDataTransferObject { /** @var string */ protected $id; - /** @var string (Datetime) */ + /** @var string|null (Datetime) */ protected $created_at; /** @var string|null */ protected $in_reply_to_id = null; @@ -107,8 +107,8 @@ class Status extends BaseDataTransferObject */ public function __construct(array $item, Account $account, Counts $counts, UserAttributes $userAttributes, bool $sensitive, Application $application, array $mentions, array $tags, Card $card, array $attachments, array $in_reply, array $reblog, FriendicaExtension $friendica, array $quote = null, array $poll = null) { - $this->id = (string)$item['uri-id']; - $this->created_at = DateTimeFormat::utc($item['created'], DateTimeFormat::JSON); + $this->id = (string)$item['uri-id']; + $this->created_at = $item['created']; if ($item['gravity'] == Item::GRAVITY_COMMENT) { $this->in_reply_to_id = (string)$item['thr-parent-id']; @@ -154,6 +154,24 @@ class Status extends BaseDataTransferObject $this->friendica = $friendica; } + /** + * Returns the current created_at string or null if not set + * @return \DateTime|null + */ + public function createdAt(): ?string + { + return $this->created_at; + } + + /** + * Returns the Friendica Extension properties + * @return FriendicaExtension + */ + public function friendicaExtension(): FriendicaExtension + { + return $this->friendica; + } + /** * Returns the current entity as an array * diff --git a/src/Object/Api/Mastodon/Status/FriendicaExtension.php b/src/Object/Api/Mastodon/Status/FriendicaExtension.php index b2853894ad..b6dcd5df0c 100644 --- a/src/Object/Api/Mastodon/Status/FriendicaExtension.php +++ b/src/Object/Api/Mastodon/Status/FriendicaExtension.php @@ -35,22 +35,86 @@ class FriendicaExtension extends BaseDataTransferObject /** @var string */ protected $title; + /** @var string|null (Datetime) */ + protected $changed_at; + + /** @var string|null (Datetime) */ + protected $commented_at; + + /** @var string|null (Datetime) */ + protected $edited_at; + + /** @var string|null (Datetime) */ + protected $received_at; + /** @var FriendicaDeliveryData */ protected $delivery_data; /** @var int */ protected $dislikes_count; + /** * Creates a status count object * * @param string $title + * @param string|null $changed_at + * @param string|null $commented_at + * @param string|null $edited_at + * @param string|null $received_at * @param int $dislikes_count * @param FriendicaDeliveryData $delivery_data */ - public function __construct(string $title, int $dislikes_count, FriendicaDeliveryData $delivery_data) - { + public function __construct( + string $title, + ?string $changed_at, + ?string $commented_at, + ?string $edited_at, + ?string $received_at, + int $dislikes_count, + FriendicaDeliveryData $delivery_data + ) { $this->title = $title; + $this->changed_at = $changed_at; + $this->commented_at = $commented_at; + $this->edited_at = $edited_at; + $this->received_at = $received_at; $this->delivery_data = $delivery_data; $this->dislikes_count = $dislikes_count; } + + /** + * Returns the current changed_at string or null if not set + * @return ?string + */ + public function changedAt(): ?string + { + return $this->changed_at; + } + + /** + * Returns the current commented_at string or null if not set + * @return ?string + */ + public function commentedAt(): ?string + { + return $this->commented_at; + } + + /** + * Returns the current edited_at string or null if not set + * @return ?string + */ + public function editedAt(): ?string + { + return $this->edited_at; + } + + /** + * Returns the current received_at string or null if not set + * @return ?string + */ + public function receivedAt(): ?string + { + return $this->received_at; + } } diff --git a/src/Object/Api/Mastodon/TimelineOrderByTypes.php b/src/Object/Api/Mastodon/TimelineOrderByTypes.php new file mode 100644 index 0000000000..a58f892733 --- /dev/null +++ b/src/Object/Api/Mastodon/TimelineOrderByTypes.php @@ -0,0 +1,35 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon; + +/** + * Enumeration of order types that can be requested + */ +abstract class TimelineOrderByTypes +{ + const CHANGED = 'changed'; + const CREATED = 'created'; + const COMMENTED = 'commented'; + const EDITED = 'edited'; + const ID = 'id'; + const RECEIVED = 'received'; +}