Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
11 / 11
CRAP
100.00% covered (success)
100.00%
1 / 1
AbstractUserRepository
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
11 / 11
14
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
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\Mapper\UserMapper;
18use InvalidArgumentException;
19use Override;
20use Phexium\Domain\Id\IdInterface;
21use Phexium\Domain\Specification\SpecificationInterface;
22use Phexium\Plugin\SqlDriver\Port\SqlDriverInterface;
23
24abstract class AbstractUserRepository implements UserRepository
25{
26    protected const string TABLE = 'user';
27
28    public function __construct(
29        protected readonly SqlDriverInterface $driver,
30        protected readonly UserMapper $mapper,
31    ) {}
32
33    #[Override]
34    public function findAll(): UsersCollection
35    {
36        $rows = $this->driver->findAll(self::TABLE);
37
38        return UsersCollection::fromMap($rows, fn (array $row): User => $this->mapper->fromRow($row));
39    }
40
41    #[Override]
42    public function findBy(SpecificationInterface $specification, ?array $orderBy = null, ?int $offset = null, ?int $limit = null): UsersCollection
43    {
44        $rows = $this->driver->findBy(self::TABLE, $specification, $orderBy, $offset, $limit);
45
46        return UsersCollection::fromMap($rows, fn (array $row): User => $this->mapper->fromRow($row));
47    }
48
49    #[Override]
50    public function findOneBy(SpecificationInterface $specification): ?User
51    {
52        $row = $this->driver->findOneBy(self::TABLE, $specification);
53
54        return $row !== null ? $this->mapper->fromRow($row) : null;
55    }
56
57    #[Override]
58    public function findById(IdInterface $id): ?User
59    {
60        $row = $this->driver->findById(self::TABLE, $id);
61
62        return $row !== null ? $this->mapper->fromRow($row) : null;
63    }
64
65    #[Override]
66    public function getById(IdInterface $id): User
67    {
68        $user = $this->findById($id);
69
70        if (!$user instanceof User) {
71            throw new InvalidArgumentException('User with ID='.$id->getValue().' not found');
72        }
73
74        return $user;
75    }
76
77    #[Override]
78    public function exists(IdInterface $id): bool
79    {
80        return $this->driver->exists(self::TABLE, $id);
81    }
82
83    #[Override]
84    public function save(User $user): void
85    {
86        $this->driver->save(self::TABLE, $this->mapper->toRow($user));
87    }
88
89    #[Override]
90    public function delete(User $user): int
91    {
92        return $this->deleteById($user->getId());
93    }
94
95    #[Override]
96    public function deleteById(IdInterface $id): int
97    {
98        return $this->driver->deleteById(self::TABLE, $id);
99    }
100
101    #[Override]
102    public function findByEmail(Email $email): ?User
103    {
104        return $this->findOneBy(new EmailSpecification($email));
105    }
106}