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.
7.5 kB · 200 lines
PHP
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201<?php
declare(strict_types=1);
namespace Tests\Infrastructure\Persistence\Account\InviteCode;
use App\Domain\Account\InviteCode\InviteCode;use App\Domain\Account\InviteCode\InviteCodeNotFoundException;use App\Domain\Account\InviteCode\InviteCodeUse;use App\Infrastructure\Database\Database;use App\Infrastructure\Database\Schema\AccountSchema;use App\Infrastructure\Persistence\Account\InviteCode\SqliteInviteCodeRepository;use DateTimeImmutable;use Tests\TestCase;
class SqliteInviteCodeRepositoryTest extends TestCase{ private function newRepo(): SqliteInviteCodeRepository { $db = new Database(':memory:'); AccountSchema::apply($db);
return new SqliteInviteCodeRepository($db); }
private function makeCode( string $code = 'pds-abc-1234', string $forAccount = 'did:plc:alice', ?DateTimeImmutable $createdAt = null, int $availableUses = 5, ): InviteCode { return new InviteCode( code: $code, availableUses: $availableUses, disabled: false, forAccount: $forAccount, createdBy: 'admin', createdAt: $createdAt ?? new DateTimeImmutable('2026-01-01T00:00:00Z'), ); }
private function makeUse(string $code, string $usedBy, string $usedAt): InviteCodeUse { return new InviteCodeUse($code, $usedBy, new DateTimeImmutable($usedAt)); }
public function testFindAll(): void { $repo = $this->newRepo(); $repo->save($this->makeCode('code1')); $repo->save($this->makeCode('code2'));
$this->assertCount(2, $repo->findAll()); }
public function testFindByCode(): void { $repo = $this->newRepo(); $repo->save($this->makeCode());
$found = $repo->findByCode('pds-abc-1234'); $this->assertSame('pds-abc-1234', $found->getCode()); }
public function testFindByCodeThrowsWhenMissing(): void { $repo = $this->newRepo();
$this->expectException(InviteCodeNotFoundException::class); $repo->findByCode('no-such-code'); }
public function testFindAllForAccount(): void { $repo = $this->newRepo(); $repo->save($this->makeCode('c1', 'did:plc:alice')); $repo->save($this->makeCode('c2', 'did:plc:bob'));
$results = $repo->findAllForAccount('did:plc:alice'); $this->assertCount(1, $results); $this->assertSame('c1', $results[0]->getCode()); }
public function testDisable(): void { $repo = $this->newRepo(); $repo->save($this->makeCode()); $repo->disable('pds-abc-1234');
$this->assertTrue($repo->findByCode('pds-abc-1234')->isDisabled()); }
public function testRecordUseAndFindUses(): void { $repo = $this->newRepo(); $repo->save($this->makeCode()); $use = $this->makeUse('pds-abc-1234', 'did:plc:invite-user', '2026-01-02T00:00:00Z'); $repo->recordUse($use);
$uses = $repo->findUsesForCode('pds-abc-1234'); $this->assertCount(1, $uses); $this->assertSame('did:plc:invite-user', $uses[0]->getUsedBy()); }
public function testFindPageByRecentOrdersNewestFirst(): void { $repo = $this->newRepo(); $repo->save($this->makeCode('old', createdAt: new DateTimeImmutable('2026-01-01T00:00:00Z'))); $repo->save($this->makeCode('newest', createdAt: new DateTimeImmutable('2026-01-03T00:00:00Z'))); $repo->save($this->makeCode('middle', createdAt: new DateTimeImmutable('2026-01-02T00:00:00Z')));
$page = $repo->findPageByRecent(null, null, 2);
$this->assertSame(['newest', 'middle'], array_map( static fn (InviteCode $code): string => $code->getCode(), $page )); }
public function testFindPageByRecentAppliesCursor(): void { $repo = $this->newRepo(); $repo->save($this->makeCode('old', createdAt: new DateTimeImmutable('2026-01-01T00:00:00Z'))); $repo->save($this->makeCode('middle', createdAt: new DateTimeImmutable('2026-01-02T00:00:00Z'))); $repo->save($this->makeCode('newest', createdAt: new DateTimeImmutable('2026-01-03T00:00:00Z')));
$page = $repo->findPageByRecent('2026-01-02T00:00:00+00:00', 'middle', 5);
$this->assertSame(['old'], array_map( static fn (InviteCode $code): string => $code->getCode(), $page )); }
public function testFindPageByUsageOrdersMostUsedFirst(): void { $repo = $this->newRepo(); $repo->save($this->makeCode('one')); $repo->save($this->makeCode('three')); $repo->save($this->makeCode('two'));
$repo->recordUse($this->makeUse('three', 'did:plc:three-user-1', '2026-01-03T00:00:00Z')); $repo->recordUse($this->makeUse('three', 'did:plc:three-user-2', '2026-01-03T01:00:00Z')); $repo->recordUse($this->makeUse('three', 'did:plc:three-user-3', '2026-01-03T02:00:00Z')); $repo->recordUse($this->makeUse('two', 'did:plc:two-user-1', '2026-01-03T03:00:00Z')); $repo->recordUse($this->makeUse('two', 'did:plc:two-user-2', '2026-01-03T04:00:00Z')); $repo->recordUse($this->makeUse('one', 'did:plc:one-user-1', '2026-01-03T05:00:00Z'));
$page = $repo->findPageByUsage(null, null, 3);
$this->assertSame(['three', 'two', 'one'], array_map( static fn (InviteCode $code): string => $code->getCode(), $page )); }
public function testFindPageByUsageAppliesCursor(): void { $repo = $this->newRepo(); $repo->save($this->makeCode('one')); $repo->save($this->makeCode('three')); $repo->save($this->makeCode('two'));
$repo->recordUse($this->makeUse('three', 'did:plc:three-user-1', '2026-01-03T00:00:00Z')); $repo->recordUse($this->makeUse('three', 'did:plc:three-user-2', '2026-01-03T01:00:00Z')); $repo->recordUse($this->makeUse('three', 'did:plc:three-user-3', '2026-01-03T02:00:00Z')); $repo->recordUse($this->makeUse('two', 'did:plc:two-user-1', '2026-01-03T03:00:00Z')); $repo->recordUse($this->makeUse('two', 'did:plc:two-user-2', '2026-01-03T04:00:00Z')); $repo->recordUse($this->makeUse('one', 'did:plc:one-user-1', '2026-01-03T05:00:00Z'));
$page = $repo->findPageByUsage(2, 'two', 3);
$this->assertSame(['one'], array_map( static fn (InviteCode $code): string => $code->getCode(), $page )); }
public function testFindUsesForCodesGroupsByCodeAndOrdersNewestFirst(): void { $repo = $this->newRepo(); $repo->save($this->makeCode('alpha')); $repo->save($this->makeCode('beta'));
$repo->recordUse($this->makeUse('alpha', 'did:plc:alpha-user-1', '2026-01-01T00:00:00Z')); $repo->recordUse($this->makeUse('alpha', 'did:plc:alpha-user-2', '2026-01-02T00:00:00Z')); $repo->recordUse($this->makeUse('beta', 'did:plc:beta-user-1', '2026-01-03T00:00:00Z'));
$uses = $repo->findUsesForCodes(['alpha', 'beta']);
$this->assertSame(['did:plc:alpha-user-2', 'did:plc:alpha-user-1'], array_map( static fn (InviteCodeUse $use): string => $use->getUsedBy(), $uses['alpha'] )); $this->assertSame(['did:plc:beta-user-1'], array_map( static fn (InviteCodeUse $use): string => $use->getUsedBy(), $uses['beta'] )); }}