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 | } |