Completed
Push — master ( 969424...1c0e8d )
by Agel_Nash
03:49
created

AbstractDatabase::selectDb()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
crap 1
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 51
    public function connect()
39
    {
40 51
        $tStart = microtime(true);
41
42 51
        $out = $this->getDriver()->getConnect();
43
44 50
        $totalTime = microtime(true) - $tStart;
45 50
        if ($this->isDebug()) {
46 50
            $this->setConnectionTime($totalTime);
47
        }
48 50
        $this->setCharset(
49 50
            $this->getConfig('charset'),
50 50
            $this->getConfig('method')
51
        );
52
53 50
        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 $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type AgelxNash\Modx\Evo\Database\AbstractDatabase which is incompatible with the return type mandated by AgelxNash\Modx\Evo\Datab...Interface::disconnect() of AgelxNash\Modx\Evo\Datab...erfaces\DriverInterface.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
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 50
    public function setCharset($charset, $method = null)
97
    {
98 50
        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
                $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 37
    public function query($sql)
145
    {
146 37
        $tStart = microtime(true);
147 37
        if (\is_array($sql)) {
148 2
            $sql = implode("\n", $sql);
149
        }
150 37
        $this->setLastQuery($sql);
151
152 37
        $result = $this->getDriver()->query(
153 37
            $this->getLastQuery()
154
        );
155
156 35
        if ($result === false) {
157
            $this->checkLastError($this->getLastQuery());
158
        } else {
159 35
            $tend = microtime(true);
160 35
            $totalTime = $tend - $tStart;
161 35
            $this->addQueriesTime($totalTime);
162 35
            if ($this->isDebug()) {
163 35
                $this->collectQuery(
164 35
                    $result,
165 35
                    $this->getLastQuery(),
166 35
                    $totalTime
167
                );
168
            }
169
170 35
            return $result;
171
        }
172
        return false;
173
    }
174
175
    /**
176
     * {@inheritDoc}
177
     */
178 25
    public function getRecordCount($result)
179
    {
180 25
        return $this->getDriver()->getRecordCount($result);
181
    }
182
183
    /**
184
     * {@inheritDoc}
185
     */
186 5
    public function getRow($result, $mode = 'assoc')
187
    {
188 5
        if (\is_scalar($result)) {
189 3
            $result = $this->query($result);
190
        }
191
192 5
        return $this->getDriver()->getRow($result, $mode);
193
    }
194
195
    /**
196
     * {@inheritDoc}
197
     */
198 6
    public function getVersion()
199
    {
200 6
        return $this->getDriver()->getVersion();
201
    }
202
203
    /**
204
     * {@inheritDoc}
205
     */
206 6
    public function getInsertId()
207
    {
208 6
        return $this->convertValue(
209 6
            $this->getDriver()->getInsertId()
210
        );
211
    }
212
213
    /**
214
     * {@inheritDoc}
215
     */
216 16
    public function getAffectedRows()
217
    {
218 16
        return $this->getDriver()->getAffectedRows();
219
    }
220
221
    /**
222
     * {@inheritDoc}
223
     */
224 6
    public function getColumn($name, $result)
225
    {
226 6
        if (\is_scalar($result)) {
227 6
            $result = $this->query($result);
228
        }
229
230 6
        return $this->getDriver()->getColumn($name, $result);
231
    }
232
233
    /**
234
     * {@inheritDoc}
235
     */
236 2
    public function getColumnNames($result)
237
    {
238 2
        if (\is_scalar($result)) {
239
            $result = $this->query($result);
240
        }
241 2
        return $this->getDriver()->getColumnNames($result);
242
    }
243
244
    /**
245
     * {@inheritDoc}
246
     */
247 8
    public function getValue($result)
248
    {
249 8
        if (\is_scalar($result)) {
250 8
            $result = $this->query($result);
251
        }
252
253 8
        return $this->convertValue(
254 8
            $this->getDriver()->getValue($result)
255
        );
256
    }
257
258
    /**
259
     * {@inheritDoc}
260
     */
261 2
    public function getTableMetaData($table)
262
    {
263 2
        $metadata = [];
264 2
        if (! empty($table)) {
265 2
            $sql = 'SHOW FIELDS FROM ' . $table;
266 2
            $result = $this->query($sql);
267 2
            $metadata = $this->getDriver()->getTableMetaData($result);
268
        }
269
270 2
        return $metadata;
271
    }
272
273
    /**
274
     * {@inheritDoc}
275
     */
276 56
    public function getDriver()
277
    {
278 56
        return $this->driver;
279
    }
280
281
    /**
282
     * {@inheritDoc}
283
     */
284 75
    public function setDriver($driver)
285
    {
286 75
        if (! \in_array(Interfaces\DriverInterface::class, class_implements($driver), true)) {
287 1
            throw new Exceptions\DriverException(
288 1
                $driver . ' should implements the ' . Interfaces\DriverInterface::class
289
            );
290
        }
291
292 75
        if (is_scalar($driver)) {
293 71
            $this->driver = new $driver($this->getConfig());
294
        } else {
295 4
            $this->driver = $driver;
296 4
            $this->config = array_merge($this->config, $driver->getConfig());
297
        }
298
299 75
        return $this->driver;
300
    }
301
302
    /**
303
     * {@inheritDoc}
304
     */
305 2
    public function makeArray($result, $index = false)
306
    {
307 2
        $rsArray = [];
308 2
        $iterator = 0;
309 2
        while ($row = $this->getRow($result)) {
310 2
            $returnIndex = $index !== false && isset($row[$index]) ? $row[$index] : $iterator;
311 2
            $rsArray[$returnIndex] = $row;
312 2
            $iterator++;
313
        }
314
315 2
        return $rsArray;
316
    }
317
318
    /**
319
     * {@inheritDoc}
320
     */
321 2
    public function delete($table, $where = '', $orderBy = '', $limit = '')
322
    {
323 2
        $table = $this->prepareFrom($table);
324 2
        $where = $this->prepareWhere($where);
325 2
        $orderBy = $this->prepareOrder($orderBy);
326 2
        $limit = $this->prepareLimit($limit);
327
328 2
        $result = $this->query("DELETE FROM {$table} {$where} {$orderBy} {$limit}");
329 2
        return $this->isResult($result) ? true : $result;
330
    }
331
332
    /**
333
     * {@inheritDoc}
334
     */
335 6
    public function select($fields, $tables, $where = '', $orderBy = '', $limit = '')
336
    {
337 6
        $fields = $this->prepareFields($fields);
338 6
        $tables = $this->prepareFrom($tables, true);
339 6
        $where = $this->prepareWhere($where);
340 6
        $orderBy = $this->prepareOrder($orderBy);
341 6
        $limit = $this->prepareLimit($limit);
342
343 6
        return $this->query("SELECT {$fields} FROM {$tables} {$where} {$orderBy} {$limit}");
344
    }
345
346
    /**
347
     * {@inheritDoc}
348
     */
349 4
    public function update($values, $table, $where = '')
350
    {
351 4
        $table = $this->prepareFrom($table);
352 4
        $values = $this->prepareValuesSet($values);
353 4
        if (mb_strtoupper(mb_substr($values, 0, 4)) !== 'SET ') {
354 4
            $values = 'SET ' . $values;
355
        }
356 4
        $where = $this->prepareWhere($where);
357
358 4
        $result = $this->query("UPDATE {$table} {$values} {$where}");
359 4
        return $this->isResult($result) ? true : $result;
360
    }
361
362
    /**
363
     * {@inheritDoc}
364
     */
365 8
    public function insert(
366
        $fields,
367
        $table,
368
        $fromFields = '*',
369
        $fromTable = '',
370
        $where = '',
371
        $limit = ''
372
    ) {
373 8
        $table = $this->prepareFrom($table);
374
375 8
        $useFields = null;
376 8
        $lid = null;
377
378 8
        if (\is_array($fields)) {
379 8
            $useFields = empty($fromTable) ?
380 6
                $this->prepareValues($fields) :
381 8
                $this->prepareFields($fields, true);
382
        } else {
383 4
            $useFields = $fields;
384
        }
385
386 8
        if (empty($useFields) || ! \is_scalar($useFields) || ($useFields === '*' && ! empty($fromTable))) {
387
            throw (new Exceptions\InvalidFieldException('Invalid insert fields'))
388
                ->setData($fields);
389
        }
390
391 8
        if (empty($fromTable)) {
392 6
            $this->query("INSERT INTO {$table} {$useFields}");
393
        } else {
394 2
            if (empty($fromFields) || $fromFields === '*') {
395 2
                $fromFields = $this->prepareFields($fields, true);
396
            } else {
397 2
                $fromFields = $this->prepareFields($fromFields, true);
398
            }
399
400 2
            $where = $this->prepareWhere($where);
401 2
            $limit = $this->prepareLimit($limit);
402
403 2
            $lid = $this->query(
404 2
                "INSERT INTO {$table} ({$useFields}) SELECT {$fromFields} FROM {$fromTable} {$where} {$limit}"
405
            );
406 2
            $lid = $this->isResult($lid) ? true : $lid;
407
        }
408
409 8
        if ($lid === null && ($lid = $this->getInsertId()) === false) {
410
            throw new Exceptions\GetDataException("Couldn't get last insert key!");
411
        }
412
413 8
        return $this->convertValue($lid);
414
    }
415
416
    /**
417
     * {@inheritDoc}
418
     */
419 2
    public function save($fields, $table, $where = '')
420
    {
421 2
        if ($where === '') {
422 2
            $mode = 'insert';
423
        } else {
424 2
            $result = $this->select('*', $table, $where);
425
426 2
            if ($this->getRecordCount($result) === 0) {
427 2
                $mode = 'insert';
428
            } else {
429 2
                $mode = 'update';
430
            }
431
        }
432
433 2
        return ($mode === 'insert') ? $this->insert($fields, $table) : $this->update($fields, $table, $where);
434
    }
435
436
    /**
437
     * {@inheritDoc}
438
     */
439 2
    public function optimize($table)
440
    {
441 2
        $result = $this->query('OPTIMIZE TABLE ' . $table);
442 2
        if ($result !== false) {
443 2
            $result = $this->alterTable($table);
444
        }
445
446 2
        return $this->isResult($result) ? true : $result;
447
    }
448
449
    /**
450
     * {@inheritDoc}
451
     */
452 4
    public function alterTable($table)
453
    {
454 4
        $result = $this->query('ALTER TABLE ' . $table);
455
456 4
        return $this->isResult($result) ? true : $result;
457
    }
458
459
    /**
460
     * {@inheritDoc}
461
     */
462 2
    public function truncate($table)
463
    {
464 2
        $result = $this->query('TRUNCATE ' . $table);
465
466 2
        return $this->isResult($result) ? $this->getValue($result) : $result;
467
    }
468
469
    /**
470
     * {@inheritDoc}
471
     */
472 53
    public function getTableName($table, $escape = true)
473
    {
474 53
        if (empty($table)) {
475 2
            throw new Exceptions\TableNotDefinedException($table);
476
        }
477
478 53
        $out = $this->getConfig('prefix') . $table;
479
480 53
        return $escape ? '`' . $out . '`' : $out;
481
    }
482
483
    /**
484
     * {@inheritDoc}
485
     */
486 51
    public function getFullTableName($table)
487
    {
488 51
        if (empty($table)) {
489 1
            throw new Exceptions\TableNotDefinedException($table);
490
        }
491
492 51
        return implode('.', [
493 51
            '`' . $this->getConfig('database') . '`',
494 51
            $this->getTableName($table)
495
        ]);
496
    }
497
}
498