Passed
Push — master ( ae1a26...486cfe )
by Petr
03:11
created

ADatabase   F

Complexity

Total Complexity 71

Size/Duplication

Total Lines 304
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 71
eloc 150
c 1
b 0
f 0
dl 0
loc 304
ccs 149
cts 149
cp 1
rs 2.7199

11 Methods

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