Test Failed
Push — master ( 3db190...3fa664 )
by Joe
15:20 queued 11:30
created
src/Generic.php 1 patch
Indentation   +383 added lines, -383 removed lines patch added patch discarded remove patch
@@ -14,387 +14,387 @@
 block discarded – undo
14 14
  */
15 15
 abstract class Generic
16 16
 {
17
-    /* public: connection parameters */
18
-    public $host = 'localhost';
19
-    public $database = '';
20
-    public $user = '';
21
-    public $password = '';
22
-    public $port = '';
23
-
24
-    /* public: configuration parameters */
25
-    public $autoStripslashes = false;
26
-    public $Debug = 0; // Set to 1 for debugging messages.
27
-    public $haltOnError = 'yes'; // "yes" (halt with message), "no" (ignore errors quietly), "report" (ignore error, but spit a warning)
28
-
29
-    public $maxConnectErrors = 5;
30
-    public $connectionAttempt = 0;
31
-    public $maxMatches = 10000000;
32
-
33
-    public $Type = 'mysql';
34
-
35
-    /**
36
-     * @var int
37
-     */
38
-    public $autoFree = 0; // Set to 1 for automatic mysql_free_result()
39
-
40
-    /* public: result array and current row number */
41
-    public $Record = [];
42
-    public $Row;
43
-
44
-    /* public: current error number and error text */
45
-    public $Errno = 0;
46
-    public $Error = '';
47
-
48
-    /* public: this is an api revision, not a CVS revision. */
49
-    public $type = 'generic';
50
-
51
-    /**
52
-     * @var int|object
53
-     */
54
-    public $linkId = 0;
55
-    public $queryId = 0;
56
-
57
-    public $characterSet = 'utf8mb4';
58
-    public $collation = 'utf8mb4_unicode_ci';
59
-
60
-    /**
61
-     * Logged queries.
62
-     * @var array
63
-     */
64
-    protected $log = [];
65
-
66
-    /**
67
-     * Constructs the db handler, can optionally specify connection parameters
68
-     *
69
-     * @param string $database Optional The database name
70
-     * @param string $user Optional The username to connect with
71
-     * @param string $password Optional The password to use
72
-     * @param string $host Optional The hostname where the server is, or default to localhost
73
-     * @param string $query Optional query to perform immediately
74
-     * @param string $port optional port for the connection
75
-     */
76
-    public function __construct($database = '', $user = '', $password = '', $host = 'localhost', $query = '', $port = '')
77
-    {
78
-        $this->database = $database;
79
-        $this->user = $user;
80
-        $this->password = $password;
81
-        $this->host = $host;
82
-        $this->port = $port;
83
-        if ($query != '') {
84
-            $this->query($query);
85
-        }
86
-        $this->connectionAttempt = 0;
87
-    }
88
-
89
-    /**
90
-     * @param string $message
91
-     * @param string $line
92
-     * @param string $file
93
-     * @return void
94
-     */
95
-    public function log($message, $line = '', $file = '', $level = 'info')
96
-    {
97
-        error_log($message);
98
-    }
99
-
100
-    /**
101
-     * @return int|object
102
-     */
103
-    public function linkId()
104
-    {
105
-        return $this->linkId;
106
-    }
107
-
108
-    /**
109
-     * @return int|object
110
-     */
111
-    public function queryId()
112
-    {
113
-        return $this->queryId;
114
-    }
115
-
116
-    /**
117
-     * @param $string
118
-     * @return string
119
-     */
120
-    public function real_escape($string = '')
121
-    {
122
-        if ((!is_resource($this->linkId) || $this->linkId == 0) && !$this->connect()) {
123
-            return $this->escape($string);
124
-        }
125
-        return mysqli_real_escape_string($this->linkId, $string);
126
-    }
127
-
128
-    /**
129
-     * @param $string
130
-     * @return string
131
-     */
132
-    public function escape($string = '')
133
-    {
134
-        //if (function_exists('mysql_escape_string'))
135
-        //return mysql_escape_string($string);
136
-        return str_replace(['\\', "\0", "\n", "\r", "'", '"', "\x1a"], ['\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'], $string);
137
-    }
138
-
139
-    /**
140
-     * @param mixed $str
141
-     * @return string
142
-     */
143
-    public function dbAddslashes($str = '')
144
-    {
145
-        if (!isset($str) || $str == '') {
146
-            return '';
147
-        }
148
-        return addslashes($str);
149
-    }
150
-
151
-    /**
152
-     * Db::toTimestamp()
153
-     * @param mixed $epoch
154
-     * @return bool|string
155
-     */
156
-    public function toTimestamp($epoch)
157
-    {
158
-        return date('Y-m-d H:i:s', is_float($epoch) ? intval($epoch) : $epoch);
159
-    }
160
-
161
-    /**
162
-     * Db::fromTimestamp()
163
-     * @param mixed $timestamp
164
-     * @return bool|int|mixed
165
-     */
166
-    public function fromTimestamp($timestamp)
167
-    {
168
-        if (preg_match('/([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/', $timestamp, $parts)) {
169
-            $time = mktime($parts[4], $parts[5], $parts[6], $parts[2], $parts[3], $parts[1]);
170
-        } elseif (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/', $timestamp, $parts)) {
171
-            $time = mktime($parts[4], $parts[5], $parts[6], $parts[2], $parts[3], $parts[1]);
172
-        } elseif (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})/', $timestamp, $parts)) {
173
-            $time = mktime(1, 1, 1, $parts[2], $parts[3], $parts[1]);
174
-        } elseif (is_numeric($timestamp) && $timestamp >= 943938000) {
175
-            $time = $timestamp;
176
-        } else {
177
-            $this->log('Cannot Match Timestamp from '.$timestamp, __LINE__, __FILE__);
178
-            $time = false;
179
-        }
180
-        return $time;
181
-    }
182
-
183
-    /**
184
-     * perform a query with limited result set
185
-     *
186
-     * @param string $queryString
187
-     * @param string|int $numRows
188
-     * @param int $offset
189
-     * @param string|int $line
190
-     * @param string $file
191
-     * @return mixed
192
-     */
193
-    public function limitQuery($queryString, $numRows = '', $offset = 0, $line = '', $file = '')
194
-    {
195
-        if (!$numRows) {
196
-            $numRows = $this->maxMatches;
197
-        }
198
-        if ($offset == 0) {
199
-            $queryString .= ' LIMIT '.(int) $numRows;
200
-        } else {
201
-            $queryString .= ' LIMIT '.(int) $offset.','.(int) $numRows;
202
-        }
203
-
204
-        if ($this->Debug) {
205
-            printf("Debug: limitQuery = %s<br>offset=%d, num_rows=%d<br>\n", $queryString, $offset, $numRows);
206
-        }
207
-
208
-        return $this->query($queryString, $line, $file);
209
-    }
210
-
211
-    /**
212
-     * db:qr()
213
-     *
214
-     *  alias of queryReturn()
215
-     *
216
-     * @param mixed $query SQL Query to be used
217
-     * @param string $line optionally pass __LINE__ calling the query for logging
218
-     * @param string $file optionally pass __FILE__ calling the query for logging
219
-     * @return mixed FALSE if no rows, if a single row it returns that, if multiple it returns an array of rows, associative responses only
220
-     */
221
-    public function qr($query, $line = '', $file = '')
222
-    {
223
-        return $this->queryReturn($query, $line, $file);
224
-    }
225
-
226
-    /**
227
-     * gets a field
228
-     *
229
-     * @param mixed  $name
230
-     * @param string $stripSlashes
231
-     * @return string
232
-     */
233
-    public function f($name, $stripSlashes = '')
234
-    {
235
-        if (is_null($this->Record)) {
236
-            return null;
237
-        } elseif ($stripSlashes || ($this->autoStripslashes && !$stripSlashes)) {
238
-            return stripslashes($this->Record[$name]);
239
-        } else {
240
-            return $this->Record[$name];
241
-        }
242
-    }
243
-
244
-    /**
245
-     * error handling
246
-     *
247
-     * @param mixed $msg
248
-     * @param string $line
249
-     * @param string $file
250
-     * @return void
251
-     */
252
-    public function halt($msg, $line = '', $file = '')
253
-    {
254
-        $this->unlock(false);
255
-        /* Just in case there is a table currently locked */
256
-
257
-        //$this->Error = @$this->linkId->error;
258
-        //$this->Errno = @$this->linkId->errno;
259
-        if ($this->haltOnError == 'no') {
260
-            return true;
261
-        }
262
-        if ($msg != '') {
263
-            $this->haltmsg($msg, $line, $file);
264
-        }
265
-        if ($this->haltOnError != 'report') {
266
-            echo '<p><b>Session halted.</b>';
267
-            //if (isset($GLOBALS['tf']))
268
-            //$GLOBALS['tf']->terminate();
269
-            die();
270
-        }
271
-        return true;
272
-    }
273
-
274
-    /**
275
-     * @param mixed $msg
276
-     * @param string $line
277
-     * @param string $file
278
-     * @return mixed|void
279
-     */
280
-    public function logBackTrace($msg, $line = '', $file = '')
281
-    {
282
-        $backtrace = (function_exists('debug_backtrace') ? debug_backtrace() : []);
283
-        $this->log(
284
-            ('' !== getenv('REQUEST_URI') ? ' '.getenv('REQUEST_URI') : '').
285
-            ((isset($_POST) && count($_POST)) ? ' POST='.json_encode($_POST) : '').
286
-            ((isset($_GET) && count($_GET)) ? ' GET='.json_encode($_GET) : '').
287
-            ((isset($_FILES) && count($_FILES)) ? ' FILES='.json_encode($_FILES) : '').
288
-            ('' !== getenv('HTTP_USER_AGENT') ? ' AGENT="'.getenv('HTTP_USER_AGENT').'"' : '').
289
-            (isset($_SERVER['REQUEST_METHOD']) ? ' METHOD="'.$_SERVER['REQUEST_METHOD'].'"'.
290
-                ($_SERVER['REQUEST_METHOD'] === 'POST' ? ' POST="'.json_encode($_POST).'"' : '') : ''),
291
-            $line,
292
-            $file,
293
-            'error'
294
-        );
295
-        for ($level = 1, $levelMax = count($backtrace); $level < $levelMax; $level++) {
296
-            $message = (isset($backtrace[$level]['file']) ? 'File: '.$backtrace[$level]['file'] : '').
297
-                (isset($backtrace[$level]['line']) ? ' Line: '.$backtrace[$level]['line'] : '').
298
-                ' Function: '.(isset($backtrace[$level] ['class']) ? '(class '.$backtrace[$level] ['class'].') ' : '').
299
-                (isset($backtrace[$level] ['type']) ? $backtrace[$level] ['type'].' ' : '').
300
-                $backtrace[$level] ['function'].'(';
301
-            if (isset($backtrace[$level] ['args'])) {
302
-                for ($argument = 0, $argumentMax = count($backtrace[$level]['args']); $argument < $argumentMax; $argument++) {
303
-                    $message .= ($argument > 0 ? ', ' : '').
304
-                        (is_object($backtrace[$level]['args'][$argument]) ? 'class '.get_class($backtrace[$level]['args'][$argument]) : json_encode($backtrace[$level]['args'][$argument]));
305
-                }
306
-            }
307
-            $message .= ')';
308
-            $this->log($message, $line, $file, 'error');
309
-        }
310
-    }
311
-
312
-    public function emailError($queryString, $error, $line, $file)
313
-    {
314
-        $subject = php_uname('n').' MySQLi Error '.$queryString;
315
-        if (class_exists('\\TFSmarty')) {
316
-            $smarty = new \TFSmarty();
317
-            $smarty->assign([
318
-                'type' => $this->type,
319
-                'queryString' => $queryString,
320
-                'error' => $error,
321
-                'line' => $line,
322
-                'file' => $file,
323
-                'request' => $_REQUEST,
324
-                'server' => $_SERVER,
325
-            ]);
326
-            if (isset($GLOBALS['tf'])) {
327
-                $smarty->assign('account_id', $GLOBALS['tf']->session->account_id);
328
-            }
329
-            $email = $smarty->fetch('email/admin/sql_error.tpl');
330
-            (new \MyAdmin\Mail())->adminMail($subject, $email, '[email protected]', '');
331
-            (new \MyAdmin\Mail())->adminMail($subject, $email, '[email protected]', '');
332
-        }
333
-        $this->haltmsg('Invalid SQL: '.$queryString, $line, $file);
334
-    }
335
-
336
-    /**
337
-     * @param mixed $msg
338
-     * @param string $line
339
-     * @param string $file
340
-     * @return mixed|void
341
-     */
342
-    public function haltmsg($msg, $line = '', $file = '')
343
-    {
344
-        $email = "DB Error {$msg} {$file}:{$line}";
345
-        if (class_exists('\\MyAdmin\Mail')) {
346
-            \MyAdmin\Mail::failsafeMail($email, $email, ['[email protected]', '[email protected]']);
347
-            return;
348
-        }
349
-        $this->log("Database error: $msg", $line, $file, 'error');
350
-        if ($this->Errno != '0' || !in_array($this->Error, ['', '()'])) {
351
-            $sqlstate = mysqli_sqlstate($this->linkId);
352
-            $this->log("MySQLi SQLState: {$sqlstate}. Error: ".$this->Errno.' ('.$this->Error.')', $line, $file, 'error');
353
-        }
354
-        $this->logBackTrace($msg, $line, $file);
355
-    }
356
-
357
-    /**
358
-     * @return array
359
-     */
360
-    public function indexNames()
361
-    {
362
-        return [];
363
-    }
364
-
365
-
366
-    /**
367
-     * Add query to logged queries.
368
-     * @param string $statement
369
-     * @param float $time Elapsed seconds with microseconds
370
-     * @param string|int $line Line Number
371
-     * @param string $file File Name
372
-     */
373
-    public function addLog($statement, $time, $line = '', $file = '')
374
-    {
375
-        $query = [
376
-            'statement' => $statement,
377
-            'time' => $time * 1000
378
-        ];
379
-        if ($line != '') {
380
-            $query['line'] = $line;
381
-        }
382
-        if ($file != '') {
383
-            $query['file'] = $file;
384
-        }
385
-        if (!isset($GLOBALS['db_queries'])) {
386
-            $GLOBALS['db_queries'] = [];
387
-        }
388
-        $GLOBALS['db_queries'][] = $query;
389
-        array_push($this->log, $query);
390
-    }
391
-
392
-    /**
393
-     * Return logged queries.
394
-     * @return array Logged queries
395
-     */
396
-    public function getLog()
397
-    {
398
-        return $this->log;
399
-    }
17
+	/* public: connection parameters */
18
+	public $host = 'localhost';
19
+	public $database = '';
20
+	public $user = '';
21
+	public $password = '';
22
+	public $port = '';
23
+
24
+	/* public: configuration parameters */
25
+	public $autoStripslashes = false;
26
+	public $Debug = 0; // Set to 1 for debugging messages.
27
+	public $haltOnError = 'yes'; // "yes" (halt with message), "no" (ignore errors quietly), "report" (ignore error, but spit a warning)
28
+
29
+	public $maxConnectErrors = 5;
30
+	public $connectionAttempt = 0;
31
+	public $maxMatches = 10000000;
32
+
33
+	public $Type = 'mysql';
34
+
35
+	/**
36
+	 * @var int
37
+	 */
38
+	public $autoFree = 0; // Set to 1 for automatic mysql_free_result()
39
+
40
+	/* public: result array and current row number */
41
+	public $Record = [];
42
+	public $Row;
43
+
44
+	/* public: current error number and error text */
45
+	public $Errno = 0;
46
+	public $Error = '';
47
+
48
+	/* public: this is an api revision, not a CVS revision. */
49
+	public $type = 'generic';
50
+
51
+	/**
52
+	 * @var int|object
53
+	 */
54
+	public $linkId = 0;
55
+	public $queryId = 0;
56
+
57
+	public $characterSet = 'utf8mb4';
58
+	public $collation = 'utf8mb4_unicode_ci';
59
+
60
+	/**
61
+	 * Logged queries.
62
+	 * @var array
63
+	 */
64
+	protected $log = [];
65
+
66
+	/**
67
+	 * Constructs the db handler, can optionally specify connection parameters
68
+	 *
69
+	 * @param string $database Optional The database name
70
+	 * @param string $user Optional The username to connect with
71
+	 * @param string $password Optional The password to use
72
+	 * @param string $host Optional The hostname where the server is, or default to localhost
73
+	 * @param string $query Optional query to perform immediately
74
+	 * @param string $port optional port for the connection
75
+	 */
76
+	public function __construct($database = '', $user = '', $password = '', $host = 'localhost', $query = '', $port = '')
77
+	{
78
+		$this->database = $database;
79
+		$this->user = $user;
80
+		$this->password = $password;
81
+		$this->host = $host;
82
+		$this->port = $port;
83
+		if ($query != '') {
84
+			$this->query($query);
85
+		}
86
+		$this->connectionAttempt = 0;
87
+	}
88
+
89
+	/**
90
+	 * @param string $message
91
+	 * @param string $line
92
+	 * @param string $file
93
+	 * @return void
94
+	 */
95
+	public function log($message, $line = '', $file = '', $level = 'info')
96
+	{
97
+		error_log($message);
98
+	}
99
+
100
+	/**
101
+	 * @return int|object
102
+	 */
103
+	public function linkId()
104
+	{
105
+		return $this->linkId;
106
+	}
107
+
108
+	/**
109
+	 * @return int|object
110
+	 */
111
+	public function queryId()
112
+	{
113
+		return $this->queryId;
114
+	}
115
+
116
+	/**
117
+	 * @param $string
118
+	 * @return string
119
+	 */
120
+	public function real_escape($string = '')
121
+	{
122
+		if ((!is_resource($this->linkId) || $this->linkId == 0) && !$this->connect()) {
123
+			return $this->escape($string);
124
+		}
125
+		return mysqli_real_escape_string($this->linkId, $string);
126
+	}
127
+
128
+	/**
129
+	 * @param $string
130
+	 * @return string
131
+	 */
132
+	public function escape($string = '')
133
+	{
134
+		//if (function_exists('mysql_escape_string'))
135
+		//return mysql_escape_string($string);
136
+		return str_replace(['\\', "\0", "\n", "\r", "'", '"', "\x1a"], ['\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'], $string);
137
+	}
138
+
139
+	/**
140
+	 * @param mixed $str
141
+	 * @return string
142
+	 */
143
+	public function dbAddslashes($str = '')
144
+	{
145
+		if (!isset($str) || $str == '') {
146
+			return '';
147
+		}
148
+		return addslashes($str);
149
+	}
150
+
151
+	/**
152
+	 * Db::toTimestamp()
153
+	 * @param mixed $epoch
154
+	 * @return bool|string
155
+	 */
156
+	public function toTimestamp($epoch)
157
+	{
158
+		return date('Y-m-d H:i:s', is_float($epoch) ? intval($epoch) : $epoch);
159
+	}
160
+
161
+	/**
162
+	 * Db::fromTimestamp()
163
+	 * @param mixed $timestamp
164
+	 * @return bool|int|mixed
165
+	 */
166
+	public function fromTimestamp($timestamp)
167
+	{
168
+		if (preg_match('/([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/', $timestamp, $parts)) {
169
+			$time = mktime($parts[4], $parts[5], $parts[6], $parts[2], $parts[3], $parts[1]);
170
+		} elseif (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/', $timestamp, $parts)) {
171
+			$time = mktime($parts[4], $parts[5], $parts[6], $parts[2], $parts[3], $parts[1]);
172
+		} elseif (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})/', $timestamp, $parts)) {
173
+			$time = mktime(1, 1, 1, $parts[2], $parts[3], $parts[1]);
174
+		} elseif (is_numeric($timestamp) && $timestamp >= 943938000) {
175
+			$time = $timestamp;
176
+		} else {
177
+			$this->log('Cannot Match Timestamp from '.$timestamp, __LINE__, __FILE__);
178
+			$time = false;
179
+		}
180
+		return $time;
181
+	}
182
+
183
+	/**
184
+	 * perform a query with limited result set
185
+	 *
186
+	 * @param string $queryString
187
+	 * @param string|int $numRows
188
+	 * @param int $offset
189
+	 * @param string|int $line
190
+	 * @param string $file
191
+	 * @return mixed
192
+	 */
193
+	public function limitQuery($queryString, $numRows = '', $offset = 0, $line = '', $file = '')
194
+	{
195
+		if (!$numRows) {
196
+			$numRows = $this->maxMatches;
197
+		}
198
+		if ($offset == 0) {
199
+			$queryString .= ' LIMIT '.(int) $numRows;
200
+		} else {
201
+			$queryString .= ' LIMIT '.(int) $offset.','.(int) $numRows;
202
+		}
203
+
204
+		if ($this->Debug) {
205
+			printf("Debug: limitQuery = %s<br>offset=%d, num_rows=%d<br>\n", $queryString, $offset, $numRows);
206
+		}
207
+
208
+		return $this->query($queryString, $line, $file);
209
+	}
210
+
211
+	/**
212
+	 * db:qr()
213
+	 *
214
+	 *  alias of queryReturn()
215
+	 *
216
+	 * @param mixed $query SQL Query to be used
217
+	 * @param string $line optionally pass __LINE__ calling the query for logging
218
+	 * @param string $file optionally pass __FILE__ calling the query for logging
219
+	 * @return mixed FALSE if no rows, if a single row it returns that, if multiple it returns an array of rows, associative responses only
220
+	 */
221
+	public function qr($query, $line = '', $file = '')
222
+	{
223
+		return $this->queryReturn($query, $line, $file);
224
+	}
225
+
226
+	/**
227
+	 * gets a field
228
+	 *
229
+	 * @param mixed  $name
230
+	 * @param string $stripSlashes
231
+	 * @return string
232
+	 */
233
+	public function f($name, $stripSlashes = '')
234
+	{
235
+		if (is_null($this->Record)) {
236
+			return null;
237
+		} elseif ($stripSlashes || ($this->autoStripslashes && !$stripSlashes)) {
238
+			return stripslashes($this->Record[$name]);
239
+		} else {
240
+			return $this->Record[$name];
241
+		}
242
+	}
243
+
244
+	/**
245
+	 * error handling
246
+	 *
247
+	 * @param mixed $msg
248
+	 * @param string $line
249
+	 * @param string $file
250
+	 * @return void
251
+	 */
252
+	public function halt($msg, $line = '', $file = '')
253
+	{
254
+		$this->unlock(false);
255
+		/* Just in case there is a table currently locked */
256
+
257
+		//$this->Error = @$this->linkId->error;
258
+		//$this->Errno = @$this->linkId->errno;
259
+		if ($this->haltOnError == 'no') {
260
+			return true;
261
+		}
262
+		if ($msg != '') {
263
+			$this->haltmsg($msg, $line, $file);
264
+		}
265
+		if ($this->haltOnError != 'report') {
266
+			echo '<p><b>Session halted.</b>';
267
+			//if (isset($GLOBALS['tf']))
268
+			//$GLOBALS['tf']->terminate();
269
+			die();
270
+		}
271
+		return true;
272
+	}
273
+
274
+	/**
275
+	 * @param mixed $msg
276
+	 * @param string $line
277
+	 * @param string $file
278
+	 * @return mixed|void
279
+	 */
280
+	public function logBackTrace($msg, $line = '', $file = '')
281
+	{
282
+		$backtrace = (function_exists('debug_backtrace') ? debug_backtrace() : []);
283
+		$this->log(
284
+			('' !== getenv('REQUEST_URI') ? ' '.getenv('REQUEST_URI') : '').
285
+			((isset($_POST) && count($_POST)) ? ' POST='.json_encode($_POST) : '').
286
+			((isset($_GET) && count($_GET)) ? ' GET='.json_encode($_GET) : '').
287
+			((isset($_FILES) && count($_FILES)) ? ' FILES='.json_encode($_FILES) : '').
288
+			('' !== getenv('HTTP_USER_AGENT') ? ' AGENT="'.getenv('HTTP_USER_AGENT').'"' : '').
289
+			(isset($_SERVER['REQUEST_METHOD']) ? ' METHOD="'.$_SERVER['REQUEST_METHOD'].'"'.
290
+				($_SERVER['REQUEST_METHOD'] === 'POST' ? ' POST="'.json_encode($_POST).'"' : '') : ''),
291
+			$line,
292
+			$file,
293
+			'error'
294
+		);
295
+		for ($level = 1, $levelMax = count($backtrace); $level < $levelMax; $level++) {
296
+			$message = (isset($backtrace[$level]['file']) ? 'File: '.$backtrace[$level]['file'] : '').
297
+				(isset($backtrace[$level]['line']) ? ' Line: '.$backtrace[$level]['line'] : '').
298
+				' Function: '.(isset($backtrace[$level] ['class']) ? '(class '.$backtrace[$level] ['class'].') ' : '').
299
+				(isset($backtrace[$level] ['type']) ? $backtrace[$level] ['type'].' ' : '').
300
+				$backtrace[$level] ['function'].'(';
301
+			if (isset($backtrace[$level] ['args'])) {
302
+				for ($argument = 0, $argumentMax = count($backtrace[$level]['args']); $argument < $argumentMax; $argument++) {
303
+					$message .= ($argument > 0 ? ', ' : '').
304
+						(is_object($backtrace[$level]['args'][$argument]) ? 'class '.get_class($backtrace[$level]['args'][$argument]) : json_encode($backtrace[$level]['args'][$argument]));
305
+				}
306
+			}
307
+			$message .= ')';
308
+			$this->log($message, $line, $file, 'error');
309
+		}
310
+	}
311
+
312
+	public function emailError($queryString, $error, $line, $file)
313
+	{
314
+		$subject = php_uname('n').' MySQLi Error '.$queryString;
315
+		if (class_exists('\\TFSmarty')) {
316
+			$smarty = new \TFSmarty();
317
+			$smarty->assign([
318
+				'type' => $this->type,
319
+				'queryString' => $queryString,
320
+				'error' => $error,
321
+				'line' => $line,
322
+				'file' => $file,
323
+				'request' => $_REQUEST,
324
+				'server' => $_SERVER,
325
+			]);
326
+			if (isset($GLOBALS['tf'])) {
327
+				$smarty->assign('account_id', $GLOBALS['tf']->session->account_id);
328
+			}
329
+			$email = $smarty->fetch('email/admin/sql_error.tpl');
330
+			(new \MyAdmin\Mail())->adminMail($subject, $email, '[email protected]', '');
331
+			(new \MyAdmin\Mail())->adminMail($subject, $email, '[email protected]', '');
332
+		}
333
+		$this->haltmsg('Invalid SQL: '.$queryString, $line, $file);
334
+	}
335
+
336
+	/**
337
+	 * @param mixed $msg
338
+	 * @param string $line
339
+	 * @param string $file
340
+	 * @return mixed|void
341
+	 */
342
+	public function haltmsg($msg, $line = '', $file = '')
343
+	{
344
+		$email = "DB Error {$msg} {$file}:{$line}";
345
+		if (class_exists('\\MyAdmin\Mail')) {
346
+			\MyAdmin\Mail::failsafeMail($email, $email, ['[email protected]', '[email protected]']);
347
+			return;
348
+		}
349
+		$this->log("Database error: $msg", $line, $file, 'error');
350
+		if ($this->Errno != '0' || !in_array($this->Error, ['', '()'])) {
351
+			$sqlstate = mysqli_sqlstate($this->linkId);
352
+			$this->log("MySQLi SQLState: {$sqlstate}. Error: ".$this->Errno.' ('.$this->Error.')', $line, $file, 'error');
353
+		}
354
+		$this->logBackTrace($msg, $line, $file);
355
+	}
356
+
357
+	/**
358
+	 * @return array
359
+	 */
360
+	public function indexNames()
361
+	{
362
+		return [];
363
+	}
364
+
365
+
366
+	/**
367
+	 * Add query to logged queries.
368
+	 * @param string $statement
369
+	 * @param float $time Elapsed seconds with microseconds
370
+	 * @param string|int $line Line Number
371
+	 * @param string $file File Name
372
+	 */
373
+	public function addLog($statement, $time, $line = '', $file = '')
374
+	{
375
+		$query = [
376
+			'statement' => $statement,
377
+			'time' => $time * 1000
378
+		];
379
+		if ($line != '') {
380
+			$query['line'] = $line;
381
+		}
382
+		if ($file != '') {
383
+			$query['file'] = $file;
384
+		}
385
+		if (!isset($GLOBALS['db_queries'])) {
386
+			$GLOBALS['db_queries'] = [];
387
+		}
388
+		$GLOBALS['db_queries'][] = $query;
389
+		array_push($this->log, $query);
390
+	}
391
+
392
+	/**
393
+	 * Return logged queries.
394
+	 * @return array Logged queries
395
+	 */
396
+	public function getLog()
397
+	{
398
+		return $this->log;
399
+	}
400 400
 }
Please login to merge, or discard this patch.