Completed
Push — develop ( 4e806c...6a553b )
by Agel_Nash
10:03
created

Database::getFullTableName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php namespace EvolutionCMS;
2
3
use mysqli;
4
use mysqli_result;
5
6
class Database implements Interfaces\DatabaseInterface
0 ignored issues
show
Coding Style introduced by
The property $_dbconnectionmethod is not named in camelCase.

This check marks property names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
7
{
8
    /**
9
     * @var mysqli
10
     */
11
    public $conn;
12
    public $config;
13
    public $lastQuery;
14
    public $isConnected;
15
    public $_dbconnectionmethod;
16
17
    /**
18
     * DBAPI constructor.
19
     *
20
     * @param string $host
21
     * @param string $dbase
22
     * @param string $uid
23
     * @param string $pwd
24
     * @param null|string $pre
25
     * @param string $charset
26
     * @param string $connection_method
27
     */
28
    public function __construct(
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style Naming introduced by
The parameter $connection_method is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
29
        $host = '',
30
        $dbase = '',
31
        $uid = '',
32
        $pwd = '',
33
        $pre = null,
34
        $charset = '',
35
        $connection_method = 'SET CHARACTER SET'
36
    ) {
37
        $this->config['host'] = $host ? $host : $GLOBALS['database_server'];
38
        $this->config['dbase'] = $dbase ? $dbase : $GLOBALS['dbase'];
39
        $this->config['user'] = $uid ? $uid : $GLOBALS['database_user'];
40
        $this->config['pass'] = $pwd ? $pwd : $GLOBALS['database_password'];
41
        $this->config['charset'] = $charset ? $charset : $GLOBALS['database_connection_charset'];
42
        $this->config['connection_method'] = $this->_dbconnectionmethod = (isset($GLOBALS['database_connection_method']) ? $GLOBALS['database_connection_method'] : $connection_method);
43
        $this->config['table_prefix'] = ($pre !== null) ? $pre : $GLOBALS['table_prefix'];
44
    }
45
46
    /**
47
     * @param string $host
48
     * @param string $dbase
49
     * @param string $uid
50
     * @param string $pwd
51
     * @return mysqli
0 ignored issues
show
Documentation introduced by
Should the return type not be mysqli|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
52
     */
53
    public function connect($host = '', $dbase = '', $uid = '', $pwd = '')
0 ignored issues
show
Coding Style introduced by
connect uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
54
    {
55
        $modx = evolutionCMS();
56
        $uid = $uid ? $uid : $this->config['user'];
57
        $pwd = $pwd ? $pwd : $this->config['pass'];
58
        $host = $host ? $host : $this->config['host'];
59
        $dbase = $dbase ? $dbase : $this->config['dbase'];
60
        $dbase = trim($dbase, '`'); // remove the `` chars
61
        $charset = $this->config['charset'];
62
        $connection_method = $this->config['connection_method'];
63
        $tstart = $modx->getMicroTime();
64
        $safe_count = 0;
65
        do {
66
            $this->conn = new mysqli($host, $uid, $pwd, $dbase);
67
            if ($this->conn->connect_error) {
68
                $this->conn = null;
69
                if (isset($modx->config['send_errormail']) && $modx->config['send_errormail'] !== '0') {
70
                    if ($modx->config['send_errormail'] <= 2) {
71
                        $logtitle = 'Failed to create the database connection!';
72
                        $request_uri = $modx->getPhpCompat()->htmlspecialchars($_SERVER['REQUEST_URI']);
73
                        $ua = $modx->getPhpCompat()->htmlspecialchars($_SERVER['HTTP_USER_AGENT']);
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $ua. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
74
                        $referer = $modx->getPhpCompat()->htmlspecialchars($_SERVER['HTTP_REFERER']);
75
                        $modx->sendmail(array(
76
                            'subject' => 'Missing to create the database connection! from ' . $modx->getPhpCompat()->entities($modx->config['site_name']),
77
                            'body'    => "{$logtitle}\n{$request_uri}\n{$ua}\n{$referer}",
78
                            'type'    => 'text'
79
                        ));
80
                    }
81
                }
82
                sleep(1);
83
                $safe_count++;
84
            }
85
        } while (!$this->conn && $safe_count < 3);
86
        if ($this->conn instanceof mysqli) {
87
            $this->conn->query("{$connection_method} {$charset}");
88
            $tend = $modx->getMicroTime();
89
            $totaltime = $tend - $tstart;
90
            if ($modx->dumpSQL) {
91
                $modx->queryCode .= "<fieldset style='text-align:left'><legend>Database connection</legend>" . sprintf("Database connection was created in %2.4f s",
92
                        $totaltime) . "</fieldset><br />";
93
            }
94
            $this->conn->set_charset($this->config['charset']);
95
            $this->isConnected = true;
96
            $modx->queryTime += $totaltime;
97
        } else {
98
            $modx->messageQuit("Failed to create the database connection!");
99
            exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method connect() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
100
        }
101
        return $this->conn;
102
    }
103
104
    /**
105
     * @return void
106
     */
107
    public function disconnect()
108
    {
109
        $this->conn->close();
110
        $this->conn = null;
111
        $this->isConnected = false;
112
    }
113
114
    /**
115
     * @param array|string $s
116
     * @param int $safeCount
117
     * @return array|string
118
     */
119
    public function escape($s, $safeCount = 0)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $s. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
120
    {
121
        $safeCount++;
122
        if (1000 < $safeCount) {
123
            exit("Too many loops '{$safeCount}'");
0 ignored issues
show
Coding Style Compatibility introduced by
The method escape() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
124
        }
125
        if ( ! ($this->conn instanceof mysqli)) {
126
            $this->connect();
127
        }
128
        if (is_array($s)) {
129
            if (count($s) === 0) {
130
                $s = '';
131
            } else {
132
                foreach ($s as $i => $v) {
133
                    $s[$i] = $this->escape($v, $safeCount);
134
                }
135
            }
136
        } else {
137
            $s = $this->conn->escape_string($s);
138
        }
139
140
        return $s;
141
    }
142
143
    /**
144
     * @param string|array|mysqli_result $sql
145
     * @param bool $watchError
146
     * @return bool|mysqli_result
147
     */
148
    public function query($sql, $watchError = true)
149
    {
150
        $modx = evolutionCMS();
151
        if ( ! ($this->conn instanceof mysqli)) {
152
            $this->connect();
153
        }
154
        $tStart = $modx->getMicroTime();
155
        if (is_array($sql)) {
156
            $sql = implode("\n", $sql);
157
        }
158
        $this->lastQuery = $sql;
159
        if (!($result = $this->conn->query($sql))) {
160
            if (!$watchError) {
161
                return false;
162
            }
163
            switch (mysqli_errno($this->conn)) {
164
                case 1054:
165
                case 1060:
166
                case 1061:
167
                case 1062:
168
                case 1091:
169
                    break;
170
                default:
171
                    $modx->messageQuit('Execution of a query to the database failed - ' . $this->getLastError(), $sql);
0 ignored issues
show
Bug introduced by
It seems like $sql defined by parameter $sql on line 148 can also be of type object<mysqli_result>; however, EvolutionCMS\Core::messageQuit() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
172
            }
173
        } else {
174
            $tend = $modx->getMicroTime();
175
            $totalTime = $tend - $tStart;
176
            $modx->queryTime += $totalTime;
177
            if ($modx->dumpSQL) {
178
                $debug = debug_backtrace();
179
                array_shift($debug);
180
                $debug_path = array();
181
                foreach ($debug as $line) {
182
                    $debug_path[] = $line['function'];
183
                }
184
                $debug_path = implode(' > ', array_reverse($debug_path));
185
                $modx->queryCode .= "<fieldset style='text-align:left'><legend>Query " . ($modx->executedQueries + 1) . " - " . sprintf("%2.2f ms",
186
                        $totalTime * 1000) . "</legend>";
187
                $modx->queryCode .= $sql . '<br><br>';
188
                if ($modx->event->name) {
189
                    $modx->queryCode .= 'Current Event  => ' . $modx->event->name . '<br>';
190
                }
191
                if ($modx->event->activePlugin) {
192
                    $modx->queryCode .= 'Current Plugin => ' . $modx->event->activePlugin . '<br>';
193
                }
194
                if ($modx->currentSnippet) {
195
                    $modx->queryCode .= 'Current Snippet => ' . $modx->currentSnippet . '<br>';
196
                }
197
                if (stripos($sql, 'select') === 0) {
198
                    $modx->queryCode .= 'Record Count => ' . $this->getRecordCount($result) . '<br>';
199
                } else {
200
                    $modx->queryCode .= 'Affected Rows => ' . $this->getAffectedRows() . '<br>';
201
                }
202
                $modx->queryCode .= 'Functions Path => ' . $debug_path . '<br>';
203
                $modx->queryCode .= "</fieldset><br />";
204
            }
205
            $modx->executedQueries++;
206
207
            return $result;
208
        }
209
        return false;
210
    }
211
212
    /**
213
     * @param string $from
214
     * @param string $where
215
     * @param string $orderBy
216
     * @param string $limit
217
     * @return bool|mysqli_result
218
     */
219
    public function delete($from, $where = '', $orderBy = '', $limit = '')
220
    {
221
        $modx = evolutionCMS();
222
        $out = false;
223
        if (!$from) {
224
            $modx->messageQuit("Empty \$from parameters in DBAPI::delete().");
225
        } else {
226
            $from = $this->replaceFullTableName($from);
227
            $where = trim($where);
228
            $orderBy = trim($orderBy);
229
            $limit = trim($limit);
230
            if ($where !== '' && stripos($where, 'WHERE') !== 0) {
231
                $where = "WHERE {$where}";
232
            }
233
            if ($orderBy !== '' && stripos($orderBy, 'ORDER BY') !== 0) {
234
                $orderBy = "ORDER BY {$orderBy}";
235
            }
236
            if ($limit !== '' && stripos($limit, 'LIMIT') !== 0) {
237
                $limit = "LIMIT {$limit}";
238
            }
239
240
            $out = $this->query("DELETE FROM {$from} {$where} {$orderBy} {$limit}");
241
        }
242
        return $out;
243
    }
244
245
    /**
246
     * @param string|array $fields
247
     * @param string|array $from
248
     * @param string|array $where
249
     * @param string $orderBy
250
     * @param string $limit
251
     * @return bool|mysqli_result
252
     */
253
    public function select($fields = "*", $from = "", $where = "", $orderBy = "", $limit = "")
254
    {
255
        $modx = evolutionCMS();
256
257
        if (is_array($fields)) {
258
            $fields = $this->_getFieldsStringFromArray($fields);
259
        }
260
        if (is_array($from)) {
261
            $from = $this->_getFromStringFromArray($from);
262
        }
263
        if (is_array($where)) {
264
            $where = implode(' ', $where);
265
        }
266
267
        if (!$from) {
268
            $modx->messageQuit("Empty \$from parameters in DBAPI::select().");
269
            exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method select() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
270
        }
271
272
        $fields = $this->replaceFullTableName($fields);
273
        $from = $this->replaceFullTableName($from);
274
        $where = trim($where);
275
        $orderBy = trim($orderBy);
276
        $limit = trim($limit);
277
        if ($where !== '' && stripos($where, 'WHERE') !== 0) {
278
            $where = "WHERE {$where}";
279
        }
280
        if ($orderBy !== '' && stripos($orderBy, 'ORDER') !== 0) {
281
            $orderBy = "ORDER BY {$orderBy}";
282
        }
283
        if ($limit !== '' && stripos($limit, 'LIMIT') !== 0) {
284
            $limit = "LIMIT {$limit}";
285
        }
286
287
        return $this->query("SELECT {$fields} FROM {$from} {$where} {$orderBy} {$limit}");
288
    }
289
290
    /**
291
     * @param array|string $fields
292
     * @param $table
293
     * @param string $where
294
     * @return bool|mysqli_result
295
     */
296
    public function update($fields, $table, $where = "")
297
    {
298
        $modx = evolutionCMS();
299
        $out = false;
300
        if (!$table) {
301
            $modx->messageQuit('Empty '.$table.' parameter in DBAPI::update().');
302
        } else {
303
            $table = $this->replaceFullTableName($table);
304
            if (is_array($fields)) {
305
                foreach ($fields as $key => $value) {
306
                    if ($value === null || strtolower($value) === 'null') {
307
                        $f = 'NULL';
308
                    } else {
309
                        $f = "'" . $value . "'";
310
                    }
311
                    $fields[$key] = "`{$key}` = " . $f;
312
                }
313
                $fields = implode(',', $fields);
314
            }
315
            $where = trim($where);
316
            if ($where !== '' && stripos($where, 'WHERE') !== 0) {
317
                $where = 'WHERE '.$where;
318
            }
319
320
            return $this->query('UPDATE '.$table.' SET '.$fields.' '.$where);
321
        }
322
        return $out;
323
    }
324
325
    /**
326
     * @param string|array $fields
327
     * @param string $intotable
328
     * @param string $fromfields
329
     * @param string $fromtable
330
     * @param string $where
331
     * @param string $limit
332
     * @return mixed
333
     */
334
    public function insert($fields, $intotable, $fromfields = "*", $fromtable = "", $where = "", $limit = "")
335
    {
336
        $modx = evolutionCMS();
337
        $out = false;
338
        if (!$intotable) {
339
            $modx->messageQuit("Empty \$intotable parameters in DBAPI::insert().");
340
        } else {
341
            $intotable = $this->replaceFullTableName($intotable);
342
            if (!is_array($fields)) {
343
                $this->query("INSERT INTO {$intotable} {$fields}");
344
            } else {
345
                if (empty($fromtable)) {
346
                    $fields = "(`" . implode("`, `", array_keys($fields)) . "`) VALUES('" . implode("', '",
347
                            array_values($fields)) . "')";
348
                    $this->query("INSERT INTO {$intotable} {$fields}");
349
                } else {
350
                    $fromtable = $this->replaceFullTableName($fromtable);
351
                    $fields = "(" . implode(",", array_keys($fields)) . ")";
352
                    $where = trim($where);
353
                    $limit = trim($limit);
354
                    if ($where !== '' && stripos($where, 'WHERE') !== 0) {
355
                        $where = "WHERE {$where}";
356
                    }
357
                    if ($limit !== '' && stripos($limit, 'LIMIT') !== 0) {
358
                        $limit = "LIMIT {$limit}";
359
                    }
360
                    $this->query("INSERT INTO {$intotable} {$fields} SELECT {$fromfields} FROM {$fromtable} {$where} {$limit}");
361
                }
362
            }
363
            if (($lid = $this->getInsertId()) === false) {
364
                $modx->messageQuit("Couldn't get last insert key!");
365
            }
366
367
            $out = $lid;
368
        }
369
        return $out;
370
    }
371
372
    /**
373
     * @param $fields
374
     * @param $table
375
     * @param string $where
376
     * @return bool|mixed|mysqli_result
377
     */
378
    public function save($fields, $table, $where = '')
379
    { // This is similar to "replace into table".
380
381
        if ($where === '') {
382
            $mode = 'insert';
383
        } elseif ($this->getRecordCount($this->select('*', $table, $where)) === 0) {
0 ignored issues
show
Bug introduced by
It seems like $this->select('*', $table, $where) targeting EvolutionCMS\Database::select() can also be of type boolean; however, EvolutionCMS\Database::getRecordCount() does only seem to accept object<mysqli_result>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
384
            $mode = 'insert';
385
        } else {
386
            $mode = 'update';
387
        }
388
389
        return ($mode === 'insert') ? $this->insert($fields, $table) : $this->update($fields, $table, $where);
390
    }
391
392
    /**
393
     * @param mixed $rs
394
     * @return bool
395
     */
396
    public function isResult($rs)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $rs. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
397
    {
398
        return $rs instanceof mysqli_result;
399
    }
400
401
    /**
402
     * @param mysqli_result $rs
403
     */
404
    public function freeResult($rs)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $rs. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
405
    {
406
        $rs->free_result();
407
    }
408
409
    /**
410
     * @param mysqli_result $rs
411
     * @return mixed
412
     */
413
    public function numFields($rs)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $rs. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
414
    {
415
        return $rs->field_count;
416
    }
417
418
    /**
419
     * @param mysqli_result $rs
420
     * @param int $col
421
     * @return string|null
422
     */
423
    public function fieldName($rs, $col = 0)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $rs. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
424
    {
425
        $field = $rs->fetch_field_direct($col);
426
427
        return isset($field->name) ? $field->name : null;
428
    }
429
430
    /**
431
     * @param $name
432
     */
433
    public function selectDb($name)
434
    {
435
        $this->conn->select_db($name);
436
    }
437
438
439
    /**
440
     * @param null|mysqli $conn
441
     * @return mixed
442
     */
443
    public function getInsertId($conn = null)
444
    {
445
        if (! ($conn instanceof mysqli)) {
446
            $conn =& $this->conn;
447
        }
448
449
        return $conn->insert_id;
450
    }
451
452
    /**
453
     * @param null|mysqli $conn
454
     * @return int
455
     */
456
    public function getAffectedRows($conn = null)
457
    {
458
        if (! ($conn instanceof mysqli)) {
459
            $conn =& $this->conn;
460
        }
461
462
        return $conn->affected_rows;
463
    }
464
465
    /**
466
     * @param null|mysqli $conn
467
     * @return string
468
     */
469
    public function getLastError($conn = null)
470
    {
471
        if (! ($conn instanceof mysqli)) {
472
            $conn =& $this->conn;
473
        }
474
475
        return $conn->error;
476
    }
477
478
    /**
479
     * @param mysqli_result $ds
480
     * @return int
481
     */
482
    public function getRecordCount($ds)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $ds. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
483
    {
484
        return ($ds instanceof mysqli_result) ? $ds->num_rows : 0;
485
    }
486
487
    /**
488
     * @param mysqli_result $ds
489
     * @param string $mode
490
     * @return array|bool|mixed|object|stdClass
491
     */
492
    public function getRow($ds, $mode = 'assoc')
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $ds. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
493
    {
494
        $out = false;
495
        if ($ds instanceof mysqli_result) {
496
            switch($mode){
497
                case 'assoc':
498
                    $out = $ds->fetch_assoc();
499
                    break;
500
                case 'num':
501
                    $out = $ds->fetch_row();
502
                    break;
503
                case 'object':
504
                    $out = $ds->fetch_object();
505
                    break;
506
                case 'both':
507
                    $out = $ds->fetch_array(MYSQLI_BOTH);
508
                    break;
509
                default:
510
                    $modx = evolutionCMS();
511
                    $modx->messageQuit("Unknown get type ($mode) specified for fetchRow - must be empty, 'assoc', 'num' or 'both'.");
512
513
            }
514
        }
515
        return $out;
516
    }
517
518
    /**
519
     * @param $name
520
     * @param mysqli_result|string $dsq
521
     * @return array
522
     */
523
    public function getColumn($name, $dsq)
524
    {
525
        $col = array();
526
        if ( ! ($dsq instanceof mysqli_result)) {
527
            $dsq = $this->query($dsq);
528
        }
529
        if ($dsq) {
530
            while ($row = $this->getRow($dsq)) {
0 ignored issues
show
Bug introduced by
It seems like $dsq can also be of type boolean; however, EvolutionCMS\Database::getRow() does only seem to accept object<mysqli_result>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
531
                $col[] = $row[$name];
532
            }
533
        }
534
535
        return $col;
536
    }
537
538
    /**
539
     * @param mysqli_result|string $dsq
540
     * @return array
541
     */
542
    public function getColumnNames($dsq)
543
    {
544
        $names = array();
545
        if ( ! ($dsq instanceof mysqli_result)) {
546
            $dsq = $this->query($dsq);
547
        }
548
        if ($dsq) {
549
            $limit = $this->numFields($dsq);
0 ignored issues
show
Bug introduced by
It seems like $dsq can also be of type boolean; however, EvolutionCMS\Database::numFields() does only seem to accept object<mysqli_result>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
550
            for ($i = 0; $i < $limit; $i++) {
551
                $names[] = $this->fieldName($dsq, $i);
0 ignored issues
show
Bug introduced by
It seems like $dsq can also be of type boolean; however, EvolutionCMS\Database::fieldName() does only seem to accept object<mysqli_result>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
552
            }
553
        }
554
555
        return $names;
556
    }
557
558
    /**
559
     * @param mysqli_result|string $dsq
560
     * @return bool|string|int
561
     */
562
    public function getValue($dsq)
563
    {
564
        $out = false;
565
        if ( ! ($dsq instanceof mysqli_result)) {
566
            $dsq = $this->query($dsq);
567
        }
568
        if ($dsq) {
569
            $r = $this->getRow($dsq, 'num');
0 ignored issues
show
Bug introduced by
It seems like $dsq can also be of type boolean; however, EvolutionCMS\Database::getRow() does only seem to accept object<mysqli_result>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Comprehensibility introduced by
Avoid variables with short names like $r. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
570
            $out = isset($r[0]) ? $r[0] : false;
571
        }
572
573
        return $out;
574
    }
575
576
    /**
577
     * @param string $table
578
     * @return array
579
     */
580
    public function getTableMetaData($table)
581
    {
582
        $metadata = array();
583
        if (!empty($table) && is_scalar($table)) {
584
            $sql = 'SHOW FIELDS FROM '.$table;
585
            if ($ds = $this->query($sql)) {
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $ds. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
586
                while ($row = $this->getRow($ds)) {
0 ignored issues
show
Bug introduced by
It seems like $ds defined by $this->query($sql) on line 585 can also be of type boolean; however, EvolutionCMS\Database::getRow() does only seem to accept object<mysqli_result>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
587
                    $fieldName = $row['Field'];
588
                    $metadata[$fieldName] = $row;
589
                }
590
            }
591
        }
592
593
        return $metadata;
594
    }
595
596
    /**
597
     * @param int $timestamp
598
     * @param string $fieldType
599
     * @return false|string
600
     */
601
    public function prepareDate($timestamp, $fieldType = 'DATETIME')
602
    {
603
        $date = false;
604
        if (!$timestamp === false && $timestamp > 0) {
605
            switch ($fieldType) {
606
                case 'DATE' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
607
                    $date = date('Y-m-d', $timestamp);
608
                    break;
609
                case 'TIME' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
610
                    $date = date('H:i:s', $timestamp);
611
                    break;
612
                case 'YEAR' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
613
                    $date = date('Y', $timestamp);
614
                    break;
615
                default :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
616
                    $date = date('Y-m-d H:i:s', $timestamp);
617
                    break;
618
            }
619
        }
620
621
        return $date;
622
    }
623
624
    /**
625
     * @param string|mysqli_result $rs
626
     * @param bool $index
627
     * @return array
628
     */
629
    public function makeArray($rs = '', $index = false)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $rs. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
630
    {
631
        $rsArray = array();
632
        if (!$rs) {
633
            return $rsArray;
634
        }
635
        $iterator = 0;
636
        while ($row = $this->getRow($rs)) {
0 ignored issues
show
Bug introduced by
It seems like $rs defined by parameter $rs on line 629 can also be of type string; however, EvolutionCMS\Database::getRow() does only seem to accept object<mysqli_result>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
637
            $returnIndex = $index !== false && isset($row[$index]) ? $row[$index] : $iterator;
638
            $rsArray[$returnIndex] = $row;
639
            $iterator++;
640
        }
641
642
        return $rsArray;
643
    }
644
645
    /**
646
     * @return string
647
     */
648
    public function getVersion()
649
    {
650
        return $this->conn->server_info;
651
    }
652
653
    public function getFullTableName($tbl)
654
    {
655
        return $this->config['dbase'] . ".`" . $this->config['table_prefix'] . $tbl . "`";
656
    }
657
658
    /**
659
     * @param string $tableName
660
     * @param bool $force
661
     * @return string
662
     */
663
    public function replaceFullTableName($tableName, $force = false)
664
    {
665
        $tableName = trim($tableName);
666
        $dbase = trim($this->config['dbase'], '`');
667
        $prefix = $this->config['table_prefix'];
668
        if ((bool)$force === true) {
669
            $result = "`{$dbase}`.`{$prefix}{$tableName}`";
670
        } elseif (strpos($tableName, '[+prefix+]') !== false) {
671
            $result = preg_replace('@\[\+prefix\+\]([0-9a-zA-Z_]+)@', "`{$dbase}`.`{$prefix}$1`", $tableName);
672
        } else {
673
            $result = $tableName;
674
        }
675
676
        return $result;
677
    }
678
679
    /**
680
     * @param string $table_name
681
     * @return bool|mysqli_result
682
     */
683
    public function optimize($table_name)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $table_name is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
684
    {
685
        $rs = $this->query('OPTIMIZE TABLE '.$table_name);
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $rs. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
686
        if ($rs) {
687
            $rs = $this->query('ALTER TABLE '.$table_name);
688
        }
689
690
        return $rs;
691
    }
692
693
    /**
694
     * @param string $table_name
695
     * @return bool|mysqli_result
696
     */
697
    public function truncate($table_name)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $table_name is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
698
    {
699
        return $this->query('TRUNCATE '.$table_name);
700
    }
701
702
    /**
703
     * @param mysqli_result $result
704
     * @param int $row_number
705
     * @return bool
706
     */
707
    public function dataSeek($result, $row_number)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $row_number is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
708
    {
709
        return $result->data_seek($row_number);
710
    }
711
712
    /**
713
     * @param array $fields
714
     * @return string
715
     */
716
    public function _getFieldsStringFromArray($fields = array())
717
    {
718
719
        if (empty($fields)) {
720
            return '*';
721
        }
722
723
        $_ = array();
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $_. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
724
        foreach ($fields as $k => $v) {
725
            if ($k !== $v) {
726
                $_[] = $v.' as '.$k;
727
            } else {
728
                $_[] = $v;
729
            }
730
        }
731
732
        return implode(',', $_);
733
    }
734
735
    /**
736
     * @param array $tables
737
     * @return string
738
     */
739
    public function _getFromStringFromArray($tables = array())
740
    {
741
        $_ = array();
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $_. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
742
        foreach ($tables as $k => $v) {
743
            $_[] = $v;
744
        }
745
746
        return implode(' ', $_);
747
    }
748
}
749