. // }}} /** * ActivityPub implementation for GNU social * * @package GNUsocial * @category ActivityPub * * @author Diogo Peralta Cordeiro <@diogo.site> * @copyright 2021 Free Software Foundation, Inc http://www.fsf.org * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later */ namespace Plugin\ActivityPub\Util; use ActivityPhp\Type\Core\OrderedCollection; use ActivityPhp\Type\Core\OrderedCollectionPage; use App\Core\Router; use Component\Collection\Util\Controller\CircleController; use Component\Collection\Util\Controller\FeedController; use Component\Collection\Util\Controller\OrderedCollection as GSOrderedCollection; use Plugin\ActivityPub\ActivityPub; use Symfony\Component\HttpFoundation\Request; /** * Provides a response in application/ld+json to GSActivity * * @copyright 2021 Free Software Foundation, Inc http://www.fsf.org * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later */ abstract class OrderedCollectionController extends GSOrderedCollection { protected array $ordered_items = []; protected string $route; protected array $route_args = []; protected int $actor_id; public static function fromControllerVars(array $vars): array { $route = $vars['request']->get('_route'); $route_args = array_merge($vars['request']->query->all(), $vars['request']->attributes->get('_route_params')); unset($route_args['is_system_path'], $route_args['template'], $route_args['_format'], $route_args['accept'], $route_args['p']); if (is_subclass_of($vars['controller'][0], FeedController::class)) { $notes = []; foreach ($vars['notes'] as $note_replies) { $notes[] = Router::url('note_view', ['id' => $note_replies['note']->getId()], type: Router::ABSOLUTE_URL); } $type = self::setupType(route: $route, route_args: $route_args, ordered_items: $notes); } elseif (is_subclass_of($vars['controller'][0], CircleController::class)) { $actors = []; foreach ($vars['actors'] as $actor) { $actors[] = Router::url('actor_view_id', ['id' => $actor->getId()], type: Router::ABSOLUTE_URL); } $type = self::setupType(route: $route, route_args: $route_args, ordered_items: $actors); } else { $type = self::setupType(route: $route, route_args: $route_args, ordered_items: []); } return ['type' => $type]; } protected static function setupType(string $route, array $route_args = [], array $ordered_items = []): OrderedCollectionPage|OrderedCollection { $page = $route_args['page'] ?? 0; $type = $page === 0 ? new OrderedCollection() : new OrderedCollectionPage(); $type->set('@context', ActivityPub::$activity_streams_two_context); $type->set('items', $ordered_items); $type->set('orderedItems', $ordered_items); $type->set('totalItems', \count($ordered_items)); if ($page === 0) { $route_args['page'] = 1; $type->set('first', Router::url($route, $route_args, type: ROUTER::ABSOLUTE_URL)); } else { $type->set('partOf', Router::url($route, $route_args, type: ROUTER::ABSOLUTE_URL)); if ($page + 1 < $total_pages = 1) { // TODO: do proper pagination $route_args['page'] = ($page + 1 == 1 ? 2 : $page + 1); $type->set('next', Router::url($route, $route_args, type: ROUTER::ABSOLUTE_URL)); } if ($page > 1) { $route_args['page'] = ($page - 1 <= 0 ? 1 : $page - 1); $type->set('prev', Router::url($route, $route_args, type: ROUTER::ABSOLUTE_URL)); } } return $type; } public function handle(Request $request): array { $type = self::setupType($this->route, $this->route_args, $this->ordered_items, $this->actor_id); return ['type' => $type]; } }