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

Repository::save()   B

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