Passed
Push — master ( 63f0e8...02118d )
by Petr
02:59
created

ADatabase   F

Complexity

Total Complexity 76

Size/Duplication

Total Lines 341
Duplicated Lines 0 %

Test Coverage

Coverage 99.42%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 170
c 1
b 0
f 0
dl 0
loc 341
ccs 170
cts 171
cp 0.9942
rs 2.32
wmc 76

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A getAlias() 0 3 1
A deleteRecord() 0 21 6
B countRecord() 0 34 8
B updateRecord() 0 26 8
B loadRecord() 0 36 8
C updateRecordByPk() 0 40 14
B loadMultiple() 0 33 8
A insertRecord() 0 16 5
B loadRecordByPk() 0 47 10
B deleteRecordByPk() 0 28 7

How to fix   Complexity   

Complex Class

Complex classes like ADatabase often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ADatabase, and based on these observations, apply Extract Interface, too.

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