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