AbstractDatabase   F
last analyzed

Complexity

Total Complexity 84

Size/Duplication

Total Lines 546
Duplicated Lines 0 %

Test Coverage

Coverage 95.02%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 84
eloc 178
c 2
b 0
f 0
dl 0
loc 546
ccs 191
cts 201
cp 0.9502
rs 2

37 Methods

Rating   Name   Duplication   Size   Complexity  
A getLastErrorNo() 0 3 1
A getLastError() 0 3 1
A getFullTableName() 0 9 2
A getTableName() 0 9 3
A connect() 0 16 2
A rollback() 0 3 1
A truncate() 0 5 2
A makeArray() 0 11 4
A save() 0 15 4
A disconnect() 0 8 1
A isResult() 0 3 1
A getColumnNames() 0 6 2
A getDriver() 0 3 1
A delete() 0 9 2
A getValue() 0 8 2
A selectDb() 0 9 1
A optimize() 0 8 3
A fieldName() 0 3 1
A getRecordCount() 0 3 1
A query() 0 31 4
A getTableMetaData() 0 10 2
A setDriver() 0 16 3
A numFields() 0 3 1
A getVersion() 0 3 1
A getAffectedRows() 0 3 1
A begin() 0 3 1
A getInsertId() 0 4 1
A select() 0 9 1
A alterTable() 0 5 2
B insertFrom() 0 34 10
A escape() 0 19 5
A update() 0 11 3
A commit() 0 3 1
A getColumn() 0 7 2
B insert() 0 29 8
A setCharset() 0 3 1
A getRow() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like AbstractDatabase 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 AbstractDatabase, and based on these observations, apply Extract Interface, too.

