Something went wrong. Try again.
A barebones implementation of an atproto PDS in PHP and Slim Framework 4.
pds php atproto
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128<?php
declare(strict_types=1);
namespace App\Application\Actions\Pds\Atproto\Sync;
use App\Application\Actions\Pds\PdsAction;use App\Application\Actions\Pds\XrpcException;use App\Application\Settings\SettingsInterface;use App\Domain\Actor\ActorRepository;use App\Domain\ActorStore\ActorStoreFactory;use App\Domain\Pds\Atproto\Sync\ListReposResponse;use App\Domain\Pds\Atproto\Sync\RepoView;use App\Domain\Repo\RepoRootNotFoundException;use Psr\Http\Message\ResponseInterface as Response;use Psr\Log\LoggerInterface;
class ListReposAction extends PdsAction{ public const DEFAULT_LIMIT = 500;
public const MAX_LIMIT = 1000;
private ActorRepository $actorRepository;
private ActorStoreFactory $actorStoreFactory;
public function __construct( LoggerInterface $logger, SettingsInterface $settings, ActorRepository $actorRepository, ActorStoreFactory $actorStoreFactory ) { parent::__construct($logger, $settings, 'com.atproto.sync.listRepos'); $this->actorRepository = $actorRepository; $this->actorStoreFactory = $actorStoreFactory; }
/** * {@inheritdoc} */ protected function action(): Response { $params = $this->request->getQueryParams();
$limit = $this->parseLimit($params['limit'] ?? null); $cursor = $this->parseCursor($params['cursor'] ?? null);
$actors = $this->actorRepository->findPage($cursor, $limit);
$repos = []; foreach ($actors as $actor) { try { $root = $this->actorStoreFactory->get($actor->getDid()) ->getRepoRoot() ->findByDid($actor->getDid()); } catch (RepoRootNotFoundException $e) { // actor exists but its repo hasn't been initialised; skip it continue; }
$status = $actor->getRepoStatus(); $repos[] = new RepoView( did: $actor->getDid(), head: $root->getCid(), rev: $root->getRev(), active: $status === null, status: $status, ); }
// a full page means there may be more results; the cursor is the // last actor DID returned (whether or not it produced a RepoView) $nextCursor = null; if (count($actors) === $limit) { $last = end($actors); assert($last !== false); $nextCursor = $last->getDid(); }
return $this->respondWithData(new ListReposResponse($repos, $nextCursor)); }
private function parseLimit(mixed $raw): int { if ($raw === null || $raw === '') { return self::DEFAULT_LIMIT; }
if (!is_string($raw) && !is_int($raw)) { throw XrpcException::invalidParam( $this->actionName, 'limit must be an integer', (string) (is_scalar($raw) ? $raw : '') ); }
if (is_string($raw) && !preg_match('/^-?\d+$/', $raw)) { throw XrpcException::invalidParam($this->actionName, 'limit must be an integer', $raw); }
$limit = (int) $raw; if ($limit < 1 || $limit > self::MAX_LIMIT) { throw XrpcException::invalidParam( $this->actionName, sprintf('limit must be between 1 and %d', self::MAX_LIMIT), (string) $raw ); }
return $limit; }
private function parseCursor(mixed $raw): ?string { if ($raw === null) { return null; }
if (!is_string($raw)) { throw XrpcException::invalidParam($this->actionName, 'cursor must be a string', ''); }
$cursor = trim($raw); return $cursor === '' ? null : $cursor; }}