Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
94.00% |
47 / 50 |
|
62.50% |
5 / 8 |
CRAP | |
0.00% |
0 / 1 |
DriverBase | |
94.00% |
47 / 50 |
|
62.50% |
5 / 8 |
19.08 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
dispatch | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
addConnection | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
changeConnection | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
setOptions | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
setLogger | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setQueryOptions | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
processRecords | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
formatRecords | |
94.44% |
17 / 18 |
|
0.00% |
0 / 1 |
8.01 | |||
processOptions | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
parseOptions | |
85.71% |
6 / 7 |
|
0.00% |
0 / 1 |
3.03 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Projom\Storage\Engine\Driver; |
6 | |
7 | use Projom\Storage\Query\Action; |
8 | use Projom\Storage\Engine\Driver\Connection\ConnectionInterface; |
9 | use Projom\Storage\Query\Format; |
10 | use Projom\Storage\Query\RecordInterface; |
11 | use Psr\Log\LoggerAwareInterface; |
12 | use Psr\Log\LoggerInterface; |
13 | use Psr\Log\NullLogger; |
14 | |
15 | abstract class DriverBase implements LoggerAwareInterface |
16 | { |
17 | protected const DEFAULT_OPTIONS = [ |
18 | 'return_single_record' => false, |
19 | ]; |
20 | |
21 | protected LoggerInterface $logger; |
22 | private array $options = []; |
23 | private null|array $queryOptions = null; |
24 | |
25 | public function __construct(LoggerInterface $logger = new NullLogger(), array $options = []) |
26 | { |
27 | $this->logger = $logger; |
28 | $this->setOptions($options); |
29 | } |
30 | |
31 | abstract public function dispatch(Action $action, mixed $args): mixed; |
32 | abstract public function addConnection(ConnectionInterface $connection): void; |
33 | abstract public function changeConnection(int|string $name): void; |
34 | |
35 | public function setOptions(array $options): void |
36 | { |
37 | $this->logger->debug( |
38 | 'Method: {method} with {options}.', |
39 | ['options' => $options, 'method' => __METHOD__] |
40 | ); |
41 | |
42 | $this->options = $options; |
43 | } |
44 | |
45 | public function setLogger(LoggerInterface $logger): void |
46 | { |
47 | $this->logger = $logger; |
48 | } |
49 | |
50 | protected function setQueryOptions(null|array $queryOptions): void |
51 | { |
52 | $this->logger->debug( |
53 | 'Method: {method} with {options}.', |
54 | ['options' => $queryOptions, 'method' => __METHOD__] |
55 | ); |
56 | |
57 | $this->queryOptions = $queryOptions; |
58 | } |
59 | |
60 | protected function processRecords(array $records, array $formatting): mixed |
61 | { |
62 | $this->logger->debug( |
63 | 'Method: {method} with {records}.', |
64 | ['records' => $records, 'method' => __METHOD__] |
65 | ); |
66 | |
67 | $records = $this->formatRecords($records, ...$formatting); |
68 | $records = $this->processOptions($records); |
69 | |
70 | return $records; |
71 | } |
72 | |
73 | private function formatRecords(array $records, Format $format, mixed $args = null): mixed |
74 | { |
75 | $this->logger->debug( |
76 | 'Method: {method} with {format} and {args}.', |
77 | ['format' => $format->name, 'args' => $args, 'method' => __METHOD__] |
78 | ); |
79 | |
80 | switch ($format) { |
81 | case Format::ARRAY: |
82 | return $records; |
83 | |
84 | case Format::STD_CLASS: |
85 | return array_map(fn($record) => (object) $record, $records); |
86 | |
87 | case Format::CUSTOM_OBJECT: |
88 | $className = $args; |
89 | |
90 | if ($className === null) |
91 | throw new \Exception('Class name not provided.', 400); |
92 | if (!class_exists($className)) |
93 | throw new \Exception("Class: $className does not exist.", 400); |
94 | if (!is_subclass_of($className, RecordInterface::class)) |
95 | throw new \Exception("Class: $className must implement RecordInterface.", 400); |
96 | |
97 | return array_map(fn($record) => $className::createFromRecord($record), $records); |
98 | |
99 | default: |
100 | throw new \Exception('Format is not recognized.', 400); |
101 | } |
102 | } |
103 | |
104 | private function processOptions(array $records): array|object |
105 | { |
106 | $options = $this->parseOptions(); |
107 | |
108 | if ($options['return_single_record']) |
109 | if (count($records) === 1) |
110 | $records = $records[0]; |
111 | |
112 | return $records; |
113 | } |
114 | |
115 | private function parseOptions(): array |
116 | { |
117 | $parseOptions = $this->options; |
118 | if ($this->queryOptions !== null) |
119 | $parseOptions = $this->queryOptions; |
120 | |
121 | $options = static::DEFAULT_OPTIONS; |
122 | |
123 | if (array_key_exists('return_single_record', $parseOptions)) |
124 | $options['return_single_record'] = (bool) $parseOptions['return_single_record']; |
125 | |
126 | return $options; |
127 | } |
128 | } |