1
<?php namespace AgelxNash\Modx\Evo\Database;
2
3
abstract class AbstractDatabase implements Interfaces\DatabaseInterface, Interfaces\DebugInterface
4
{
5
    use Traits\DebugTrait,
6
        Traits\SupportTrait,
7
        Traits\ConfigTrait;
8
9
    /**
10
     * @var Interfaces\DriverInterface
11
     */
12
    protected $driver;
13
14
    /**
15
     * @var int
16
     */
17
    protected $safeLoopCount = 1000;
18
19
    /**
20
     * {@inheritDoc}
21
     */
22 2
    public function getLastError()
23
    {
24 2
        return $this->getDriver()->getLastError();
25
    }
26
27
    /**
28
     * {@inheritDoc}
29
     */
30 6
    public function getLastErrorNo()
31
    {
32 6
        return (string)$this->getDriver()->getLastErrorNo();
33
    }
34
35
    /**
36
     * {@inheritDoc}
37
     */
38 59
    public function connect()
39
    {
40 59
        $tStart = microtime(true);
41
42 59
        $out = $this->getDriver()->getConnect();
43
44 58
        $totalTime = microtime(true) - $tStart;
45 58
        if ($this->isDebug()) {
46 58
            $this->setConnectionTime($totalTime);
47
        }
48 58
        $this->setCharset(
49 58
            $this->getConfig('charset'),
50 58
            $this->getConfig('method')
51
        );
52
53 58
        return $out;
54
    }
55
56
    /**
57
     * {@inheritDoc}
58
     */
59 4
    public function disconnect()
60
    {
61 4
        $this->getDriver()->disconnect();
62
63 4
        $this->setConnectionTime(0);
64 4
        $this->flushExecutedQuery();
65
66 4
        return true;
67
    }
68
69
    /**
70
     * {@inheritDoc}
71
     */
72 13
    public function isResult($result)
73
    {
74 13
        return $this->getDriver()->isResult($result);
75
    }
76
77
    /**
78
     * {@inheritDoc}
79
     */
80 2
    public function numFields($result)
81
    {
82 2
        return $this->getDriver()->numFields($result);
83
    }
84
85
    /**
86
     * {@inheritDoc}
87
     */
88 2
    public function fieldName($result, $col = 0)
89
    {
90 2
        return $this->getDriver()->fieldName($result, $col);
91
    }
92
93
    /**
94
     * {@inheritDoc}
95
     */
96 58
    public function setCharset($charset, $method = null)
97
    {
98 58
        return $this->getDriver()->setCharset($charset, $method);
99
    }
100
101
    /**
102
     * {@inheritDoc}
103
     */
104 2
    public function selectDb($name)
105
    {
106 2
        $tStart = microtime(true);
107
108 2
        $result = $this->getDriver()->selectDb($name);
109
110 2
        $this->addQueriesTime(microtime(true) - $tStart);
111
112 2
        return $result;
113
    }
114
115
    /**
116
     * {@inheritDoc}
117
     * @throws Exceptions\TooManyLoopsException
118
     */
119 2
    public function escape($data, $safeCount = 0)
120
    {
121 2
        $safeCount++;
122 2
        if ($this->safeLoopCount < $safeCount) {
123 2
            throw new Exceptions\TooManyLoopsException("Too many loops '{$safeCount}'");
124
        }
125 2
        if (\is_array($data)) {
126 2
            if (\count($data) === 0) {
127 2
                $data = '';
128
            } else {
129 2
                foreach ($data as $i => $v) {
130 2
                    $data[$i] = $this->escape($v, $safeCount);
131
                }
132
            }
133
        } else {
134 2
            $data = $this->getDriver()->escape($data);
135
        }
136
137 2
        return $data;
138
    }
139
140
    /**
141
     * @param string|array $sql
142
     * {@inheritDoc}
143
     */
144 45
    public function query($sql)
145
    {
146 45
        $tStart = microtime(true);
147 45
        if (\is_array($sql)) {
148 2
            $sql = implode("\n", $sql);
149
        }
150 45
        $this->setLastQuery($sql);
151
152 45
        $result = $this->getDriver()->query(
153 45
            $this->getLastQuery()
154
        );
155
156 43
        if ($result === false) {
157
            /**
158
             * @TODO: NOT WORK?
159
             */
160
            $this->checkLastError($this->getLastQuery());
161
        } else {
162 43
            $tend = microtime(true);
163 43
            $totalTime = $tend - $tStart;
164 43
            $this->addQueriesTime($totalTime);
165 43
            if ($this->isDebug()) {
166 43
                $this->collectQuery(
167 43
                    $result,
168 43
                    $this->getLastQuery(),
169 43
                    $totalTime
170
                );
171
            }
172
        }
173
174 43
        return $result;
175
    }
176
177
    /**
178
     * {@inheritDoc}
179
     */
180 33
    public function getRecordCount($result)
181
    {
182 33
        return $this->getDriver()->getRecordCount($result);
183
    }
184
185
    /**
186
     * {@inheritDoc}
187
     */
188 7
    public function getRow($result, $mode = 'assoc')
189
    {
190 7
        if (\is_scalar($result)) {
191 3
            $result = $this->query($result);
192
        }
193
194 7
        return $this->getDriver()->getRow($result, $mode);
195
    }
196
197
    /**
198
     * {@inheritDoc}
199
     */
200 4
    public function getVersion()
201
    {
202 4
        return $this->getDriver()->getVersion();
203
    }
204
205
    /**
206
     * {@inheritDoc}
207
     */
208 14
    public function getInsertId()
209
    {
210 14
        return $this->convertValue(
211 14
            $this->getDriver()->getInsertId()
212
        );
213
    }
214
215
    /**
216
     * {@inheritDoc}
217
     */
218 22
    public function getAffectedRows()
219
    {
220 22
        return $this->getDriver()->getAffectedRows();
221
    }
222
223
    /**
224
     * {@inheritDoc}
225
     */
226 6
    public function getColumn($name, $result)
227
    {
228 6
        if (\is_scalar($result)) {
229 6
            $result = $this->query($result);
230
        }
231
232 6
        return $this->getDriver()->getColumn($name, $result);
233
    }
234
235
    /**
236
     * {@inheritDoc}
237
     */
238 2
    public function getColumnNames($result)
239
    {
240 2
        if (\is_scalar($result)) {
241 2
            $result = $this->query($result);
242
        }
243 2
        return $this->getDriver()->getColumnNames($result);
244
    }
245
246
    /**
247
     * {@inheritDoc}
248
     */
249 14
    public function getValue($result)
250
    {
251 14
        if (\is_scalar($result)) {
252 8
            $result = $this->query($result);
253
        }
254
255 14
        return $this->convertValue(
256 14
            $this->getDriver()->getValue($result)
257
        );
258
    }
259
260
    /**
261
     * {@inheritDoc}
262
     */
263 2
    public function getTableMetaData($table)
264
    {
265 2
        $metadata = [];
266 2
        if (! empty($table)) {
267 2
            $sql = 'SHOW FIELDS FROM ' . $table;
268 2
            $result = $this->query($sql);
269 2
            $metadata = $this->getDriver()->getTableMetaData($result);
270
        }
271
272 2
        return $metadata;
273
    }
274
275
    /**
276
     * {@inheritDoc}
277
     */
278 62
    public function getDriver()
279
    {
280 62
        return $this->driver;
281
    }
282
283
    /**
284
     * {@inheritDoc}
285
     */
286 85
    public function setDriver($driver)
287
    {
288 85
        if (! \in_array(Interfaces\DriverInterface::class, class_implements($driver), true)) {
289 1
            throw new Exceptions\DriverException(
290 1
                $driver . ' should implements the ' . Interfaces\DriverInterface::class
291
            );
292
        }
293
294 85
        if (is_scalar($driver)) {
295 82
            $this->driver = new $driver($this->getConfig());
296
        } else {
297 3
            $this->driver = $driver;
298 3
            $this->config = array_merge($this->config, $driver->getConfig());
299
        }
300
301 85
        return $this->driver;
302
    }
303
304
    /**
305
     * {@inheritDoc}
306
     */
307 2
    public function makeArray($result, $index = false)
308
    {
309 2
        $rsArray = [];
310 2
        $iterator = 0;
311 2
        while ($row = $this->getRow($result)) {
312 2
            $returnIndex = $index !== false && isset($row[$index]) ? $row[$index] : $iterator;
313 2
            $rsArray[$returnIndex] = $row;
314 2
            $iterator++;
315
        }
316
317 2
        return $rsArray;
318
    }
319
320
    /**
321
     * {@inheritDoc}
322
     */
323 2
    public function delete($table, $where = '', $orderBy = '', $limit = '')
324
    {
325 2
        $table = $this->prepareFrom($table);
326 2
        $where = $this->prepareWhere($where);
327 2
        $orderBy = $this->prepareOrder($orderBy);
328 2
        $limit = $this->prepareLimit($limit);
329
330 2
        $result = $this->query("DELETE FROM {$table} {$where} {$orderBy} {$limit}");
331 2
        return $this->isResult($result) ? true : $result;
332
    }
333
334
    /**
335
     * {@inheritDoc}
336
     */
337 6
    public function select($fields, $tables, $where = '', $orderBy = '', $limit = '')
338
    {
339 6
        $fields = $this->prepareFields($fields);
340 6
        $tables = $this->prepareFrom($tables, true);
341 6
        $where = $this->prepareWhere($where);
342 6
        $orderBy = $this->prepareOrder($orderBy);
343 6
        $limit = $this->prepareLimit($limit);
344
345 6
        return $this->query("SELECT {$fields} FROM {$tables} {$where} {$orderBy} {$limit}");
346
    }
347
348
    /**
349
     * {@inheritDoc}
350
     */
351 4
    public function update($values, $table, $where = '')
352
    {
353 4
        $table = $this->prepareFrom($table);
354 4
        $values = $this->prepareValuesSet($values);
355 4
        if (mb_strtoupper(mb_substr($values, 0, 4)) !== 'SET ') {
356 4
            $values = 'SET ' . $values;
357
        }
358 4
        $where = $this->prepareWhere($where);
359
360 4
        $result = $this->query("UPDATE {$table} {$values} {$where}");
361 4
        return $this->isResult($result) ? true : $result;
362
    }
363
364
    /**
365
     * {@inheritDoc}
366
     */
367 15
    public function insert(
368
        $fields,
369
        $table,
370
        $fromFields = '*',
371
        $fromTable = '',
372
        $where = '',
373
        $limit = ''
374
    ) {
375 15
        $lid = null;
376
377 15
        if (empty($fromTable)) {
378 13
            $table = $this->prepareFrom($table);
379 13
            $useFields = \is_array($fields) ? $this->prepareValues($fields) : $fields;
380
381 13
            if (empty($useFields) || ! \is_scalar($useFields) || $useFields === '*') {
382 1
                throw (new Exceptions\InvalidFieldException('Invalid insert fields'))
383 1
                    ->setData($fields);
384
            }
385
386 12
            $this->query("INSERT INTO {$table} {$useFields}");
387
        } else {
388 2
            $lid = $this->insertFrom($fields, $table, $fromFields, $fromTable, $where, $limit);
389
        }
390
391 14
        if ($lid === null && ($lid = $this->getInsertId()) === false) {
392
            throw new Exceptions\GetDataException("Couldn't get last insert key!");
393
        }
394
395 14
        return $this->convertValue($lid);
396
    }
397
398
    /**
399
     * @param string|array $fields
400
     * @param string $table
401
     * @param string|array $fromFields
402
     * @param string $fromTable
403
     * @param string|array $where
404
     * @param string $limit
405
     * @return mixed
406
     * @throws Exceptions\InvalidFieldException
407
     * @throws Exceptions\TableNotDefinedException
408
     */
409 2
    public function insertFrom(
410
        $fields,
411
        $table,
412
        $fromFields = '*',
413
        $fromTable = '',
414
        $where = '',
415
        $limit = ''
416
    ) {
417 2
        $table = $this->prepareFrom($table);
418 2
        $useFields = \is_array($fields) ? $this->prepareFields($fields, true) : $fields;
419
420 2
        if (empty($useFields) || ! \is_scalar($useFields) || $useFields === '*') {
421
            throw (new Exceptions\InvalidFieldException('Invalid insert fields'))
422
                ->setData($fields);
423
        }
424
425 2
        if (empty($fromFields) || $fromFields === '*') {
426 2
            $fromFields = $this->prepareFields($fields, true);
427
        } else {
428 2
            $fromFields = $this->prepareFields($fromFields, true);
429
        }
430
431 2
        $where = $this->prepareWhere($where);
432 2
        $limit = $this->prepareLimit($limit);
433
434 2
        $lid = $this->query(
435 2
            "INSERT INTO {$table} ({$useFields}) SELECT {$fromFields} FROM {$fromTable} {$where} {$limit}"
436
        );
437
438 2
        $lid = $this->isResult($lid) ? true : $lid;
439 2
        if ($lid === true && $this->getInsertId() > 0) {
440 2
            $lid = $this->getInsertId();
441
        }
442 2
        return $lid;
443
    }
444
445
    /**
446
     * {@inheritDoc}
447
     */
448 2
    public function save($fields, $table, $where = '')
449
    {
450 2
        if ($where === '') {
451 2
            $mode = 'insert';
452
        } else {
453 2
            $result = $this->select('*', $table, $where);
454
455 2
            if ($this->getRecordCount($result) === 0) {
456 2
                $mode = 'insert';
457
            } else {
458 2
                $mode = 'update';
459
            }
460
        }
461
462 2
        return ($mode === 'insert') ? $this->insert($fields, $table) : $this->update($fields, $table, $where);
463
    }
464
465
    /**
466
     * {@inheritDoc}
467
     */
468 2
    public function optimize($table)
469
    {
470 2
        $result = $this->query('OPTIMIZE TABLE ' . $table);
471 2
        if ($result !== false) {
472 2
            $result = $this->alterTable($table);
473
        }
474
475 2
        return $this->isResult($result) ? true : $result;
476
    }
477
478
    /**
479
     * {@inheritDoc}
480
     */
481 4
    public function alterTable($table)
482
    {
483 4
        $result = $this->query('ALTER TABLE ' . $table);
484
485 4
        return $this->isResult($result) ? true : $result;
486
    }
487
488
    /**
489
     * {@inheritDoc}
490
     */
491 2
    public function truncate($table)
492
    {
493 2
        $result = $this->query('TRUNCATE ' . $table);
494
495 2
        return $this->isResult($result) ? $this->getValue($result) : $result;
496
    }
497
498
    /**
499
     * {@inheritDoc}
500
     */
501 61
    public function getTableName($table, $escape = true)
502
    {
503 61
        if (empty($table)) {
504 2
            throw new Exceptions\TableNotDefinedException($table);
505
        }
506
507 61
        $out = $this->getConfig('prefix') . $table;
508
509 61
        return $escape ? '`' . $out . '`' : $out;
510
    }
511
512
    /**
513
     * {@inheritDoc}
514
     */
515 59
    public function getFullTableName($table)
516
    {
517 59
        if (empty($table)) {
518 1
            throw new Exceptions\TableNotDefinedException($table);
519
        }
520
521 59
        return implode('.', [
522 59
            '`' . $this->getConfig('database') . '`',
523 59
            $this->getTableName($table)
524
        ]);
525
    }
526
527
    /**
528
     * {@inheritDoc}
529
     */
530
    public function begin ($flag = 0, $name = null)
531
    {
532
        return $this->getDriver()->begin($flag, $name);
533
    }
534
535
    /**
536
     * {@inheritDoc}
537
     */
538
    public function commit ($flag = 0, $name = null)
539
    {
540
        return $this->getDriver()->commit($flag, $name);
541
    }
542
543
    /**
544
     * {@inheritDoc}
545
     */
546
    public function rollback ($flag = 0, $name = null)
547
    {
548
        return $this->getDriver()->rollback($flag, $name);
549
    }
550
551
552
}
553