Passed
Push — master ( f2aa8d...153a1c )
by Petr
13:28 queued 05:17
created

ADatabase::updateRecord()   B

Complexity

Conditions 8
Paths 13

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 15
nc 13
nop 1
dl 0
loc 24
ccs 15
cts 15
cp 1
crap 8
rs 8.4444
c 1
b 0
f 0
1
<?php
2
3
namespace kalanis\kw_mapper\Mappers\Database;
4
5
6
use kalanis\kw_mapper\Interfaces\IQueryBuilder;
7
use kalanis\kw_mapper\MapperException;
8
use kalanis\kw_mapper\Mappers\AMapper;
9
use kalanis\kw_mapper\Records\ARecord;
10
use kalanis\kw_mapper\Records\TFill;
11
use kalanis\kw_mapper\Storage;
12
13
14
/**
15
 * Class ADatabase
16
 * @package kalanis\kw_mapper\Mappers\Database
17
 */
18
abstract class ADatabase extends AMapper
19
{
20
    use TFill;
21
    use TTable;
22
23
    /** @var Storage\Database\ASQL */
24
    protected $database = null;
25
    /** @var Storage\Database\Dialects\ADialect */
26
    protected $dialect = null;
27
    /** @var Storage\Database\QueryBuilder */
28
    protected $queryBuilder = null;
29
30
    /**
31
     * @throws MapperException
32
     */
33 12
    public function __construct()
34
    {
35 12
        parent::__construct();
36 12
        $config = Storage\Database\ConfigStorage::getInstance()->getConfig($this->getSource());
37 12
        $this->database = Storage\Database\DatabaseSingleton::getInstance()->getDatabase($config);
38 12
        $this->dialect = Storage\Database\Dialects\Factory::getInstance()->getDialectClass($this->database->languageDialect());
39 12
        $this->queryBuilder = new Storage\Database\QueryBuilder($this->dialect);
40
    }
41
42 22
    public function getAlias(): string
43
    {
44 22
        return $this->getTable();
45
    }
46
47 3
    protected function insertRecord(ARecord $record): bool
48
    {
49 3
        $this->queryBuilder->clear();
50 3
        $this->queryBuilder->setBaseTable($this->getTable());
51 3
        foreach ($record as $key => $item) {
52 3
            if (isset($this->relations[$key]) && (false !== $item)) {
53 2
                $this->queryBuilder->addProperty($this->getTable(), $this->relations[$key], $item);
54
            }
55
        }
56 3
        if (empty($this->queryBuilder->getProperties())) {
57 1
            return false;
58
        }
59
60 2
        return $this->database->exec(strval($this->dialect->insert($this->queryBuilder)), $this->queryBuilder->getParams());
61
    }
62
63 4
    protected function updateRecord(ARecord $record): bool
64
    {
65 4
        if ($this->updateRecordByPk($record)) {
66 2
            return true;
67
        }
68 4
        $this->queryBuilder->clear();
69 4
        $this->queryBuilder->setBaseTable($this->getTable());
70 4
        foreach ($record as $key => $item) {
71 4
            if (isset($this->relations[$key]) && (false !== $item)) {
72 4
                if ($record->getEntry($key)->isFromStorage()) {
73 3
                    $this->queryBuilder->addCondition($this->getTable(), $this->relations[$key], IQueryBuilder::OPERATION_EQ, $item);
74
                } else {
75 3
                    $this->queryBuilder->addProperty($this->getTable(), $this->relations[$key], $item);
76
                }
77
            }
78
        }
79 4
        if (empty($this->queryBuilder->getConditions())) {
80 1
            return false;
81
        }
82 3
        if (empty($this->queryBuilder->getProperties())) {
83 1
            return false;
84
        }
85
86 2
        return $this->database->exec(strval($this->dialect->update($this->queryBuilder)), $this->queryBuilder->getParams());
87
    }
88
89
    /**
90
     * @param ARecord $record
91
     * @throws MapperException
92
     * @return bool
93
     */
94 6
    protected function updateRecordByPk(ARecord $record): bool
95
    {
96 6
        if (empty($record->getMapper()->getPrimaryKeys())) {
97 1
            return false;
98
        }
99
100 5
        $this->queryBuilder->clear();
101 5
        $this->queryBuilder->setBaseTable($this->getTable());
102 5
        foreach ($record->getMapper()->getPrimaryKeys() as $key) {
103
            try {
104 5
                if (isset($this->relations[$key])) {
105 5
                    $entry = $record->getEntry($key);
106 4
                    if ($entry->isFromStorage() && (false !== $entry->getData())) {
107 4
                        $this->queryBuilder->addCondition($this->getTable(), $this->relations[$key], IQueryBuilder::OPERATION_EQ, $entry->getData());
108
                    }
109
                }
110 1
            } catch (MapperException $ex) {
111 1
                return false;
112
            }
113
        }
114
115 4
        if (empty($this->queryBuilder->getConditions())) { // no conditions, nothing in PKs - back to normal system
116 3
            return false;
117
        }
118
119 3
        foreach ($record as $key => $item) {
120 3
            if (isset($this->relations[$key])) {
121 3
                $entry = $record->getEntry($key);
122 3
                if (!in_array($key, $record->getMapper()->getPrimaryKeys()) && !$entry->isFromStorage() && (false !== $item)) {
123 2
                    $this->queryBuilder->addProperty($this->getTable(), $this->relations[$key], $item);
124
                }
125
            }
126
        }
127 3
        if (empty($this->queryBuilder->getProperties())) {
128 1
            return false;
129
        }
130
131 2
        return $this->database->exec(strval($this->dialect->update($this->queryBuilder)), $this->queryBuilder->getParams());
132
    }
133
134 4
    protected function loadRecord(ARecord $record): bool
135
    {
136 4
        if ($this->loadRecordByPk($record)) {
137 2
            return true;
138
        }
139
140 4
        $this->queryBuilder->clear();
141 4
        $this->queryBuilder->setBaseTable($this->getTable());
142
143
        // conditions - must be equal
144 4
        foreach ($record as $key => $item) {
145 4
            if (isset($this->relations[$key]) && (false !== $item)) {
146 3
                $this->queryBuilder->addCondition($this->getTable(), $this->relations[$key], IQueryBuilder::OPERATION_EQ, $item);
147
            }
148
        }
149
150 4
        if (empty($this->queryBuilder->getConditions())) {
151 1
            return false;
152
        }
153
154
        // relations - what to get
155 3
        foreach ($this->relations as $localAlias => $remoteColumn) {
156 3
            $this->queryBuilder->addColumn($this->getTable(), $remoteColumn, $localAlias);
157
        }
158 3
        $this->queryBuilder->setLimits(0,1);
159
160
        // query itself
161 3
        $lines = $this->database->query(strval($this->dialect->select($this->queryBuilder)), $this->queryBuilder->getParams());
162 3
        if (empty($lines)) {
163 1
            return false;
164
        }
165
166
        // fill entries in record
167 2
        $line = reset($lines);
168 2
        foreach ($line as $index => $item) {
169 2
            $entry = $record->getEntry($index);
170 2
            $entry->setData($this->typedFillSelection($entry, $item), true);
171
        }
172 2
        return true;
173
    }
174
175
    /**
176
     * @param ARecord $record
177
     * @throws MapperException
178
     * @return bool
179
     */
180 5
    protected function loadRecordByPk(ARecord $record): bool
181
    {
182 5
        if (empty($record->getMapper()->getPrimaryKeys())) {
183 1
            return false;
184
        }
185
186 4
        $this->queryBuilder->clear();
187 4
        $this->queryBuilder->setBaseTable($this->getTable());
188
189
        // conditions - everything must be equal
190 4
        foreach ($record->getMapper()->getPrimaryKeys() as $key) {
191
            try {
192 4
                if (isset($this->relations[$key])) {
193 4
                    $item = $record->offsetGet($key);
194 3
                    if (false !== $item) {
195 3
                        $this->queryBuilder->addCondition($this->getTable(), $this->relations[$key], IQueryBuilder::OPERATION_EQ, $item);
196
                    }
197
                }
198 1
            } catch (MapperException $ex) {
199 1
                return false;
200
            }
201
        }
202
203 3
        if (empty($this->queryBuilder->getConditions())) { // no conditions, nothing in PKs - back to normal system
204 2
            return false;
205
        }
206
207
        // relations - what to get
208 3
        foreach ($this->relations as $localAlias => $remoteColumn) {
209 3
            $this->queryBuilder->addColumn($this->getTable(), $remoteColumn, $localAlias);
210
        }
211
212
        // query itself
213 3
        $this->queryBuilder->setLimits(0,1);
214 3
        $lines = $this->database->query(strval($this->dialect->select($this->queryBuilder)), $this->queryBuilder->getParams());
215 3
        if (empty($lines)) {
216 1
            return false;
217
        }
218
219
        // fill entries in record
220 2
        $line = reset($lines);
221 2
        foreach ($line as $index => $item) {
222 2
            $entry = $record->getEntry($index);
223 2
            $entry->setData($this->typedFillSelection($entry, $item), true);
224
        }
225 2
        return true;
226
    }
227
228 3
    public function countRecord(ARecord $record): int
229
    {
230 3
        $this->queryBuilder->clear();
231 3
        $this->queryBuilder->setBaseTable($this->getTable());
232 3
        foreach ($record as $key => $item) {
233 3
            if (isset($this->relations[$key]) && (false !== $item)) {
234 3
                $this->queryBuilder->addCondition($this->getTable(), $this->relations[$key], IQueryBuilder::OPERATION_EQ, $item);
235
            }
236
        }
237
238 3
        if (empty($this->queryBuilder->getConditions())) {
239 1
            return 0;
240
        }
241
242 3
        if (empty($record->getMapper()->getPrimaryKeys())) {
243 1
            $relation = reset($this->relations);
244 1
            if (false !== $relation) {
245 1
                $this->queryBuilder->addColumn($this->getTable(), $relation, 'count', IQueryBuilder::AGGREGATE_COUNT);
246
            }
247
        } else {
248
//            foreach ($record->getMapper()->getPrimaryKeys() as $primaryKey) {
249
//                $this->queryBuilder->addColumn($this->getTable(), $primaryKey, '', IQueryBuilder::AGGREGATE_COUNT);
250
//            }
251 2
            $pks = $record->getMapper()->getPrimaryKeys();
252 2
            $key = reset($pks);
253 2
            $this->queryBuilder->addColumn($this->getTable(), $this->relations[$key], 'count', IQueryBuilder::AGGREGATE_COUNT);
254
        }
255
256 3
        $lines = $this->database->query(strval($this->dialect->select($this->queryBuilder)), $this->queryBuilder->getParams());
257 3
        if (empty($lines) || !is_iterable($lines)) {
258
            // @codeCoverageIgnoreStart
259
            return 0;
260
        }
261
        // @codeCoverageIgnoreEnd
262 3
        $line = reset($lines);
263 3
        return intval(reset($line));
264
    }
265
266 4
    protected function deleteRecord(ARecord $record): bool
267
    {
268 4
        if ($this->deleteRecordByPk($record)) {
269 1
            return true;
270
        }
271
272 3
        $this->queryBuilder->clear();
273 3
        $this->queryBuilder->setBaseTable($this->getTable());
274 3
        foreach ($record as $key => $item) {
275 3
            if (isset($this->relations[$key]) && (false !== $item)) {
276 2
                $this->queryBuilder->addCondition($this->getTable(), $this->relations[$key], IQueryBuilder::OPERATION_EQ, $item);
277
            }
278
        }
279
280 3
        if (empty($this->queryBuilder->getConditions())) {
281 1
            return false;
282
        }
283
284 2
        return $this->database->exec(strval($this->dialect->delete($this->queryBuilder)), $this->queryBuilder->getParams());
285
    }
286
287
    /**
288
     * @param ARecord $record
289
     * @throws MapperException
290
     * @return bool
291
     */
292 6
    protected function deleteRecordByPk(ARecord $record): bool
293
    {
294 6
        if (empty($record->getMapper()->getPrimaryKeys())) {
295 1
            return false;
296
        }
297
298 5
        $this->queryBuilder->clear();
299 5
        $this->queryBuilder->setBaseTable($this->getTable());
300 5
        foreach ($record->getMapper()->getPrimaryKeys() as $key) {
301
            try {
302 5
                if (isset($this->relations[$key])) {
303 5
                    $item = $record->offsetGet($key);
304 4
                    if (false !== $item) {
305 4
                        $this->queryBuilder->addCondition($this->getTable(), $this->relations[$key], IQueryBuilder::OPERATION_EQ, $item);
306
                    }
307
                }
308 1
            } catch (MapperException $ex) {
309 1
                return false;
310
            }
311
        }
312
313 4
        if (empty($this->queryBuilder->getConditions())) { // no conditions, nothing in PKs - back to normal system
314 3
            return false;
315
        }
316
317 1
        return $this->database->exec(strval($this->dialect->delete($this->queryBuilder)), $this->queryBuilder->getParams());
318
    }
319
320 3
    public function loadMultiple(ARecord $record): array
321
    {
322 3
        $this->queryBuilder->clear();
323 3
        $this->queryBuilder->setBaseTable($this->getTable());
324 3
        foreach ($record as $key => $item) {
325 3
            if (isset($this->relations[$key]) && (false !== $item)) {
326 3
                $this->queryBuilder->addCondition($this->getTable(), $this->relations[$key], IQueryBuilder::OPERATION_EQ, $item);
327
            }
328
        }
329
330 3
        if (empty($this->queryBuilder->getConditions())) {
331 1
            return [];
332
        }
333
334
        // relations - what to get
335 3
        foreach ($this->relations as $localAlias => $remoteColumn) {
336 3
            $this->queryBuilder->addColumn($this->getTable(), $remoteColumn, $localAlias);
337
        }
338
339
        // query itself
340 3
        $lines = $this->database->query(strval($this->dialect->select($this->queryBuilder)), $this->queryBuilder->getParams());
341 3
        if (empty($lines)) {
342 1
            return [];
343
        }
344
345 2
        $result = [];
346 2
        foreach ($lines as $line) {
347 2
            $rec = clone $record;
348 2
            foreach ($line as $index => $item) {
349 2
                $entry = $rec->getEntry($index);
350 2
                $entry->setData($this->typedFillSelection($entry, $item), true);
351
            }
352 2
            $result[] = $rec;
353
        }
354 2
        return $result;
355
    }
356
}
357