Repository::save()   B
last analyzed

Complexity

Conditions 8
Paths 36

Size

Total Lines 58
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 9.4367

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 8
eloc 31
c 3
b 0
f 0
nc 36
nop 1
dl 0
loc 58
ccs 28
cts 39
cp 0.7179
crap 9.4367
rs 8.1795

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 30
    public function __construct(DbDriverInterface $dbDataset, Mapper $mapper)
38
    {
39 30
        $this->dbDriver = $dbDataset;
40 30
        $this->mapper = $mapper;
41
        $this->beforeInsert = function ($instance) {
42 5
            return $instance;
43
        };
44
        $this->beforeUpdate = function ($instance) {
45 3
            return $instance;
46
        };
47 30
    }
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 30
    protected function getDbDriver()
61
    {
62 30
        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 29
    public function getByQuery(Query $query, array $mapper = [])
175
    {
176 29
        $mapper = array_merge([$this->mapper], $mapper);
177 29
        $query = $query->build($this->getDbDriver());
178
179 29
        $params = $query['params'];
180 29
        $sql = $query['sql'];
181 29
        $result = [];
182 29
        $iterator = $this->getDbDriver()->getIterator($sql, $params);
183
184 29
        foreach ($iterator as $row) {
185 27
            $collection = [];
186 27
            foreach ($mapper as $item) {
187 27
                $instance = $item->getEntity();
188 27
                $data = $row->toArray();
189
190 27
                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 27
                BinderObject::bindObject($data, $instance);
197
198 27
                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 27
                if (count($item->getFieldMap()) > 0) {
207 11
                    BinderObject::bindObject($data, $instance);
208
                }
209 27
                $collection[] = $instance;
210
            }
211 27
            $result[] = count($collection) === 1 ? $collection[0] : $collection;
212
        }
213
214 29
        return $result;
215
    }
216
217
    /**
218
     * Get by Query without map to an instance.
219
     *
220
     * @param Query $query
221
     * @return array
222
     * @throws Exception\InvalidArgumentException
223
     * @throws \ByJG\Serializer\Exception\InvalidArgumentException
224
     */
225 1
    public function getByQueryRaw(Query $query)
226
    {
227 1
        $query = $query->build($this->getDbDriver());
228 1
        $iterator = $this->getDbDriver()->getIterator($query['sql'], $query['params']);
229 1
        return $iterator->toArray();
230
    }
231
232
    /**
233
     * @param mixed $instance
234
     * @return mixed
235
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
236
     * @throws \ByJG\MicroOrm\Exception\OrmBeforeInvalidException
237
     * @throws \ByJG\MicroOrm\Exception\OrmInvalidFieldsException
238
     * @throws \ByJG\Serializer\Exception\InvalidArgumentException
239
     */
240 10
    public function save($instance)
241
    {
242
        // Get all fields
243 10
        $array = BinderObject::toArrayFrom($instance, true);
244 10
        $array = $this->getMapper()->prepareField($array);
245
246
        // Mapping the data
247 10
        foreach ((array)$this->getMapper()->getFieldMap() as $property => $fieldmap) {
248 3
            $fieldname = $fieldmap[Mapper::FIELDMAP_FIELD];
249 3
            $updateMask = $fieldmap[Mapper::FIELDMAP_UPDATEMASK];
250
251
            // Get the value from the mapped field name
252 3
            $value = $array[$property];
253 3
            unset($array[$property]);
254 3
            $updateValue = $updateMask($value, $instance);
255
256
            // If no value for UpdateMask, remove from the list;
257 3
            if ($updateValue === false) {
258 2
                continue;
259
            }
260 3
            $array[$fieldname] = $updateValue;
261
        }
262
263
        // Defines if is Insert or Update
264
        $isInsert =
265 10
            empty($array[$this->mapper->getPrimaryKey()])
266 10
            || ($this->get($array[$this->mapper->getPrimaryKey()]) === null)
267
        ;
268
269
        // Prepare query to insert
270 10
        $updatable = Updatable::getInstance()
271 10
            ->table($this->mapper->getTable())
272 10
            ->fields(array_keys($array));
273
274
        // Execute Before Statements
275 10
        if ($isInsert) {
276 6
            $closure = $this->beforeInsert;
277 6
            $array = $closure($array);
278
        } else {
279 4
            $closure = $this->beforeUpdate;
280 4
            $array = $closure($array);
281
        }
282
283
        // Check if is OK
284 10
        if (empty($array) || !is_array($array)) {
285
            throw new OrmBeforeInvalidException('Invalid Before Insert Closure');
286
        }
287
288
        // Execute the Insert or Update
289 10
        if ($isInsert) {
290 6
            $array[$this->mapper->getPrimaryKey()] = $this->insert($updatable, $array);
291
        } else {
292 4
            $this->update($updatable, $array);
293
        }
294
295 10
        BinderObject::bindObject($array, $instance);
296
297 10
        return $instance;
298
    }
299
300
    /**
301
     * @param \ByJG\MicroOrm\Updatable $updatable
302
     * @param array $params
303
     * @return int
304
     * @throws \ByJG\MicroOrm\Exception\OrmInvalidFieldsException
305
     */
306 6
    protected function insert(Updatable $updatable, array $params)
307
    {
308 6
        $keyGen = $this->getMapper()->generateKey();
309 6
        if (empty($keyGen)) {
310 5
            return $this->insertWithAutoinc($updatable, $params);
311
        } else {
312 1
            return $this->insertWithKeyGen($updatable, $params, $keyGen);
313
        }
314
    }
315
316
    /**
317
     * @param \ByJG\MicroOrm\Updatable $updatable
318
     * @param array $params
319
     * @return int
320
     * @throws \ByJG\MicroOrm\Exception\OrmInvalidFieldsException
321
     */
322 5
    protected function insertWithAutoinc(Updatable $updatable, array $params)
323
    {
324 5
        $sql = $updatable->buildInsert($params, $this->getDbDriver()->getDbHelper());
325 5
        $dbFunctions = $this->getDbDriver()->getDbHelper();
326 5
        return $dbFunctions->executeAndGetInsertedId($this->getDbDriver(), $sql, $params);
327
    }
328
329
    /**
330
     * @param \ByJG\MicroOrm\Updatable $updatable
331
     * @param array $params
332
     * @param $keyGen
333
     * @return mixed
334
     * @throws \ByJG\MicroOrm\Exception\OrmInvalidFieldsException
335
     */
336 1
    protected function insertWithKeyGen(Updatable $updatable, array $params, $keyGen)
337
    {
338 1
        $params[$this->mapper->getPrimaryKey()] = $keyGen;
339 1
        $sql = $updatable->buildInsert($params, $this->getDbDriver()->getDbHelper());
340 1
        $this->getDbDriver()->execute($sql, $params);
341 1
        return $keyGen;
342
    }
343
344
    /**
345
     * @param \ByJG\MicroOrm\Updatable $updatable
346
     * @param array $params
347
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
348
     */
349 4
    protected function update(Updatable $updatable, array $params)
350
    {
351 4
        $params = array_merge($params, ['_id' => $params[$this->mapper->getPrimaryKey()]]);
352 4
        $updatable->where($this->mapper->getPrimaryKey() . ' = [[_id]] ', ['_id' => $params['_id']]);
353
354 4
        $sql = $updatable->buildUpdate($params, $this->getDbDriver()->getDbHelper());
355
356 4
        $this->getDbDriver()->execute($sql, $params);
357 4
    }
358
359 1
    public function setBeforeUpdate(\Closure $closure)
360
    {
361 1
        $this->beforeUpdate = $closure;
362 1
    }
363
364 1
    public function setBeforeInsert(\Closure $closure)
365
    {
366 1
        $this->beforeInsert = $closure;
367 1
    }
368
}
369