Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
1 / 1
InMemoryDriver
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
9 / 9
18
100.00% covered (success)
100.00%
1 / 1
 findAll
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 findById
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 findBy
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 findOneBy
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 save
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 deleteById
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
 reset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 applySorting
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
3
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 Phexium\Plugin\SqlDriver\Adapter;
11
12use InvalidArgumentException;
13use Override;
14use Phexium\Domain\Id\IdInterface;
15use Phexium\Domain\Specification\SpecificationInterface;
16use Phexium\Plugin\SqlDriver\Port\SqlDriverInterface;
17
18final class InMemoryDriver implements SqlDriverInterface
19{
20    private array $storage = [];
21
22    #[Override]
23    public function findAll(string $table): array
24    {
25        return array_values($this->storage[$table] ?? []);
26    }
27
28    #[Override]
29    public function findById(string $table, IdInterface $id): ?array
30    {
31        return $this->storage[$table][$id->getValue()] ?? null;
32    }
33
34    #[Override]
35    public function findBy(string $table, SpecificationInterface $specification, ?array $orderBy = null, ?int $offset = null, ?int $limit = null): array
36    {
37        $filter = $specification->toInMemoryFilter();
38        $rows = $this->storage[$table] ?? [];
39        $result = array_filter($rows, $filter);
40        $result = array_values($result);
41
42        if ($orderBy !== null) {
43            $result = $this->applySorting($result, $orderBy);
44        }
45
46        if ($offset !== null || $limit !== null) {
47            return array_slice($result, $offset ?? 0, $limit);
48        }
49
50        return $result;
51    }
52
53    #[Override]
54    public function findOneBy(string $table, SpecificationInterface $specification): ?array
55    {
56        $filter = $specification->toInMemoryFilter();
57        $rows = $this->storage[$table] ?? [];
58
59        foreach ($rows as $row) {
60            if ($filter($row)) {
61                return $row;
62            }
63        }
64
65        return null;
66    }
67
68    #[Override]
69    public function save(string $table, array $row): void
70    {
71        if (!isset($this->storage[$table])) {
72            $this->storage[$table] = [];
73        }
74
75        $id = $row['id'] ?? throw new InvalidArgumentException('Row must have an "id" key');
76        $this->storage[$table][$id] = $row;
77    }
78
79    #[Override]
80    public function deleteById(string $table, IdInterface $id): int
81    {
82        if (!isset($this->storage[$table][$id->getValue()])) {
83            return 0;
84        }
85
86        unset($this->storage[$table][$id->getValue()]);
87
88        return 1;
89    }
90
91    #[Override]
92    public function exists(string $table, IdInterface $id): bool
93    {
94        return isset($this->storage[$table][$id->getValue()]);
95    }
96
97    public function reset(string $table): void
98    {
99        $this->storage[$table] = [];
100    }
101
102    private function applySorting(array $rows, array $orderBy): array
103    {
104        foreach ($orderBy as $field => $direction) {
105            $direction = strtoupper($direction);
106            $ascending = $direction === 'ASC';
107
108            usort($rows, static function (array $a, array $b) use ($field, $ascending): int {
109                $valueA = $a[$field] ?? null;
110                $valueB = $b[$field] ?? null;
111                $comparison = $valueA <=> $valueB;
112
113                return $ascending ? $comparison : -$comparison;
114            });
115        }
116
117        return $rows;
118    }
119}