Completed
Push — master ( a45e07...0294bf )
by Agel_Nash
02:52
created

AbstractDatabase   F

Complexity

Total Complexity 69

Size/Duplication

Total Lines 525
Duplicated Lines 0 %

Test Coverage

Coverage 93.41%

Importance

Changes 0
Metric Value
wmc 69
dl 0
loc 525
ccs 170
cts 182
cp 0.9341
rs 2.8301
c 0
b 0
f 0

29 Methods

Rating   Name   Duplication   Size   Complexity  
A connect() 0 17 2
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
B query() 0 31 4
A getTableMetaData() 0 10 2
A setDriver() 0 16 3
A getVersion() 0 3 1
A numFields() 0 3 1
A getAffectedRows() 0 3 1
A getInsertId() 0 4 1
A select() 0 9 1
A alterTable() 0 5 2
B escape() 0 19 5
A update() 0 11 3
A getColumn() 0 7 2
C insert() 0 49 13
A setCharset() 0 9 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
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
     * @return Interfaces\DriverInterface
21
     * @throws Exceptions\Exception
22
     */
23 49
    public function getDriver()
24
    {
25 49
        return $this->driver;
26
    }
27
28
    /**
29
     * @param string|Interfaces\DriverInterface $driver
30
     * @return Interfaces\DriverInterface
31
     * @throws Exceptions\Exception
32
     */
33 68
    public function setDriver($driver)
34
    {
35 68
        if (! \in_array(Interfaces\DriverInterface::class, class_implements($driver), true)) {
36 1
            throw new Exceptions\DriverException(
37 1
                $driver . ' should implements the ' . Interfaces\DriverInterface::class
0 ignored issues
show
Bug introduced by
Are you sure $driver of type string|AgelxNash\Modx\Ev...erfaces\DriverInterface can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

37
                /** @scrutinizer ignore-type */ $driver . ' should implements the ' . Interfaces\DriverInterface::class
Loading history...
38
            );
39
        }
40
41 68
        if (is_scalar($driver)) {
42 64
            $this->driver = new $driver($this->getConfig());
43
        } else {
44 4
            $this->driver = $driver;
45 4
            $this->config = array_merge($this->config, $driver->getConfig());
0 ignored issues
show
Bug introduced by
The method getConfig() does not exist on AgelxNash\Modx\Evo\Datab...erfaces\DriverInterface. Did you maybe mean getConnect()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

45
            $this->config = array_merge($this->config, $driver->/** @scrutinizer ignore-call */ getConfig());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

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