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

Repository::deleteByQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 8
ccs 0
cts 6
cp 0
crap 2
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
    public function __construct(DbDriverInterface $dbDataset, Mapper $mapper)
38
    {
39
        $this->dbDriver = $dbDataset;
40
        $this->mapper = $mapper;
41
        $this->beforeInsert = function ($instance) {
42
            return $instance;
43
        };
44
        $this->beforeUpdate = function ($instance) {
45
            return $instance;
46
        };
47
    }
48
49
    /**
50
     * @return Mapper
51
     */
52
    public function getMapper()
53
    {
54
        return $this->mapper;
55
    }
56
57
    /**
58
     * @return DbDriverInterface
59
     */
60
    protected function getDbDriver()
61
    {
62
        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
    public function get($pkId)
72
    {
73
        $result = $this->getByFilter($this->mapper->getPrimaryKey() . ' = [[id]]', ['id' => $pkId]);
74
75
        if (count($result) === 1) {
76
            return $result[0];
77
        }
78
79
        return null;
80
    }
81
82
    /**
83
     * @param array $pkId
84
     * @return mixed|null
85
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
86
     */
87
    public function delete($pkId)
88
    {
89
        $params = ['id' => $pkId];
90
        $updatable = Updatable::getInstance()
91
            ->table($this->mapper->getTable())
92
            ->where($this->mapper->getPrimaryKey() . ' = [[id]]', $params);
93
94
        return $this->deleteByQuery($updatable);
95
    }
96
97
    /**
98
     * @param \ByJG\MicroOrm\Updatable $updatable
99
     * @return bool
100
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
101
     */
102
    public function deleteByQuery(Updatable $updatable)
103
    {
104
        $params = [];
105
        $sql = $updatable->buildDelete($params);
106
107
        $this->getDbDriver()->execute($sql, $params);
108
109
        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
    public function getByFilter($filter, array $params, $forUpdate = false)
121
    {
122
        $query = new Query();
123
        $query->table($this->mapper->getTable())
124
            ->where($filter, $params);
125
        
126
        if ($forUpdate) {
127
            $query->forUpdate();
128
        }
129
130
        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
    public function filterIn($arrValues, $field = "") {
141
        $arrValues = (array) $arrValues;
142
143
        if (empty($field)) {
144
            $field = $this->getMapper()->getPrimaryKey();
145
        }
146
147
        return $this->getByFilter(
148
            $field . " in (:" . implode(',:', array_keys($arrValues)) . ')',
149
            $arrValues
150
        );
151
    }
152
153
    /**
154
     * @param \ByJG\MicroOrm\Query $query
155
     * @return mixed
156
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
157
     */
158
    public function getScalar(Query $query)
159
    {
160
        $query = $query->build($this->getDbDriver());
161
162
        $params = $query['params'];
163
        $sql = $query['sql'];
164
        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
    public function getByQuery(Query $query, array $mapper = [])
175
    {
176
        $mapper = array_merge([$this->mapper], $mapper);
177
        $query = $query->build($this->getDbDriver());
178
179
        $params = $query['params'];
180
        $sql = $query['sql'];
181
        $result = [];
182
        $iterator = $this->getDbDriver()->getIterator($sql, $params);
183
184
        foreach ($iterator as $row) {
185
            $collection = [];
186
            foreach ($mapper as $item) {
187
                $instance = $item->getEntity();
188
                $data = $row->toArray();
189
190
                foreach ((array)$item->getFieldAlias() as $fieldname => $fieldalias) {
191
                    if (isset($data[$fieldalias])) {
192
                        $data[$fieldname] = $data[$fieldalias];
193
                        unset($fieldalias);
194
                    }
195
                }
196
                BinderObject::bindObject($data, $instance);
197
198
                foreach ((array)$item->getFieldMap() as $property => $fieldmap) {
199
                    $selectMask = $fieldmap[Mapper::FIELDMAP_SELECTMASK];
200
                    $value = "";
201
                    if (isset($data[$fieldmap[Mapper::FIELDMAP_FIELD]])) {
202
                        $value = $data[$fieldmap[Mapper::FIELDMAP_FIELD]];
203
                    }
204
                    $data[$property] = $selectMask($value, $instance);
205
                }
206
                if (count($item->getFieldMap()) > 0) {
207
                    BinderObject::bindObject($data, $instance);
208
                }
209
                $collection[] = $instance;
210
            }
211
            $result[] = count($collection) === 1 ? $collection[0] : $collection;
212
        }
213
214
        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
    public function save($instance)
226
    {
227
        // Get all fields
228
        $array = BinderObject::toArrayFrom($instance, true);
229
        $array = $this->getMapper()->prepareField($array);
230
231
        // Mapping the data
232
        foreach ((array)$this->getMapper()->getFieldMap() as $property => $fieldmap) {
233
            $fieldname = $fieldmap[Mapper::FIELDMAP_FIELD];
234
            $updateMask = $fieldmap[Mapper::FIELDMAP_UPDATEMASK];
235
236
            // Get the value from the mapped field name
237
            $value = $array[$property];
238
            unset($array[$property]);
239
            $updateValue = $updateMask($value, $instance);
240
241
            // If no value for UpdateMask, remove from the list;
242
            if ($updateValue === false) {
243
                continue;
244
            }
245
            $array[$fieldname] = $updateValue;
246
        }
247
248
        // Defines if is Insert or Update
249
        $isInsert =
250
            empty($array[$this->mapper->getPrimaryKey()])
251
            || ($this->get($array[$this->mapper->getPrimaryKey()]) === null)
252
        ;
253
254
        // Prepare query to insert
255
        $updatable = Updatable::getInstance()
256
            ->table($this->mapper->getTable())
257
            ->fields(array_keys($array));
258
259
        // Execute Before Statements
260
        if ($isInsert) {
261
            $closure = $this->beforeInsert;
262
            $array = $closure($array);
263
        } else {
264
            $closure = $this->beforeUpdate;
265
            $array = $closure($array);
266
        }
267
268
        // Check if is OK
269
        if (empty($array) || !is_array($array)) {
270
            throw new OrmBeforeInvalidException('Invalid Before Insert Closure');
271
        }
272
273
        // Execute the Insert or Update
274
        if ($isInsert) {
275
            $array[$this->mapper->getPrimaryKey()] = $this->insert($updatable, $array);
276
        } else {
277
            $this->update($updatable, $array);
278
        }
279
280
        BinderObject::bindObject($array, $instance);
281
282
        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
    protected function insert(Updatable $updatable, array $params)
292
    {
293
        $keyGen = $this->getMapper()->generateKey();
294
        if (empty($keyGen)) {
295
            return $this->insertWithAutoinc($updatable, $params);
296
        } else {
297
            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
    protected function insertWithAutoinc(Updatable $updatable, array $params)
308
    {
309
        $sql = $updatable->buildInsert($params, $this->getDbDriver()->getDbHelper());
310
        $dbFunctions = $this->getDbDriver()->getDbHelper();
311
        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
    protected function insertWithKeyGen(Updatable $updatable, array $params, $keyGen)
322
    {
323
        $params[$this->mapper->getPrimaryKey()] = $keyGen;
324
        $sql = $updatable->buildInsert($params, $this->getDbDriver()->getDbHelper());
325
        $this->getDbDriver()->execute($sql, $params);
326
        return $keyGen;
327
    }
328
329
    /**
330
     * @param \ByJG\MicroOrm\Updatable $updatable
331
     * @param array $params
332
     * @throws \ByJG\MicroOrm\Exception\InvalidArgumentException
333
     */
334
    protected function update(Updatable $updatable, array $params)
335
    {
336
        $params = array_merge($params, ['_id' => $params[$this->mapper->getPrimaryKey()]]);
337
        $updatable->where($this->mapper->getPrimaryKey() . ' = [[_id]] ', ['_id' => $params['_id']]);
338
339
        $sql = $updatable->buildUpdate($params, $this->getDbDriver()->getDbHelper());
340
341
        $this->getDbDriver()->execute($sql, $params);
342
    }
343
344
    public function setBeforeUpdate(\Closure $closure)
345
    {
346
        $this->beforeUpdate = $closure;
347
    }
348
349
    public function setBeforeInsert(\Closure $closure)
350
    {
351
        $this->beforeInsert = $closure;
352
    }
353
}
354