Repository::getScalar()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1.0046

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 7
ccs 5
cts 6
cp 0.8333
crap 1.0046
rs 10
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