1 | <?php declare(strict_types=1); |
||
14 | class Repository implements RepositoryInterface |
||
15 | { |
||
16 | protected $tableGateway; |
||
17 | |||
18 | protected $hydrator; |
||
19 | |||
20 | protected $modelClass; |
||
21 | |||
22 | protected $relationCollection; |
||
23 | |||
24 | 17 | public function __construct( |
|
35 | |||
36 | 1 | protected function getRelation($name): Relation |
|
37 | { |
||
38 | 1 | if (\is_null($this->relationCollection)) { |
|
39 | throw new \InvalidArgumentException("Relation $name do not exist"); |
||
40 | } |
||
41 | 1 | $relation = $this->relationCollection->getRelationByProperty($name); |
|
42 | 1 | if (!($relation instanceof Relation)) { |
|
43 | throw new \InvalidArgumentException("Relation $name do not exist"); |
||
44 | } |
||
45 | 1 | return $relation; |
|
46 | } |
||
47 | |||
48 | 1 | protected function normalizeResultSet(array $data, array $relations): array |
|
49 | { |
||
50 | /** |
||
51 | * @var string $property |
||
52 | * @var Relation $relation |
||
53 | */ |
||
54 | 1 | foreach ($relations as $property => $relation) { |
|
55 | 1 | $relationData = []; |
|
56 | 1 | foreach ($data as $field => $value) { |
|
57 | 1 | if (\strpos($field, $relation->getRelatedCollection() . '_relation_') === 0) { |
|
58 | $fieldName = \str_replace($relation->getRelatedCollection() . '_relation_', '', $field); |
||
59 | 1 | $relationData[$fieldName] = $value; |
|
60 | } |
||
61 | } |
||
62 | 1 | $data[$property] = $relationData; |
|
63 | } |
||
64 | 1 | return $data; |
|
65 | } |
||
66 | |||
67 | 1 | protected function applyRelationStrategies(array $relations) |
|
68 | { |
||
69 | /** |
||
70 | * @var string $property |
||
71 | * @var Relation $relation |
||
72 | */ |
||
73 | 1 | foreach ($relations as $property => $relation) { |
|
74 | 1 | $this->hydrator->addStrategy($property, new ObjectStrategy($this->hydrator, $relation->getRelatedModel())); |
|
75 | } |
||
76 | 1 | } |
|
77 | |||
78 | 2 | public function findOne(array $conditions = [], array $with = []): object |
|
79 | { |
||
80 | 2 | $relations = []; |
|
81 | 2 | foreach ($with as $relationName) { |
|
82 | 1 | $relations[$relationName] = $this->getRelation($relationName); |
|
83 | } |
||
84 | 2 | $data = $this->tableGateway->queryOne($conditions, $relations); |
|
85 | 2 | if (!\is_array($data)) { |
|
86 | 1 | throw new NotFoundException(); |
|
87 | } |
||
88 | 1 | if (!empty($relations)) { |
|
89 | 1 | $data = $this->normalizeResultSet($data, $relations); |
|
90 | 1 | $this->applyRelationStrategies($relations); |
|
91 | } |
||
92 | 1 | $result = $this->hydrator->hydrate($this->modelClass, $data); |
|
93 | 1 | return $result; |
|
94 | } |
||
95 | |||
96 | 1 | public function findAll(array $conditions = [], array $order = [], int $limit = 0, int $offset = 0, array $with = []): array |
|
97 | { |
||
98 | 1 | $result = []; |
|
99 | 1 | $relations = []; |
|
100 | 1 | foreach ($with as $relationName) { |
|
101 | $relations[$relationName] = $this->getRelation($relationName); |
||
102 | } |
||
103 | 1 | if (!empty($relations)) { |
|
104 | $this->applyRelationStrategies($relations); |
||
105 | } |
||
106 | 1 | $data = $this->tableGateway->queryAll($conditions, $order, $limit, $offset, $relations); |
|
107 | 1 | foreach ($data as $row) { |
|
108 | 1 | if (!empty($relations)) { |
|
109 | $row = $this->normalizeResultSet($row, $relations); |
||
110 | } |
||
111 | 1 | $result[] = $this->hydrator->hydrate($this->modelClass, $row); |
|
112 | } |
||
113 | 1 | return $result; |
|
114 | } |
||
115 | |||
116 | 1 | public function aggregate(string $expression, array $conditions): string |
|
120 | |||
121 | 1 | public function aggregateCount(string $field = '', array $conditions = []): string |
|
122 | { |
||
123 | 1 | return $this->tableGateway->aggregateCount($field, $conditions); |
|
124 | } |
||
125 | |||
126 | 1 | public function aggregateSum(string $field, array $conditions): string |
|
127 | { |
||
128 | 1 | return $this->tableGateway->aggregateSum($field, $conditions); |
|
129 | } |
||
130 | |||
131 | 1 | public function aggregateAverage(string $field, array $conditions): string |
|
132 | { |
||
133 | 1 | return $this->tableGateway->aggregateAverage($field, $conditions); |
|
134 | } |
||
135 | |||
136 | 1 | public function aggregateMin(string $field, array $conditions): string |
|
137 | { |
||
138 | 1 | return $this->tableGateway->aggregateMin($field, $conditions); |
|
139 | } |
||
140 | |||
141 | 1 | public function aggregateMax(string $field, array $conditions): string |
|
142 | { |
||
143 | 1 | return $this->tableGateway->aggregateMax($field, $conditions); |
|
144 | } |
||
145 | |||
146 | 4 | protected function validateModelClass(object $model) |
|
147 | { |
||
148 | 4 | if (!($model instanceof $this->modelClass)) { |
|
149 | 1 | throw new InvalidModelClassException('Invalid model class: ' . get_class($model) . '. Expected ' . $this->modelClass); |
|
150 | } |
||
151 | 3 | } |
|
152 | |||
153 | 1 | public function insert(object $model): void |
|
154 | { |
||
155 | 1 | $this->validateModelClass($model); |
|
156 | 1 | $data = $this->hydrator->extract($model); |
|
157 | 1 | $primaryKeys = $this->tableGateway->insert($data); |
|
158 | 1 | if (!\is_array($primaryKeys)) { |
|
159 | throw new InsertException($data); |
||
160 | } |
||
161 | 1 | $this->hydrator->hydrate($model, $primaryKeys); |
|
162 | 1 | } |
|
163 | |||
164 | 1 | public function update(object $model): void |
|
165 | { |
||
166 | 1 | $this->validateModelClass($model); |
|
167 | 1 | $data = $this->hydrator->extract($model); |
|
168 | 1 | $this->tableGateway->updateOne($data); |
|
169 | 1 | } |
|
170 | |||
171 | 2 | public function delete(object $model): void |
|
172 | { |
||
173 | 2 | $this->validateModelClass($model); |
|
174 | 1 | $data = $this->hydrator->extract($model); |
|
175 | 1 | $this->tableGateway->deleteOne($data); |
|
176 | 1 | } |
|
177 | |||
178 | 1 | public function updateAll(array $data, array $conditions): int |
|
179 | { |
||
180 | 1 | return $this->tableGateway->updateAll($data, $conditions); |
|
181 | } |
||
182 | |||
183 | 1 | public function deleteAll(array $conditions): int |
|
184 | { |
||
185 | 1 | return $this->tableGateway->deleteAll($conditions); |
|
186 | } |
||
187 | |||
188 | /** |
||
189 | * @param array $data |
||
190 | * @return object |
||
191 | */ |
||
192 | 1 | public function create(array $data = []): object |
|
196 | |||
197 | /** |
||
198 | * @param object $entity |
||
199 | * @param array $data |
||
200 | */ |
||
201 | 1 | public function populate(object $entity, array $data): void |
|
205 | } |
||
206 |