X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModule%2FBaseApi.php;h=d6e5f748f23d35976b5cf99eb84e2ddffb0ed520;hb=7fd1db0ec6b3c729e347f94ca961421fb4f5070e;hp=f8524b524ee48c694f2532515aab0cdfe06e3e71;hpb=2754cdc5d6661d27351f7c0d320f715f0b6105ba;p=friendica.git diff --git a/src/Module/BaseApi.php b/src/Module/BaseApi.php index f8524b524e..d6e5f748f2 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->editedAt())) { + self::setBoundaries(new DateTime(DateTimeFormat::utc($status->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); } @@ -227,7 +372,7 @@ class BaseApi extends BaseModule */ public static function appSupportsQuotes(): bool { - $token = self::getCurrentApplication(); + $token = OAuth::getCurrentApplicationToken(); return (!empty($token['name']) && in_array($token['name'], ['Fedilab'])); }