Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
12 / 12
CRAP
100.00% covered (success)
100.00%
1 / 1
InMemoryUserRepository
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
12 / 12
15
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 findAll
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 findBy
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 findOneBy
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 findById
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 getById
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 exists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 save
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 delete
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deleteById
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 findByEmail
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 reset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3// ╔════════════════════════════════════════════════════════════╗
4// ║ MIT Licence (#Expat) - https://opensource.org/licenses/MIT ║
5// ║ Copyright 2026 Frederic Poeydomenge <dyno@phexium.com>     ║
6// ╚════════════════════════════════════════════════════════════╝
7
8declare(strict_types=1);
9
10namespace AppDemo\User\Infrastructure;
11
12use AppDemo\User\Domain\Email;
13use AppDemo\User\Domain\Specification\EmailSpecification;
14use AppDemo\User\Domain\User;
15use AppDemo\User\Domain\UserRepository;
16use AppDemo\User\Domain\UsersCollection;
17use AppDemo\User\Infrastructure\Trait\UserRepositoryMappingTrait;
18use InvalidArgumentException;
19use Override;
20use Phexium\Domain\Id\IdInterface;
21use Phexium\Domain\Specification\SpecificationInterface;
22use Phexium\Plugin\IdGenerator\Port\IdGeneratorInterface;
23use Phexium\Plugin\SqlDriver\Adapter\InMemoryDriver;
24
25final readonly class InMemoryUserRepository implements UserRepository
26{
27    use UserRepositoryMappingTrait;
28
29    private const string TABLE = 'user';
30
31    public function __construct(
32        private InMemoryDriver $driver,
33        private IdGeneratorInterface $idGenerator,
34    ) {}
35
36    #[Override]
37    public function findAll(): UsersCollection
38    {
39        $rows = $this->driver->findAll(self::TABLE);
40
41        return UsersCollection::fromMap($rows, fn (array $row): User => $this->rowToUser($row));
42    }
43
44    #[Override]
45    public function findBy(SpecificationInterface $specification, ?array $orderBy = null, ?int $offset = null, ?int $limit = null): UsersCollection
46    {
47        $rows = $this->driver->findBy(self::TABLE, $specification, $orderBy, $offset, $limit);
48
49        return UsersCollection::fromMap($rows, fn (array $row): User => $this->rowToUser($row));
50    }
51
52    #[Override]
53    public function findOneBy(SpecificationInterface $specification): ?User
54    {
55        $row = $this->driver->findOneBy(self::TABLE, $specification);
56
57        return $row !== null ? $this->rowToUser($row) : null;
58    }
59
60    #[Override]
61    public function findById(IdInterface $id): ?User
62    {
63        $row = $this->driver->findById(self::TABLE, $id);
64
65        return $row !== null ? $this->rowToUser($row) : null;
66    }
67
68    #[Override]
69    public function getById(IdInterface $id): User
70    {
71        $user = $this->findById($id);
72
73        if (!$user instanceof User) {
74            throw new InvalidArgumentException('User with ID='.$id->getValue().' not found');
75        }
76
77        return $user;
78    }
79
80    #[Override]
81    public function exists(IdInterface $id): bool
82    {
83        return $this->driver->exists(self::TABLE, $id);
84    }
85
86    #[Override]
87    public function save(User $user): void
88    {
89        $this->driver->save(self::TABLE, $this->userToRow($user));
90    }
91
92    #[Override]
93    public function delete(User $user): int
94    {
95        return $this->deleteById($user->getId());
96    }
97
98    #[Override]
99    public function deleteById(IdInterface $id): int
100    {
101        return $this->driver->deleteById(self::TABLE, $id);
102    }
103
104    #[Override]
105    public function findByEmail(Email $email): ?User
106    {
107        return $this->findOneBy(new EmailSpecification($email));
108    }
109
110    public function reset(): void
111    {
112        $this->driver->reset(self::TABLE);
113    }
114}