Test Setup Failed
Push — master ( 1acfe1...735b89 )
by Joao
40s
created

Repository::getScalar()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

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