Passed
Push — master ( 7ebdb7...1c0465 )
by Alexander
01:53
created

Repository::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

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