Passed
Branch 4.1.0 (271fee)
by Joao
03:09
created

Repository   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 343
Duplicated Lines 0 %

Test Coverage

Coverage 68.68%

Importance

Changes 8
Bugs 0 Features 0
Metric Value
eloc 118
c 8
b 0
f 0
dl 0
loc 343
ccs 125
cts 182
cp 0.6868
rs 9.52
wmc 36

17 Methods

Rating   Name   Duplication   Size   Complexity  
A getByFilter() 0 11 2
A get() 0 9 2
A delete() 0 8 1
A insert() 0 7 2
A setBeforeUpdate() 0 3 1
A __construct() 0 9 1
A update() 0 8 1
A filterIn() 0 10 2
A insertWithKeyGen() 0 6 1
A getDbDriver() 0 3 1
B save() 0 58 8
A setBeforeInsert() 0 3 1
B getByQuery() 0 41 9
A insertWithAutoinc() 0 5 1
A deleteByQuery() 0 8 1
A getScalar() 0 7 1
A getMapper() 0 3 1
1
<?php
2
3
namespace ByJG\MicroOrm;
4
5
use ByJG\AnyDataset\Db\DbDriverInterface;
6
use ByJG\MicroOrm\Exception\OrmBeforeInvalidException;
7
use ByJG\Serializer\BinderObject;
8
9
class Repository
10
{
11
12
    /**
13
     * @var Mapper
14
     */
15
    protected $mapper;
16
17
    /**
18
     * @var DbDriverInterface
19
     */
20
    protected $dbDriver = null;
21
22
    /**
23
     * @var \Closure
24
     */
25
    protected $beforeUpdate = null;
26
27
    /**
28
     * @var \Closure
29
     */
30
    protected $beforeInsert = null;
31
32
    /**
33
     * Repository constructor.
34
     * @param DbDriverInterface $dbDataset
35
     * @param Mapper $mapper
36
     */
37 29
    public function __construct(DbDriverInterface $dbDataset, Mapper $mapper)
38
    {
39 29
        $this->dbDriver = $dbDataset;
40 29
        $this->mapper = $mapper;
41
        $this->beforeInsert = function ($instance) {
42 5
            return $instance;
43
        };
44
        $this->beforeUpdate = function ($instance) {
45 3
            return $instance;
46
        };
47 29
    }
48
49
    /**
50
     * @return Mapper
51
     */
52 14
    public function getMapper()
53
    {
54 14
        return $this->mapper;
55
    }
56
57
    /**
58
     * @return DbDriverInterface
59
     */
60 29
    protected function getDbDriver()
61
    {
62 29
        return $this->dbDriver;
63
    }
64
65
    /**
66
     * @param array|string $pkId
67
     * @return mixed|null
68
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
69
     * @throws \ByJG\Serializer\Exception\InvalidArgumentException
70
     */
71 16
    public function get($pkId)
72
    {
73 16
        $result = $this->getByFilter($this->mapper->getPrimaryKey() . ' = [[id]]', ['id' => $pkId]);
74
75 16
        if (count($result) === 1) {
76 16
            return $result[0];
77
        }
78
79 3
        return null;
80
    }
81
82
    /**
83
     * @param array $pkId
84
     * @return mixed|null
85
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
86
     */
87 2
    public function delete($pkId)
88
    {
89 2
        $params = ['id' => $pkId];
90 2
        $updatable = Updatable::getInstance()
91 2
            ->table($this->mapper->getTable())
92 2
            ->where($this->mapper->getPrimaryKey() . ' = [[id]]', $params);
93
94 2
        return $this->deleteByQuery($updatable);
95
    }
96
97
    /**
98
     * @param \ByJG\MicroOrm\Updatable $updatable
99
     * @return bool
100
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
101
     */
102 3
    public function deleteByQuery(Updatable $updatable)
103
    {
104 3
        $params = [];
105 3
        $sql = $updatable->buildDelete($params);
106
107 3
        $this->getDbDriver()->execute($sql, $params);
108
109 3
        return true;
110
    }
111
112
    /**
113
     * @param string $filter
114
     * @param array $params
115
     * @param bool $forUpdate
116
     * @return array
117
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
118
     * @throws \ByJG\Serializer\Exception\InvalidArgumentException
119
     */
120 19
    public function getByFilter($filter, array $params, $forUpdate = false)
121
    {
122 19
        $query = new Query();
123 19
        $query->table($this->mapper->getTable())
124 19
            ->where($filter, $params);
125
        
126 19
        if ($forUpdate) {
127
            $query->forUpdate();
128
        }
129
130 19
        return $this->getByQuery($query);
131
    }
132
133
    /**
134
     * @param array $arrValues
135
     * @param $field
136
     * @return array
137
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
138
     * @throws \ByJG\Serializer\Exception\InvalidArgumentException
139
     */
140 3
    public function filterIn($arrValues, $field = "") {
141 3
        $arrValues = (array) $arrValues;
142
143 3
        if (empty($field)) {
144 3
            $field = $this->getMapper()->getPrimaryKey();
145
        }
146
147 3
        return $this->getByFilter(
148 3
            $field . " in (:" . implode(',:', array_keys($arrValues)) . ')',
149 3
            $arrValues
150
        );
151
    }
152
153
    /**
154
     * @param \ByJG\MicroOrm\Query $query
155
     * @return mixed
156
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
157
     */
158 1
    public function getScalar(Query $query)
159
    {
160 1
        $query = $query->build($this->getDbDriver());
161
162 1
        $params = $query['params'];
163 1
        $sql = $query['sql'];
164 1
        return $this->getDbDriver()->getScalar($sql, $params);
165
    }
166
167
    /**
168
     * @param Query $query
169
     * @param Mapper[] $mapper
170
     * @return array
171
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
172
     * @throws \ByJG\Serializer\Exception\InvalidArgumentException
173
     */
174 28
    public function getByQuery(Query $query, array $mapper = [])
175
    {
176 28
        $mapper = array_merge([$this->mapper], $mapper);
177 28
        $query = $query->build($this->getDbDriver());
178
179 28
        $params = $query['params'];
180 28
        $sql = $query['sql'];
181 28
        $result = [];
182 28
        $iterator = $this->getDbDriver()->getIterator($sql, $params);
183
184 28
        foreach ($iterator as $row) {
185 26
            $collection = [];
186 26
            foreach ($mapper as $item) {
187 26
                $instance = $item->getEntity();
188 26
                $data = $row->toArray();
189
190 26
                foreach ((array)$item->getFieldAlias() as $fieldname => $fieldalias) {
191 4
                    if (isset($data[$fieldalias])) {
192 2
                        $data[$fieldname] = $data[$fieldalias];
193 4
                        unset($fieldalias);
194
                    }
195
                }
196 26
                BinderObject::bindObject($data, $instance);
197
198 26
                foreach ((array)$item->getFieldMap() as $property => $fieldmap) {
199 11
                    $selectMask = $fieldmap[Mapper::FIELDMAP_SELECTMASK];
200 11
                    $value = "";
201 11
                    if (isset($data[$fieldmap[Mapper::FIELDMAP_FIELD]])) {
202 10
                        $value = $data[$fieldmap[Mapper::FIELDMAP_FIELD]];
203
                    }
204 11
                    $data[$property] = $selectMask($value, $instance);
205
                }
206 26
                if (count($item->getFieldMap()) > 0) {
207 11
                    BinderObject::bindObject($data, $instance);
208
                }
209 26
                $collection[] = $instance;
210
            }
211 26
            $result[] = count($collection) === 1 ? $collection[0] : $collection;
212
        }
213
214 28
        return $result;
215
    }
216
217
    /**
218
     * @param mixed $instance
219
     * @return mixed
220
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
221
     * @throws \ByJG\MicroOrm\Exception\OrmBeforeInvalidException
222
     * @throws \ByJG\MicroOrm\Exception\OrmInvalidFieldsException
223
     * @throws \ByJG\Serializer\Exception\InvalidArgumentException
224
     */
225 10
    public function save($instance)
226
    {
227
        // Get all fields
228 10
        $array = BinderObject::toArrayFrom($instance, true);
229 10
        $array = $this->getMapper()->prepareField($array);
230
231
        // Mapping the data
232 10
        foreach ((array)$this->getMapper()->getFieldMap() as $property => $fieldmap) {
233 3
            $fieldname = $fieldmap[Mapper::FIELDMAP_FIELD];
234 3
            $updateMask = $fieldmap[Mapper::FIELDMAP_UPDATEMASK];
235
236
            // Get the value from the mapped field name
237 3
            $value = $array[$property];
238 3
            unset($array[$property]);
239 3
            $updateValue = $updateMask($value, $instance);
240
241
            // If no value for UpdateMask, remove from the list;
242 3
            if ($updateValue === false) {
243 2
                continue;
244
            }
245 3
            $array[$fieldname] = $updateValue;
246
        }
247
248
        // Defines if is Insert or Update
249
        $isInsert =
250 10
            empty($array[$this->mapper->getPrimaryKey()])
251 10
            || ($this->get($array[$this->mapper->getPrimaryKey()]) === null)
252
        ;
253
254
        // Prepare query to insert
255 10
        $updatable = Updatable::getInstance()
256 10
            ->table($this->mapper->getTable())
257 10
            ->fields(array_keys($array));
258
259
        // Execute Before Statements
260 10
        if ($isInsert) {
261 6
            $closure = $this->beforeInsert;
262 6
            $array = $closure($array);
263
        } else {
264 4
            $closure = $this->beforeUpdate;
265 4
            $array = $closure($array);
266
        }
267
268
        // Check if is OK
269 10
        if (empty($array) || !is_array($array)) {
270
            throw new OrmBeforeInvalidException('Invalid Before Insert Closure');
271
        }
272
273
        // Execute the Insert or Update
274 10
        if ($isInsert) {
275 6
            $array[$this->mapper->getPrimaryKey()] = $this->insert($updatable, $array);
276
        } else {
277 4
            $this->update($updatable, $array);
278
        }
279
280 10
        BinderObject::bindObject($array, $instance);
281
282 10
        return $instance;
283
    }
284
285
    /**
286
     * @param \ByJG\MicroOrm\Updatable $updatable
287
     * @param array $params
288
     * @return int
289
     * @throws \ByJG\MicroOrm\Exception\OrmInvalidFieldsException
290
     */
291 6
    protected function insert(Updatable $updatable, array $params)
292
    {
293 6
        $keyGen = $this->getMapper()->generateKey();
294 6
        if (empty($keyGen)) {
295 5
            return $this->insertWithAutoinc($updatable, $params);
296
        } else {
297 1
            return $this->insertWithKeyGen($updatable, $params, $keyGen);
298
        }
299
    }
300
301
    /**
302
     * @param \ByJG\MicroOrm\Updatable $updatable
303
     * @param array $params
304
     * @return int
305
     * @throws \ByJG\MicroOrm\Exception\OrmInvalidFieldsException
306
     */
307 5
    protected function insertWithAutoinc(Updatable $updatable, array $params)
308
    {
309 5
        $sql = $updatable->buildInsert($params, $this->getDbDriver()->getDbHelper());
310 5
        $dbFunctions = $this->getDbDriver()->getDbHelper();
311 5
        return $dbFunctions->executeAndGetInsertedId($this->getDbDriver(), $sql, $params);
312
    }
313
314
    /**
315
     * @param \ByJG\MicroOrm\Updatable $updatable
316
     * @param array $params
317
     * @param $keyGen
318
     * @return mixed
319
     * @throws \ByJG\MicroOrm\Exception\OrmInvalidFieldsException
320
     */
321 1
    protected function insertWithKeyGen(Updatable $updatable, array $params, $keyGen)
322
    {
323 1
        $params[$this->mapper->getPrimaryKey()] = $keyGen;
324 1
        $sql = $updatable->buildInsert($params, $this->getDbDriver()->getDbHelper());
325 1
        $this->getDbDriver()->execute($sql, $params);
326 1
        return $keyGen;
327
    }
328
329
    /**
330
     * @param \ByJG\MicroOrm\Updatable $updatable
331
     * @param array $params
332
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
333
     */
334 4
    protected function update(Updatable $updatable, array $params)
335
    {
336 4
        $params = array_merge($params, ['_id' => $params[$this->mapper->getPrimaryKey()]]);
337 4
        $updatable->where($this->mapper->getPrimaryKey() . ' = [[_id]] ', ['_id' => $params['_id']]);
338
339 4
        $sql = $updatable->buildUpdate($params, $this->getDbDriver()->getDbHelper());
340
341 4
        $this->getDbDriver()->execute($sql, $params);
342 4
    }
343
344 1
    public function setBeforeUpdate(\Closure $closure)
345
    {
346 1
        $this->beforeUpdate = $closure;
347 1
    }
348
349 1
    public function setBeforeInsert(\Closure $closure)
350
    {
351 1
        $this->beforeInsert = $closure;
352 1
    }
353
}
354