Passed
Push — master ( 1c0e8d...8b3112 )
by Agel_Nash
02:39
created

AbstractDatabase::delete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 7
cts 7
cp 1
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 4
crap 2
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 53
    public function connect()
39
    {
40 53
        $tStart = microtime(true);
41
42 53
        $out = $this->getDriver()->getConnect();
43
44 52
        $totalTime = microtime(true) - $tStart;
45 52
        if ($this->isDebug()) {
46 52
            $this->setConnectionTime($totalTime);
47
        }
48 52
        $this->setCharset(
49 52
            $this->getConfig('charset'),
50 52
            $this->getConfig('method')
51
        );
52
53 52
        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 52
    public function setCharset($charset, $method = null)
97
    {
98 52
        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 39
    public function query($sql)
145
    {
146 39
        $tStart = microtime(true);
147 39
        if (\is_array($sql)) {
148 2
            $sql = implode("\n", $sql);
149
        }
150 39
        $this->setLastQuery($sql);
151
152 39
        $result = $this->getDriver()->query(
153 39
            $this->getLastQuery()
154
        );
155
156 37
        if ($result === false) {
157
            /**
158
             * @TODO: NOT WORK?
159
             */
160
            $this->checkLastError($this->getLastQuery());
161
        } else {
162 37
            $tend = microtime(true);
163 37
            $totalTime = $tend - $tStart;
164 37
            $this->addQueriesTime($totalTime);
165 37
            if ($this->isDebug()) {
166 37
                $this->collectQuery(
167 37
                    $result,
168 37
                    $this->getLastQuery(),
169 37
                    $totalTime
170
                );
171
            }
172
        }
173
174 37
        return $result;
175
    }
176
177
    /**
178
     * {@inheritDoc}
179
     */
180 27
    public function getRecordCount($result)
181
    {
182 27
        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 6
    public function getVersion()
201
    {
202 6
        return $this->getDriver()->getVersion();
203
    }
204
205
    /**
206
     * {@inheritDoc}
207
     */
208 6
    public function getInsertId()
209
    {
210 6
        return $this->convertValue(
211 6
            $this->getDriver()->getInsertId()
212
        );
213
    }
214
215
    /**
216
     * {@inheritDoc}
217
     */
218 16
    public function getAffectedRows()
219
    {
220 16
        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 8
    public function getValue($result)
250
    {
251 8
        if (\is_scalar($result)) {
252 8
            $result = $this->query($result);
253
        }
254
255 8
        return $this->convertValue(
256 8
            $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 58
    public function getDriver()
279
    {
280 58
        return $this->driver;
281
    }
282
283
    /**
284
     * {@inheritDoc}
285
     */
286 80
    public function setDriver($driver)
287
    {
288 80
        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 80
        if (is_scalar($driver)) {
295 76
            $this->driver = new $driver($this->getConfig());
296
        } else {
297 4
            $this->driver = $driver;
298 4
            $this->config = array_merge($this->config, $driver->getConfig());
299
        }
300
301 80
        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 9
    public function insert(
368
        $fields,
369
        $table,
370
        $fromFields = '*',
371
        $fromTable = '',
372
        $where = '',
373
        $limit = ''
374
    ) {
375 9
        $table = $this->prepareFrom($table);
376
377 9
        $useFields = null;
378 9
        $lid = null;
379
380 9
        if (\is_array($fields)) {
381 8
            $useFields = empty($fromTable) ?
382 6
                $this->prepareValues($fields) :
383 8
                $this->prepareFields($fields, true);
384
        } else {
385 5
            $useFields = $fields;
386
        }
387
388 9
        if (empty($useFields) || ! \is_scalar($useFields) || ($useFields === '*' && ! empty($fromTable))) {
389 1
            throw (new Exceptions\InvalidFieldException('Invalid insert fields'))
390 1
                ->setData($fields);
391
        }
392
393 8
        if (empty($fromTable)) {
394 6
            $this->query("INSERT INTO {$table} {$useFields}");
395
        } else {
396 2
            if (empty($fromFields) || $fromFields === '*') {
397 2
                $fromFields = $this->prepareFields($fields, true);
398
            } else {
399 2
                $fromFields = $this->prepareFields($fromFields, true);
400
            }
401
402 2
            $where = $this->prepareWhere($where);
403 2
            $limit = $this->prepareLimit($limit);
404
405 2
            $lid = $this->query(
406 2
                "INSERT INTO {$table} ({$useFields}) SELECT {$fromFields} FROM {$fromTable} {$where} {$limit}"
407
            );
408 2
            $lid = $this->isResult($lid) ? true : $lid;
409
        }
410
411 8
        if ($lid === null && ($lid = $this->getInsertId()) === false) {
412
            throw new Exceptions\GetDataException("Couldn't get last insert key!");
413
        }
414
415 8
        return $this->convertValue($lid);
416
    }
417
418
    /**
419
     * {@inheritDoc}
420
     */
421 2
    public function save($fields, $table, $where = '')
422
    {
423 2
        if ($where === '') {
424 2
            $mode = 'insert';
425
        } else {
426 2
            $result = $this->select('*', $table, $where);
427
428 2
            if ($this->getRecordCount($result) === 0) {
429 2
                $mode = 'insert';
430
            } else {
431 2
                $mode = 'update';
432
            }
433
        }
434
435 2
        return ($mode === 'insert') ? $this->insert($fields, $table) : $this->update($fields, $table, $where);
436
    }
437
438
    /**
439
     * {@inheritDoc}
440
     */
441 2
    public function optimize($table)
442
    {
443 2
        $result = $this->query('OPTIMIZE TABLE ' . $table);
444 2
        if ($result !== false) {
445 2
            $result = $this->alterTable($table);
446
        }
447
448 2
        return $this->isResult($result) ? true : $result;
449
    }
450
451
    /**
452
     * {@inheritDoc}
453
     */
454 4
    public function alterTable($table)
455
    {
456 4
        $result = $this->query('ALTER TABLE ' . $table);
457
458 4
        return $this->isResult($result) ? true : $result;
459
    }
460
461
    /**
462
     * {@inheritDoc}
463
     */
464 2
    public function truncate($table)
465
    {
466 2
        $result = $this->query('TRUNCATE ' . $table);
467
468 2
        return $this->isResult($result) ? $this->getValue($result) : $result;
469
    }
470
471
    /**
472
     * {@inheritDoc}
473
     */
474 55
    public function getTableName($table, $escape = true)
475
    {
476 55
        if (empty($table)) {
477 2
            throw new Exceptions\TableNotDefinedException($table);
478
        }
479
480 55
        $out = $this->getConfig('prefix') . $table;
481
482 55
        return $escape ? '`' . $out . '`' : $out;
483
    }
484
485
    /**
486
     * {@inheritDoc}
487
     */
488 53
    public function getFullTableName($table)
489
    {
490 53
        if (empty($table)) {
491 1
            throw new Exceptions\TableNotDefinedException($table);
492
        }
493
494 53
        return implode('.', [
495 53
            '`' . $this->getConfig('database') . '`',
496 53
            $this->getTableName($table)
497
        ]);
498
    }
499
}
500