Test Failed
Push — master ( 843bd1...68b8b4 )
by Joe
04:54
created

Db::qr()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 3
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * MySQL Related Functionality
4
 * @author Joe Huss <[email protected]>
5
 * @copyright 2025
6
 * @package MyAdmin
7
 * @category SQL
8
 */
9
10
namespace MyDb\Mysqli;
11
12
use MyDb\Generic;
13
use MyDb\Db_Interface;
14
15
/**
16
 * Db
17
 *
18
 * @access public
19
 */
20
class Db extends Generic implements Db_Interface
21
{
22
    /**
23
     * @var string
24
     */
25
    public $type = 'mysqli';
26
27
    /**
28
     * alias function of select_db, changes the database we are working with.
29
     *
30
     * @param string $database the name of the database to use
31
     * @return void
32
     */
33 1
    public function useDb($database)
34
    {
35 1
        $this->selectDb($database);
36
    }
37
38
    /**
39
     * changes the database we are working with.
40
     *
41
     * @param string $database the name of the database to use
42
     * @return void
43
     */
44 1
    public function selectDb($database)
45
    {
46 1
        $this->connect();
47 1
        mysqli_select_db($this->linkId, $database);
48
    }
49
50
    /* public: connection management */
51
52
    /**
53
     * Db::connect()
54
     * @param string $database
55
     * @param string $host
56
     * @param string $user
57
     * @param string $password
58
     * @return int|\mysqli
59
     */
60 26
    public function connect($database = '', $host = '', $user = '', $password = '', $port = '')
61
    {
62
        /* Handle defaults */
63 26
        if ($database == '') {
64 26
            $database = $this->database;
65
        }
66 26
        if ($host == '') {
67 26
            $host = $this->host;
68
        }
69 26
        if ($user == '') {
70 26
            $user = $this->user;
71
        }
72 26
        if ($password == '') {
73 26
            $password = $this->password;
74
        }
75 26
        if ($port == '') {
76 26
            $port = $this->port;
77
        }
78
        /* establish connection, select database */
79 26
        if (!is_object($this->linkId)) {
80 26
            $this->connectionAttempt++;
81 26
            if ($this->connectionAttempt >= $this->maxConnectErrors - 1) {
82 6
                error_log("MySQLi Connection Attempt #{$this->connectionAttempt}/{$this->maxConnectErrors}");
83
exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
84 26
            }
85
            if ($this->connectionAttempt >= $this->maxConnectErrors) {
86
                $this->halt("connect($host, $user, \$password) failed. ".(is_object($this->linkId) && isset( $this->linkId->connect_error) ? $this->linkId->connect_error : ''));
0 ignored issues
show
introduced by
The condition is_object($this->linkId) is always false.
Loading history...
87
                return 0;
88 26
            }
89 26
            //error_log("real_connect($host, $user, $password, $database, $port)");
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
90 26
            $this->linkId = mysqli_init();
91
            $this->linkId->options(MYSQLI_INIT_COMMAND, "SET NAMES {$this->characterSet} COLLATE {$this->collation}, COLLATION_CONNECTION = {$this->collation}, COLLATION_DATABASE = {$this->collation}");
92
            if (!$this->linkId->real_connect($host, $user, $password, $database, $port != '' ? $port : NULL)) {
93 26
                $this->halt("connect($host, $user, \$password) failed. ".(is_object($this->linkId) && isset( $this->linkId->connect_error) ? $this->linkId->connect_error : ''));
94
                return 0;
95 26
            }
96 26
            $this->linkId->set_charset($this->characterSet);
97
            if ($this->linkId->connect_errno) {
98
                $this->halt("connect($host, $user, \$password) failed. ".(is_object($this->linkId) && isset( $this->linkId->connect_error) ? $this->linkId->connect_error : ''));
99
                return 0;
100
            }
101 26
        }
102
        return $this->linkId;
103
    }
104
105
    /**
106
     * Db::disconnect()
107
     * @return bool
108 1
     */
109
    public function disconnect()
110 1
    {
111 1
        $return = !is_int($this->linkId) && method_exists($this->linkId, 'close') ? $this->linkId->close() : false;
112 1
        $this->linkId = 0;
113
        return $return;
114
    }
115
116
    /**
117
     * @param $string
118
     * @return string
119 2
     */
120
    public function real_escape($string = '')
121 2
    {
122
        if ((!is_resource($this->linkId) || $this->linkId == 0) && !$this->connect()) {
0 ignored issues
show
introduced by
The condition is_resource($this->linkId) is always false.
Loading history...
123
            return $this->escape($string);
124 2
        }
125
        return mysqli_real_escape_string($this->linkId, $string);
0 ignored issues
show
Bug introduced by
It seems like $this->linkId can also be of type integer and resource; however, parameter $mysql of mysqli_real_escape_string() does only seem to accept mysqli, maybe add an additional type check? ( Ignorable by Annotation )

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

125
        return mysqli_real_escape_string(/** @scrutinizer ignore-type */ $this->linkId, $string);
Loading history...
126
    }
127
128
    /**
129
     * discard the query result
130
     * @return void
131 1
     */
132
    public function free()
133 1
    {
134
        if (is_resource($this->queryId)) {
0 ignored issues
show
introduced by
The condition is_resource($this->queryId) is always false.
Loading history...
135
            @mysqli_free_result($this->queryId);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mysqli_free_result(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

135
            /** @scrutinizer ignore-unhandled */ @mysqli_free_result($this->queryId);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
136 1
        }
137
        $this->queryId = 0;
138
    }
139
140
    /**
141
     * Db::queryReturn()
142
     *
143
     * Sends an SQL query to the server like the normal query() command but iterates through
144
     * any rows and returns the row or rows immediately or FALSE on error
145
     *
146
     * @param mixed $query SQL Query to be used
147
     * @param string $line optionally pass __LINE__ calling the query for logging
148
     * @param string $file optionally pass __FILE__ calling the query for logging
149
     * @return mixed FALSE if no rows, if a single row it returns that, if multiple it returns an array of rows, associative responses only
150 1
     */
151
    public function queryReturn($query, $line = '', $file = '')
152 1
    {
153 1
        $this->query($query, $line, $file);
0 ignored issues
show
Bug introduced by
$line of type string is incompatible with the type integer expected by parameter $line of MyDb\Mysqli\Db::query(). ( Ignorable by Annotation )

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

153
        $this->query($query, /** @scrutinizer ignore-type */ $line, $file);
Loading history...
154 1
        if ($this->num_rows() == 0) {
155 1
            return false;
156 1
        } elseif ($this->num_rows() == 1) {
157 1
            $this->next_record(MYSQLI_ASSOC);
158
            return $this->Record;
159 1
        } else {
160 1
            $out = [];
161 1
            while ($this->next_record(MYSQLI_ASSOC)) {
162
                $out[] = $this->Record;
163 1
            }
164
            return $out;
165
        }
166
    }
167
168
    /**
169
     * db:qr()
170
     *
171
     *  alias of queryReturn()
172
     *
173
     * @param mixed $query SQL Query to be used
174
     * @param string $line optionally pass __LINE__ calling the query for logging
175
     * @param string $file optionally pass __FILE__ calling the query for logging
176
     * @return mixed FALSE if no rows, if a single row it returns that, if multiple it returns an array of rows, associative responses only
177 1
     */
178
    public function qr($query, $line = '', $file = '')
179 1
    {
180
        return $this->queryReturn($query, $line, $file);
181
    }
182
183
    /**
184
     * creates a prepaired statement from query
185
     *
186
     * @param string $query sql query like INSERT INTO table (col) VALUES (?)  or  SELECT * from table WHERE col1 = ? and col2 = ?  or  UPDATE table SET col1 = ?, col2 = ? WHERE col3 = ?
187
     * @return int|\MyDb\Mysqli\mysqli_stmt
0 ignored issues
show
Bug introduced by
The type MyDb\Mysqli\mysqli_stmt was not found. Did you mean mysqli_stmt? If so, make sure to prefix the type with \.
Loading history...
188
     * @param string $line
189
     * @param string $file
190 1
     */
191
    public function prepare($query, $line = '', $file = '')
192 1
    {
193
        if (!$this->connect()) {
194
            return 0;
195 1
        }
196 1
        $haltPrev = $this->haltOnError;
0 ignored issues
show
Unused Code introduced by
The assignment to $haltPrev is dead and can be removed.
Loading history...
197 1
        $this->haltOnError = 'no';
198 1
        $start = microtime(true);
199 1
        $prepare = mysqli_prepare($this->linkId, $query);
200 1
        if (!isset($GLOBALS['disable_db_queries'])) {
201
            $this->addLog($query, microtime(true) - $start, $line, $file);
202
        }
203
        return $prepare;
204
    }
205
206
    /**
207
     * Db::query()
208
     *
209
     *  Sends an SQL query to the database
210
     *
211
     * @param mixed $queryString
212
     * @param int $line
213 10
     * @param string $file
214
     * @param bool $log
215
     * @return mixed 0 if no query or query id handler, safe to ignore this return
216
     */
217
    public function query($queryString, $line = '', $file = '', $log = false)
218
    {
219
        /* No empty queries, please, since PHP4 chokes on them. */
220 10
        /* The empty query string is passed on from the constructor,
221 1
        * when calling the class without a query, e.g. in situations
222
        * like these: '$db = new db_Subclass;'
223 10
        */
224
        if ($queryString == '') {
225
            return 0;
226
        }
227 10
        if (!$this->connect()) {
228 10
            return 0;
229
            /* we already complained in connect() about that. */
230 10
        }
231
        $haltPrev = $this->haltOnError;
232
        $this->haltOnError = 'no';
233 10
        // New query, discard previous result.
234 1
        if (is_resource($this->queryId)) {
235
            $this->free();
236 10
        }
237
        if ($this->Debug) {
238
            printf("Debug: query = %s<br>\n", $queryString);
239 10
        }
240 10
        if ($log === true || (isset($GLOBALS['log_queries']) && $GLOBALS['log_queries'] !== false)) {
241 10
            $this->log($queryString, $line, $file);
242 10
        }
243 10
        $tries = 2;
244 10
        $try = 0;
245
        $this->queryId = false;
246
        while ((null === $this->queryId || $this->queryId === false) && $try <= $tries) {
247
            $try++;
248 10
            if ($try > 1) {
249 10
                @mysqli_close($this->linkId);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mysqli_close(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

249
                /** @scrutinizer ignore-unhandled */ @mysqli_close($this->linkId);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
250 10
                $this->linkId = 0;
251 10
            }
252
            $start = microtime(true);
253
            $onlyRollback = true;
254
            $fails = -1;
255
            while ($fails < 30 && (null === $this->queryId || $this->queryId === false)) {
256
                $this->connect();
257
                $fails++;
258 10
                try {
259
                    $this->queryId = @mysqli_query($this->linkId, $queryString, MYSQLI_STORE_RESULT);
260
                    if (in_array((int)@mysqli_errno($this->linkId), [1213, 2006, 3101, 1180])) {
261 10
                        //error_log("got ".@mysqli_errno($this->linkId)." sql error fails {$fails} on query {$queryString} from {$line}:{$file}");
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
262 10
                        usleep(250000); // 0.25 second
263 10
                    } else {
264 10
                        $onlyRollback = false;
265 10
                        if (in_array((int)@mysqli_errno($this->linkId), [1064])) {
266
                            $tries = 0;
267
                        }
268
                        break;
269 10
                    }
270 10
                } catch (\mysqli_sql_exception $e) {
271
                    if (in_array((int)$e->getCode(), [1213, 2006, 3101, 1180])) {
272
                        //error_log("got ".$e->getCode()." sql error fails {$fails}");
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
273
                        usleep(250000); // 0.25 second
274
                    } else {
275 10
                        error_log('Got mysqli_sql_exception code '.$e->getCode().' error '.$e->getMessage().' on query '.$queryString.' from '.$line.':'.$file);
276
                        $onlyRollback = false;
277
                        if (in_array((int)@mysqli_errno($this->linkId), [1064])) {
278
                            $tries = 0;
279
                        }
280
                        break;
281 1
                    }
282
                }
283 1
            }
284 1
            if (!isset($GLOBALS['disable_db_queries'])) {
285
                $this->addLog($queryString, microtime(true) - $start, $line, $file);
286
            }
287
            $this->Row = 0;
288
            $this->Errno = @mysqli_errno($this->linkId);
289
            $this->Error = @mysqli_error($this->linkId);
290
            if ($try == 1 && (null === $this->queryId || $this->queryId === false)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
291
                //$this->emailError($queryString, 'Error #'.$this->Errno.': '.$this->Error, $line, $file);
0 ignored issues
show
Unused Code Comprehensibility introduced by
66% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
292
            }
293
        }
294
        $this->haltOnError = $haltPrev;
295 6
        if ($onlyRollback === true && false === $this->queryId) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $onlyRollback does not seem to be defined for all execution paths leading up to this point.
Loading history...
296
            error_log('Got MySQLi 3101 Rollback Error '.$fails.' Times, Giving Up on '.$queryString.' from '.$line.':'.$file.' on '.__LINE__.':'.__FILE__);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $fails does not seem to be defined for all execution paths leading up to this point.
Loading history...
297 6
        }
298
        if (null === $this->queryId || $this->queryId === false) {
299
            $this->emailError($queryString, 'Error #'.$this->Errno.': '.$this->Error, $line, $file);
300
            $this->halt('', $line, $file);
301
        }
302 6
303 6
        // Will return nada if it fails. That's fine.
304 6
        return $this->queryId;
305 6
    }
306
307 6
    /**
308 6
     * @return array|null|object
309
     */
310
    public function fetchObject()
311 6
    {
312
        $this->Record = @mysqli_fetch_object($this->queryId);
0 ignored issues
show
Bug introduced by
$this->queryId of type integer is incompatible with the type mysqli_result expected by parameter $result of mysqli_fetch_object(). ( Ignorable by Annotation )

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

312
        $this->Record = @mysqli_fetch_object(/** @scrutinizer ignore-type */ $this->queryId);
Loading history...
313
        return $this->Record;
314
    }
315
316
    /* public: walk result set */
317
318
    /**
319
     * Db::next_record()
320 1
     *
321
     * @param mixed $resultType
322 1
     * @return bool
323 1
     */
324 1
    public function next_record($resultType = MYSQLI_BOTH)
325
    {
326 1
        if ($this->queryId === false) {
0 ignored issues
show
introduced by
The condition $this->queryId === false is always false.
Loading history...
327
            $this->haltmsg('next_record called with no query pending.');
328 1
            return 0;
329 1
        }
330 1
331 1
        $this->Record = @mysqli_fetch_array($this->queryId, $resultType);
0 ignored issues
show
Bug introduced by
$this->queryId of type integer is incompatible with the type mysqli_result expected by parameter $result of mysqli_fetch_array(). ( Ignorable by Annotation )

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

331
        $this->Record = @mysqli_fetch_array(/** @scrutinizer ignore-type */ $this->queryId, $resultType);
Loading history...
332
        ++$this->Row;
333 1
        $this->Errno = mysqli_errno($this->linkId);
0 ignored issues
show
Bug introduced by
It seems like $this->linkId can also be of type integer; however, parameter $mysql of mysqli_errno() does only seem to accept mysqli, maybe add an additional type check? ( Ignorable by Annotation )

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

333
        $this->Errno = mysqli_errno(/** @scrutinizer ignore-type */ $this->linkId);
Loading history...
334
        $this->Error = mysqli_error($this->linkId);
0 ignored issues
show
Bug introduced by
It seems like $this->linkId can also be of type integer; however, parameter $mysql of mysqli_error() does only seem to accept mysqli, maybe add an additional type check? ( Ignorable by Annotation )

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

334
        $this->Error = mysqli_error(/** @scrutinizer ignore-type */ $this->linkId);
Loading history...
335
336
        $stat = is_array($this->Record);
337
        if (!$stat && $this->autoFree && is_resource($this->queryId)) {
0 ignored issues
show
introduced by
The condition is_resource($this->queryId) is always false.
Loading history...
338
            $this->free();
339
        }
340
        return $stat;
341 26
    }
342
343 26
    /**
344
     * switch to position in result set
345
     *
346 26
     * @param integer $pos the row numbe starting at 0 to switch to
347
     * @return bool whetherit was successfu or not.
348
     */
349 26
    public function seek($pos = 0)
350
    {
351
        $status = @mysqli_data_seek($this->queryId, $pos);
0 ignored issues
show
Bug introduced by
$this->queryId of type integer is incompatible with the type mysqli_result expected by parameter $result of mysqli_data_seek(). ( Ignorable by Annotation )

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

351
        $status = @mysqli_data_seek(/** @scrutinizer ignore-type */ $this->queryId, $pos);
Loading history...
352
        if ($status) {
353
            $this->Row = $pos;
354
        } else {
355
            $this->haltmsg("seek({$pos}) failed: result has ".$this->num_rows().' rows', __LINE__, __FILE__);
356
            /* half assed attempt to save the day, but do not consider this documented or even desirable behaviour. */
357 1
            $rows = $this->num_rows();
358
            @mysqli_data_seek($this->queryId, $rows);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mysqli_data_seek(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

358
            /** @scrutinizer ignore-unhandled */ @mysqli_data_seek($this->queryId, $rows);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
359 1
            $this->Row = $rows;
360
            return false;
361
        }
362 1
        return true;
363
    }
364
365
    /**
366
     * Initiates a transaction
367
     *
368
     * @return bool
369
     */
370 26
    public function transactionBegin()
371
    {
372 26
        if (version_compare(PHP_VERSION, '5.5.0') < 0) {
373
            return true;
374
        }
375 26
        if (!$this->connect()) {
376
            return 0;
377
        }
378
        return mysqli_begin_transaction($this->linkId);
379
    }
380
381
    /**
382
     * Commits a transaction
383
     *
384
     * @return bool
385
     */
386
    public function transactionCommit()
387 2
    {
388
        if (version_compare(PHP_VERSION, '5.5.0') < 0 || $this->linkId === 0) {
389 2
            return true;
390
        }
391
        return mysqli_commit($this->linkId);
0 ignored issues
show
Bug introduced by
It seems like $this->linkId can also be of type integer; however, parameter $mysql of mysqli_commit() does only seem to accept mysqli, maybe add an additional type check? ( Ignorable by Annotation )

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

391
        return mysqli_commit(/** @scrutinizer ignore-type */ $this->linkId);
Loading history...
392
    }
393 2
394
    /**
395
     * Rolls back a transaction
396
     *
397
     * @return bool
398
     */
399
    public function transactionAbort()
400
    {
401
        if (version_compare(PHP_VERSION, '5.5.0') < 0 || $this->linkId === 0) {
402
            return true;
403
        }
404 1
        return mysqli_rollback($this->linkId);
0 ignored issues
show
Bug introduced by
It seems like $this->linkId can also be of type integer; however, parameter $mysql of mysqli_rollback() does only seem to accept mysqli, maybe add an additional type check? ( Ignorable by Annotation )

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

404
        return mysqli_rollback(/** @scrutinizer ignore-type */ $this->linkId);
Loading history...
405
    }
406 1
407 1
    /**
408 1
     * This will get the last insert ID created on the current connection.  Should only be called after an insert query is
409 1
     * run on a table that has an auto incrementing field.  $table and $field are required, but unused here since it's
410 1
     * unnecessary for mysql.  For compatibility with pgsql, the params must be supplied.
411
     *
412
     * @param string $table
413 1
     * @param string $field
414
     * @return int|string
415
     */
416 1
    public function getLastInsertId($table, $field)
417
    {
418 1
        if (!isset($table) || $table == '' || !isset($field) || $field == '') {
419
            return -1;
420 1
        }
421 1
422
        return @mysqli_insert_id($this->linkId);
0 ignored issues
show
Bug introduced by
It seems like $this->linkId can also be of type integer; however, parameter $mysql of mysqli_insert_id() does only seem to accept mysqli, maybe add an additional type check? ( Ignorable by Annotation )

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

422
        return @mysqli_insert_id(/** @scrutinizer ignore-type */ $this->linkId);
Loading history...
423
    }
424
425 1
    /* public: table locking */
426
427
    /**
428
     * Db::lock()
429
     * @param mixed  $table
430
     * @param string $mode
431
     * @return bool|int|\mysqli_result
432
     */
433 2
    public function lock($table, $mode = 'write')
434
    {
435 2
        $this->connect();
436
        $query = 'lock tables ';
437 2
        if (is_array($table)) {
438 2
            foreach ($table as $key => $value) {
439
                if ($key == 'read' && $key != 0) {
440
                    $query .= "$value read, ";
441
                } else {
442 2
                    $query .= "$value $mode, ";
443
                }
444
            }
445
            $query = mb_substr($query, 0, -2);
446
        } else {
447
            $query .= "$table $mode";
448
        }
449
        $res = @mysqli_query($this->linkId, $query);
450
        if (!$res) {
451 2
            $this->halt("lock($table, $mode) failed.");
452
            return 0;
453 2
        }
454
        return $res;
455
    }
456
457
    /**
458
     * Db::unlock()
459
     * @param bool $haltOnError optional, defaults to TRUE, whether or not to halt on error
460 6
     * @return bool|int|\mysqli_result
461
     */
462 6
    public function unlock($haltOnError = true)
463
    {
464
        $this->connect();
465
466
        $res = @mysqli_query($this->linkId, 'unlock tables');
467
        if ($haltOnError === true && !$res) {
468
            $this->halt('unlock() failed.');
469 1
            return 0;
470
        }
471 1
        return $res;
472
    }
473
474
    /* public: evaluate the result (size, width) */
475
476
    /**
477
     * Db::affectedRows()
478
     * @return int
479 1
     */
480
    public function affectedRows()
481 1
    {
482 1
        return @mysqli_affected_rows($this->linkId);
0 ignored issues
show
Bug introduced by
It seems like $this->linkId can also be of type integer; however, parameter $mysql of mysqli_affected_rows() does only seem to accept mysqli, maybe add an additional type check? ( Ignorable by Annotation )

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

482
        return @mysqli_affected_rows(/** @scrutinizer ignore-type */ $this->linkId);
Loading history...
483 1
    }
484 1
485 1
    /**
486 1
     * Db::num_rows()
487 1
     * @return int
488 1
     */
489
    public function num_rows()
490 1
    {
491
        return @mysqli_num_rows($this->queryId);
0 ignored issues
show
Bug introduced by
$this->queryId of type integer is incompatible with the type mysqli_result expected by parameter $result of mysqli_num_rows(). ( Ignorable by Annotation )

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

491
        return @mysqli_num_rows(/** @scrutinizer ignore-type */ $this->queryId);
Loading history...
492
    }
493
494
    /**
495
     * Db::num_fields()
496
     * @return int
497
     */
498
    public function num_fields()
499
    {
500
        return @mysqli_num_fields($this->queryId);
0 ignored issues
show
Bug introduced by
$this->queryId of type integer is incompatible with the type mysqli_result expected by parameter $result of mysqli_num_fields(). ( Ignorable by Annotation )

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

500
        return @mysqli_num_fields(/** @scrutinizer ignore-type */ $this->queryId);
Loading history...
501
    }
502
503
    /**
504
     * gets an array of the table names in teh current datase
505
     *
506
     * @return array
507
     */
508
    public function tableNames()
509
    {
510
        $return = [];
511
        $this->query('SHOW TABLES');
512
        $i = 0;
513
        while ($info = $this->queryId->fetch_row()) {
0 ignored issues
show
Bug introduced by
The method fetch_row() does not exist on integer. ( Ignorable by Annotation )

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

513
        while ($info = $this->queryId->/** @scrutinizer ignore-call */ fetch_row()) {

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...
514
            $return[$i]['table_name'] = $info[0];
515
            $return[$i]['tablespace_name'] = $this->database;
516
            $return[$i]['database'] = $this->database;
517
            ++$i;
518
        }
519
        return $return;
520
    }
521
}
522
523
/**
524
 * @param $result
525
 * @param $row
526
 * @param int|string $field
527
 * @return bool
528
 */
529
/*
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
530
function mysqli_result($result, $row, $field = 0) {
531
    if ($result === false) return false;
532
    if ($row >= mysqli_num_rows($result)) return false;
533
    if (is_string($field) && !(mb_strpos($field, '.') === false)) {
534
        $tField = explode('.', $field);
535
        $field = -1;
536
        $tFields = mysqli_fetch_fields($result);
537
        for ($id = 0, $idMax = mysqli_num_fields($result); $id < $idMax; $id++) {
538
            if ($tFields[$id]->table == $tField[0] && $tFields[$id]->name == $tField[1]) {
539
                $field = $id;
540
                break;
541
            }
542
        }
543
        if ($field == -1) return false;
544
    }
545
    mysqli_data_seek($result, $row);
546
    $line = mysqli_fetch_array($result);
547
    return isset($line[$field]) ? $line[$field] : false;
548
}
549
*/
550