Completed
Push — master ( 735b89...a9a16a )
by Joao
04:28
created

Repository::setBeforeUpdate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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