|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* This file provides an implementation of the most common functions needed |
|
5
|
|
|
* for the database drivers to work. |
|
6
|
|
|
* |
|
7
|
|
|
* @package ElkArte Forum |
|
8
|
|
|
* @copyright ElkArte Forum contributors |
|
9
|
|
|
* @license BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file) |
|
10
|
|
|
* |
|
11
|
|
|
* This file contains code covered by: |
|
12
|
|
|
* copyright: 2011 Simple Machines (http://www.simplemachines.org) |
|
13
|
|
|
* |
|
14
|
|
|
* @version 2.0 dev |
|
15
|
|
|
* |
|
16
|
|
|
*/ |
|
17
|
|
|
|
|
18
|
|
|
namespace ElkArte\Database; |
|
19
|
|
|
|
|
20
|
|
|
/** |
|
21
|
|
|
* Abstract database class, implements database to control functions |
|
22
|
|
|
*/ |
|
23
|
|
|
abstract class AbstractQuery implements QueryInterface |
|
24
|
|
|
{ |
|
25
|
|
|
/** |
|
26
|
|
|
* Current connection to the database |
|
27
|
|
|
* @var \ElkArte\Database\ConnectionInterface |
|
28
|
|
|
*/ |
|
29
|
|
|
protected $connection = null; |
|
30
|
|
|
|
|
31
|
|
|
/** |
|
32
|
|
|
* Number of queries run (may include queries from $_SESSION if is a redirect) |
|
33
|
|
|
* @var int |
|
34
|
|
|
*/ |
|
35
|
|
|
protected $_query_count = 0; |
|
36
|
|
|
|
|
37
|
|
|
/** |
|
38
|
|
|
* The way to skip a database error |
|
39
|
|
|
* @var boolean |
|
40
|
|
|
*/ |
|
41
|
|
|
protected $_skip_error = false; |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* The tables prefix |
|
45
|
|
|
* @var string |
|
46
|
|
|
*/ |
|
47
|
|
|
protected $_db_prefix = ''; |
|
48
|
|
|
|
|
49
|
|
|
/** |
|
50
|
|
|
* String to match visible boards. |
|
51
|
|
|
* By default set to a false, so that unless it is set, nothing is returned. |
|
52
|
|
|
* @var string |
|
53
|
|
|
*/ |
|
54
|
|
|
protected $query_see_board = '1!=1'; |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* String to match boards the user want to see. |
|
58
|
|
|
* By default set to a false, so that unless it is set, nothing is returned. |
|
59
|
|
|
* @var string |
|
60
|
|
|
*/ |
|
61
|
|
|
protected $query_wanna_see_board = '1!=1'; |
|
62
|
|
|
|
|
63
|
|
|
/** |
|
64
|
|
|
* MySQL supports unbuffered queries, this remembers if we are running an |
|
65
|
|
|
* unbuffered or not |
|
66
|
|
|
* @var boolean |
|
67
|
|
|
*/ |
|
68
|
|
|
protected $_unbuffered = false; |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* This holds the "values" used in the replacement__callback method |
|
72
|
|
|
* @var array |
|
73
|
|
|
*/ |
|
74
|
|
|
protected $_db_callback_values = array(); |
|
75
|
|
|
|
|
76
|
|
|
/** |
|
77
|
|
|
* Temporary variable to support the migration to the new db-layer |
|
78
|
|
|
* Ideally to be removed before 2.0 shipment |
|
79
|
|
|
* @var \ElkArte\Database\AbstractResult |
|
80
|
|
|
*/ |
|
81
|
|
|
protected $result = null; |
|
82
|
|
|
|
|
83
|
|
|
/** |
|
84
|
|
|
* Comments that are allowed in a query are preg_removed. |
|
85
|
|
|
* These replacements happen in the query checks. |
|
86
|
|
|
* @var string[] |
|
87
|
|
|
*/ |
|
88
|
|
|
protected $allowed_comments = [ |
|
89
|
|
|
'from' => [ |
|
90
|
|
|
'~\s+~s', |
|
91
|
|
|
'~/\*!40001 SQL_NO_CACHE \*/~', |
|
92
|
|
|
'~/\*!40000 USE INDEX \([A-Za-z\_]+?\) \*/~', |
|
93
|
|
|
'~/\*!40100 ON DUPLICATE KEY UPDATE id_msg = \d+ \*/~', |
|
94
|
|
|
], |
|
95
|
|
|
'to' => [ |
|
96
|
|
|
' ', |
|
97
|
|
|
'', |
|
98
|
|
|
'', |
|
99
|
|
|
'', |
|
100
|
|
|
] |
|
101
|
|
|
]; |
|
102
|
|
|
|
|
103
|
|
|
/** |
|
104
|
|
|
* Holds some values (time, file, line, delta) to debug performancs of the queries. |
|
105
|
|
|
* @var mixed[] |
|
106
|
|
|
*/ |
|
107
|
|
|
protected $db_cache = []; |
|
108
|
|
|
|
|
109
|
|
|
/** |
|
110
|
|
|
* The debug object. |
|
111
|
|
|
* @var \ElkArte\Debug |
|
112
|
|
|
*/ |
|
113
|
|
|
protected $_debug = null; |
|
114
|
|
|
|
|
115
|
|
|
/** |
|
116
|
|
|
* Constructor. |
|
117
|
|
|
* |
|
118
|
|
|
* @param string $db_prefix Guess what? The tables prefix |
|
119
|
|
|
* @param resource|object $connection Obviously the database connection |
|
120
|
|
|
*/ |
|
121
|
1 |
|
public function __construct($db_prefix, $connection) |
|
122
|
|
|
{ |
|
123
|
1 |
|
global $db_show_debug; |
|
124
|
|
|
|
|
125
|
1 |
|
$this->_db_prefix = $db_prefix; |
|
126
|
1 |
|
$this->connection = $connection; |
|
|
|
|
|
|
127
|
|
|
|
|
128
|
|
|
// Debugging. |
|
129
|
1 |
|
if ($db_show_debug === true) |
|
130
|
|
|
{ |
|
131
|
|
|
$this->_debug = \ElkArte\Debug::instance(); |
|
132
|
|
|
} |
|
133
|
1 |
|
} |
|
134
|
|
|
|
|
135
|
|
|
/** |
|
136
|
|
|
* {@inheritDoc} |
|
137
|
|
|
*/ |
|
138
|
|
|
abstract public function query($identifier, $db_string, $db_values = array()); |
|
139
|
|
|
|
|
140
|
|
|
/** |
|
141
|
|
|
* {@inheritDoc} |
|
142
|
|
|
*/ |
|
143
|
|
|
abstract public function transaction($type = 'commit'); |
|
144
|
|
|
|
|
145
|
|
|
/** |
|
146
|
|
|
* {@inheritDoc} |
|
147
|
|
|
*/ |
|
148
|
|
|
abstract public function last_error(); |
|
149
|
|
|
|
|
150
|
|
|
/** |
|
151
|
|
|
* Public setter for the string that defines which boards the user can see. |
|
152
|
|
|
* @param string $string |
|
153
|
|
|
*/ |
|
154
|
3 |
|
public function setSeeBoard($string) |
|
155
|
|
|
{ |
|
156
|
3 |
|
$this->query_see_board = $string; |
|
157
|
3 |
|
} |
|
158
|
|
|
|
|
159
|
|
|
/** |
|
160
|
|
|
* Public setter for the string that defines which boards the user want to see. |
|
161
|
|
|
* @param string $string |
|
162
|
|
|
*/ |
|
163
|
3 |
|
public function setWannaSeeBoard($string) |
|
164
|
|
|
{ |
|
165
|
3 |
|
$this->query_wanna_see_board = $string; |
|
166
|
3 |
|
} |
|
167
|
|
|
|
|
168
|
|
|
/** |
|
169
|
|
|
* Callback for preg_replace_callback on the query. |
|
170
|
|
|
* It allows to replace on the fly a few pre-defined strings, for |
|
171
|
|
|
* convenience ('query_see_board', 'query_wanna_see_board'), with |
|
172
|
|
|
* their current values from User::$info. |
|
173
|
|
|
* In addition, it performs checks and sanitation on the values |
|
174
|
|
|
* sent to the database. |
|
175
|
|
|
* |
|
176
|
|
|
* @param mixed[] $matches |
|
177
|
|
|
* |
|
178
|
|
|
* @return mixed|string |
|
179
|
|
|
* @throws \ElkArte\Exceptions\Exception |
|
180
|
|
|
*/ |
|
181
|
87 |
|
public function replacement__callback($matches) |
|
182
|
|
|
{ |
|
183
|
|
|
// Connection gone??? This should *never* happen at this point, yet it does :'( |
|
184
|
87 |
|
if (!$this->validConnection()) |
|
185
|
|
|
{ |
|
186
|
|
|
\ElkArte\Errors\Errors::instance()->display_db_error('ElkArte\\Database\\AbstractQuery::replacement__callback'); |
|
187
|
|
|
} |
|
188
|
|
|
|
|
189
|
87 |
|
switch ($matches[1]) |
|
190
|
|
|
{ |
|
191
|
87 |
|
case 'db_prefix': |
|
192
|
81 |
|
return $this->_db_prefix; |
|
193
|
85 |
|
case 'query_see_board': |
|
194
|
9 |
|
return $this->query_see_board; |
|
195
|
85 |
|
case 'query_wanna_see_board': |
|
196
|
4 |
|
return $this->query_wanna_see_board; |
|
197
|
85 |
|
case 'column_case_insensitive': |
|
198
|
6 |
|
return $this->_replaceColumnCaseInsensitive($matches[2]); |
|
199
|
|
|
} |
|
200
|
|
|
|
|
201
|
85 |
|
if (!isset($matches[2])) |
|
202
|
|
|
{ |
|
203
|
|
|
$this->error_backtrace('Invalid value inserted or no type specified.', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
204
|
|
|
} |
|
205
|
|
|
|
|
206
|
85 |
|
if (!isset($this->_db_callback_values[$matches[2]])) |
|
207
|
|
|
{ |
|
208
|
|
|
$this->error_backtrace('The database value you\'re trying to insert does not exist: ' . htmlspecialchars($matches[2], ENT_COMPAT, 'UTF-8'), '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
209
|
|
|
} |
|
210
|
|
|
|
|
211
|
85 |
|
$replacement = $this->_db_callback_values[$matches[2]]; |
|
212
|
|
|
|
|
213
|
85 |
|
switch ($matches[1]) |
|
214
|
|
|
{ |
|
215
|
85 |
|
case 'int': |
|
216
|
59 |
|
return $this->_replaceInt($matches[2], $replacement); |
|
217
|
85 |
|
case 'string': |
|
218
|
64 |
|
case 'text': |
|
219
|
71 |
|
return $this->_replaceString($replacement); |
|
220
|
64 |
|
case 'string_case_sensitive': |
|
221
|
2 |
|
return $this->_replaceStringCaseSensitive($replacement); |
|
222
|
64 |
|
case 'string_case_insensitive': |
|
223
|
6 |
|
return $this->_replaceStringCaseInsensitive($replacement); |
|
224
|
62 |
|
case 'array_int': |
|
225
|
31 |
|
return $this->_replaceArrayInt($matches[2], $replacement); |
|
226
|
60 |
|
case 'array_string': |
|
227
|
38 |
|
return $this->_replaceArrayString($matches[2], $replacement); |
|
228
|
43 |
|
case 'array_string_case_insensitive': |
|
229
|
2 |
|
return $this->_replaceArrayStringCaseInsensitive($matches[2], $replacement); |
|
230
|
41 |
|
case 'date': |
|
231
|
1 |
|
return $this->_replaceDate($matches[2], $replacement); |
|
232
|
40 |
|
case 'float': |
|
233
|
15 |
|
return $this->_replaceFloat($matches[2], $replacement); |
|
234
|
28 |
|
case 'identifier': |
|
235
|
|
|
return $this->_replaceIdentifier($replacement); |
|
236
|
28 |
|
case 'raw': |
|
237
|
28 |
|
return $replacement; |
|
238
|
|
|
default: |
|
239
|
|
|
$this->error_backtrace('Undefined type used in the database query. (' . $matches[1] . ':' . $matches[2] . ')', '', false, __FILE__, __LINE__); |
|
240
|
|
|
break; |
|
241
|
|
|
} |
|
242
|
|
|
|
|
243
|
|
|
return ''; |
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
|
|
/** |
|
247
|
|
|
* {@inheritDoc} |
|
248
|
|
|
*/ |
|
249
|
61 |
|
public function quote($db_string, $db_values) |
|
250
|
|
|
{ |
|
251
|
|
|
// Only bother if there's something to replace. |
|
252
|
61 |
|
if (strpos($db_string, '{') !== false) |
|
253
|
|
|
{ |
|
254
|
|
|
// This is needed by the callback function. |
|
255
|
61 |
|
$this->_db_callback_values = $db_values; |
|
256
|
|
|
|
|
257
|
|
|
// Do the quoting and escaping |
|
258
|
61 |
|
$db_string = preg_replace_callback('~{([a-z_]+)(?::([\.a-zA-Z0-9_-]+))?}~', array($this, 'replacement__callback'), $db_string); |
|
|
|
|
|
|
259
|
|
|
|
|
260
|
|
|
// Clear this variables. |
|
261
|
61 |
|
$this->_db_callback_values = array(); |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
61 |
|
return $db_string; |
|
265
|
|
|
} |
|
266
|
|
|
|
|
267
|
|
|
/** |
|
268
|
|
|
* {@inheritDoc} |
|
269
|
|
|
*/ |
|
270
|
18 |
|
public function fetchQuery($db_string, $db_values = array()) |
|
271
|
|
|
{ |
|
272
|
18 |
|
return $this->query('', $db_string, $db_values); |
|
|
|
|
|
|
273
|
|
|
} |
|
274
|
|
|
|
|
275
|
|
|
/** |
|
276
|
|
|
* This function combines the keys and values of the data passed to db::insert. |
|
277
|
|
|
* |
|
278
|
|
|
* @param integer[] $keys |
|
279
|
|
|
* @param mixed[] $values |
|
280
|
|
|
* @return mixed[] |
|
281
|
|
|
*/ |
|
282
|
59 |
|
protected function _array_combine($keys, $values) |
|
283
|
|
|
{ |
|
284
|
59 |
|
$is_numeric = array_filter(array_keys($values), 'is_numeric'); |
|
285
|
|
|
|
|
286
|
59 |
|
if (!empty($is_numeric)) |
|
287
|
59 |
|
return array_combine($keys, $values); |
|
288
|
|
|
else |
|
289
|
|
|
{ |
|
290
|
26 |
|
$combined = array(); |
|
291
|
26 |
|
foreach ($keys as $key) |
|
292
|
|
|
{ |
|
293
|
26 |
|
if (isset($values[$key])) |
|
294
|
26 |
|
$combined[$key] = $values[$key]; |
|
295
|
|
|
} |
|
296
|
|
|
|
|
297
|
|
|
// @todo should throw an E_WARNING if count($combined) != count($keys) |
|
298
|
26 |
|
return $combined; |
|
299
|
|
|
} |
|
300
|
|
|
} |
|
301
|
|
|
|
|
302
|
|
|
/** |
|
303
|
|
|
* Tests and casts integers for replacement__callback. |
|
304
|
|
|
* |
|
305
|
|
|
* @param mixed $identifier |
|
306
|
|
|
* @param mixed $replacement |
|
307
|
|
|
* @return string |
|
308
|
|
|
* @throws \ElkArte\Exceptions\Exception |
|
309
|
|
|
*/ |
|
310
|
59 |
|
protected function _replaceInt($identifier, $replacement) |
|
311
|
|
|
{ |
|
312
|
59 |
View Code Duplication |
if (!is_numeric($replacement) || (string) $replacement !== (string) (int) $replacement) |
|
313
|
|
|
$this->error_backtrace('Wrong value type sent to the database. Integer expected. (' . $identifier . ')', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
314
|
59 |
|
return (string) (int) $replacement; |
|
315
|
|
|
} |
|
316
|
|
|
|
|
317
|
|
|
/** |
|
318
|
|
|
* Tests and casts arrays of integers for replacement__callback. |
|
319
|
|
|
* |
|
320
|
|
|
* @param string $identifier |
|
321
|
|
|
* @param mixed[] $replacement |
|
322
|
|
|
* @return string |
|
|
|
|
|
|
323
|
|
|
* @throws \ElkArte\Exceptions\Exception |
|
324
|
|
|
*/ |
|
325
|
31 |
|
protected function _replaceArrayInt($identifier, $replacement) |
|
326
|
|
|
{ |
|
327
|
31 |
|
if (is_array($replacement)) |
|
328
|
|
|
{ |
|
329
|
31 |
|
if (empty($replacement)) |
|
330
|
|
|
$this->error_backtrace('Database error, given array of integer values is empty. (' . $identifier . ')', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
331
|
|
|
|
|
332
|
31 |
|
foreach ($replacement as $key => $value) |
|
333
|
|
|
{ |
|
334
|
31 |
View Code Duplication |
if (!is_numeric($value) || (string) $value !== (string) (int) $value) |
|
335
|
|
|
$this->error_backtrace('Wrong value type sent to the database. Array of integers expected. (' . $identifier . ')', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
336
|
|
|
|
|
337
|
31 |
|
$replacement[$key] = (string) (int) $value; |
|
338
|
|
|
} |
|
339
|
|
|
|
|
340
|
31 |
|
return implode(', ', $replacement); |
|
341
|
|
|
} |
|
342
|
|
|
else |
|
343
|
|
|
{ |
|
344
|
|
|
$this->error_backtrace('Wrong value type sent to the database. Array of integers expected. (' . $identifier . ')', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
345
|
|
|
} |
|
346
|
|
|
} |
|
347
|
|
|
|
|
348
|
|
|
/** |
|
349
|
|
|
* Casts values to string for replacement__callback. |
|
350
|
|
|
* |
|
351
|
|
|
* @param mixed $replacement |
|
352
|
|
|
* @return string |
|
353
|
|
|
*/ |
|
354
|
75 |
|
protected function _replaceString($replacement) |
|
355
|
|
|
{ |
|
356
|
75 |
|
return sprintf('\'%1$s\'', $this->escape_string($replacement)); |
|
357
|
|
|
} |
|
358
|
|
|
|
|
359
|
|
|
/** |
|
360
|
|
|
* Casts values to string for replacement__callback and in the DBMS that |
|
361
|
|
|
* require this solution makes it so that the comparison will be case sensitive. |
|
362
|
|
|
* |
|
363
|
|
|
* @param mixed $replacement |
|
364
|
|
|
* @return string |
|
365
|
|
|
*/ |
|
366
|
1 |
|
protected function _replaceStringCaseSensitive($replacement) |
|
367
|
|
|
{ |
|
368
|
1 |
|
return $this->_replaceString($replacement); |
|
369
|
|
|
} |
|
370
|
|
|
|
|
371
|
|
|
/** |
|
372
|
|
|
* Casts values to LOWER(string) for replacement__callback. |
|
373
|
|
|
* |
|
374
|
|
|
* @param mixed $replacement |
|
375
|
|
|
* @return string |
|
376
|
|
|
*/ |
|
377
|
3 |
|
protected function _replaceStringCaseInsensitive($replacement) |
|
378
|
|
|
{ |
|
379
|
3 |
|
return 'LOWER(' . $this->_replaceString($replacement) . ')'; |
|
380
|
|
|
} |
|
381
|
|
|
|
|
382
|
|
|
/** |
|
383
|
|
|
* Casts the column to LOWER(column_name) for replacement__callback. |
|
384
|
|
|
* |
|
385
|
|
|
* @param mixed $replacement |
|
386
|
|
|
* @return string |
|
387
|
|
|
*/ |
|
388
|
3 |
|
protected function _replaceColumnCaseInsensitive($replacement) |
|
389
|
|
|
{ |
|
390
|
3 |
|
return 'LOWER(' . $replacement . ')'; |
|
391
|
|
|
} |
|
392
|
|
|
|
|
393
|
|
|
/** |
|
394
|
|
|
* Tests and casts arrays of strings for replacement__callback. |
|
395
|
|
|
* |
|
396
|
|
|
* @param string $identifier |
|
397
|
|
|
* @param mixed[] $replacement |
|
398
|
|
|
* @return string |
|
|
|
|
|
|
399
|
|
|
* @throws \ElkArte\Exceptions\Exception |
|
400
|
|
|
*/ |
|
401
|
38 |
View Code Duplication |
protected function _replaceArrayString($identifier, $replacement) |
|
|
|
|
|
|
402
|
|
|
{ |
|
403
|
38 |
|
if (is_array($replacement)) |
|
404
|
|
|
{ |
|
405
|
38 |
|
if (empty($replacement)) |
|
406
|
|
|
{ |
|
407
|
|
|
$this->error_backtrace('Database error, given array of string values is empty. (' . $identifier . ')', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
408
|
|
|
} |
|
409
|
|
|
|
|
410
|
38 |
|
foreach ($replacement as $key => $value) |
|
411
|
|
|
{ |
|
412
|
38 |
|
$replacement[$key] = sprintf('\'%1$s\'', $this->escape_string($value)); |
|
413
|
|
|
} |
|
414
|
|
|
|
|
415
|
38 |
|
return implode(', ', $replacement); |
|
416
|
|
|
} |
|
417
|
|
|
else |
|
418
|
|
|
{ |
|
419
|
|
|
$this->error_backtrace('Wrong value type sent to the database. Array of strings expected. (' . $identifier . ')', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
420
|
|
|
} |
|
421
|
|
|
} |
|
422
|
|
|
|
|
423
|
|
|
/** |
|
424
|
|
|
* Tests and casts to LOWER(column_name) (if needed) arrays of strings |
|
425
|
|
|
* for replacement__callback. |
|
426
|
|
|
* |
|
427
|
|
|
* @param string $identifier |
|
428
|
|
|
* @param mixed[] $replacement |
|
429
|
|
|
* @return string |
|
|
|
|
|
|
430
|
|
|
* @throws \ElkArte\Exceptions\Exception |
|
431
|
|
|
*/ |
|
432
|
2 |
View Code Duplication |
protected function _replaceArrayStringCaseInsensitive($identifier, $replacement) |
|
|
|
|
|
|
433
|
|
|
{ |
|
434
|
2 |
|
if (is_array($replacement)) |
|
435
|
|
|
{ |
|
436
|
2 |
|
if (empty($replacement)) |
|
437
|
|
|
{ |
|
438
|
|
|
$this->error_backtrace('Database error, given array of string values is empty. (' . $identifier . ')', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
439
|
|
|
} |
|
440
|
|
|
|
|
441
|
2 |
|
foreach ($replacement as $key => $value) |
|
442
|
|
|
{ |
|
443
|
2 |
|
$replacement[$key] = $this->_replaceStringCaseInsensitive($value); |
|
444
|
|
|
} |
|
445
|
|
|
|
|
446
|
2 |
|
return implode(', ', $replacement); |
|
447
|
|
|
} |
|
448
|
|
|
else |
|
449
|
|
|
{ |
|
450
|
|
|
$this->error_backtrace('Wrong value type sent to the database. Array of strings expected. (' . $identifier . ')', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
451
|
|
|
} |
|
452
|
|
|
} |
|
453
|
|
|
|
|
454
|
|
|
/** |
|
455
|
|
|
* Tests and casts date for replacement__callback. |
|
456
|
|
|
* |
|
457
|
|
|
* @param mixed $identifier |
|
458
|
|
|
* @param mixed $replacement |
|
459
|
|
|
* @return string |
|
|
|
|
|
|
460
|
|
|
* @throws \ElkArte\Exceptions\Exception |
|
461
|
|
|
*/ |
|
462
|
1 |
|
protected function _replaceDate($identifier, $replacement) |
|
463
|
|
|
{ |
|
464
|
1 |
|
if (preg_match('~^(\d{4})-([0-1]?\d)-([0-3]?\d)$~', $replacement, $date_matches) === 1) |
|
465
|
1 |
|
return sprintf('\'%04d-%02d-%02d\'', $date_matches[1], $date_matches[2], $date_matches[3]); |
|
466
|
|
|
else |
|
467
|
|
|
$this->error_backtrace('Wrong value type sent to the database. Date expected. (' . $identifier . ')', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
468
|
|
|
} |
|
469
|
|
|
|
|
470
|
|
|
/** |
|
471
|
|
|
* Tests and casts floating numbers for replacement__callback. |
|
472
|
|
|
* |
|
473
|
|
|
* @param mixed $identifier |
|
474
|
|
|
* @param mixed $replacement |
|
475
|
|
|
* @return string |
|
476
|
|
|
* @throws \ElkArte\Exceptions\Exception |
|
477
|
|
|
*/ |
|
478
|
15 |
|
protected function _replaceFloat($identifier, $replacement) |
|
479
|
|
|
{ |
|
480
|
15 |
|
if (!is_numeric($replacement)) |
|
481
|
|
|
$this->error_backtrace('Wrong value type sent to the database. Floating point number expected. (' . $identifier . ')', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
482
|
15 |
|
return (string) (float) $replacement; |
|
483
|
|
|
} |
|
484
|
|
|
|
|
485
|
|
|
/** |
|
486
|
|
|
* Quotes identifiers for replacement__callback. |
|
487
|
|
|
* |
|
488
|
|
|
* @param mixed $replacement |
|
489
|
|
|
* @return string |
|
490
|
|
|
* @throws \ElkArte\Exceptions\Exception |
|
491
|
|
|
*/ |
|
492
|
|
View Code Duplication |
protected function _replaceIdentifier($replacement) |
|
|
|
|
|
|
493
|
|
|
{ |
|
494
|
|
|
if (preg_match('~[a-z_][0-9,a-z,A-Z$_]{0,60}~', $replacement) !== 1) |
|
495
|
|
|
{ |
|
496
|
|
|
$this->error_backtrace('Wrong value type sent to the database. Invalid identifier used. (' . $replacement . ')', '', E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
497
|
|
|
} |
|
498
|
|
|
|
|
499
|
|
|
return '`' . $replacement . '`'; |
|
500
|
|
|
} |
|
501
|
|
|
|
|
502
|
|
|
/** |
|
503
|
|
|
* Checks for "illegal characters" and runs replacement__callback if not |
|
504
|
|
|
* overriden. |
|
505
|
|
|
* In case of problems, the method can ends up dying. |
|
506
|
|
|
* |
|
507
|
|
|
* @param string $db_string |
|
508
|
|
|
* @param mixed $db_values |
|
509
|
|
|
* @return null|string|string[] |
|
510
|
|
|
*/ |
|
511
|
85 |
|
protected function _prepareQuery($db_string, $db_values) |
|
512
|
|
|
{ |
|
513
|
85 |
|
global $modSettings; |
|
514
|
|
|
|
|
515
|
85 |
|
if (empty($modSettings['disableQueryCheck']) && strpos($db_string, '\'') !== false && empty($db_values['security_override'])) |
|
516
|
|
|
{ |
|
517
|
27 |
|
$this->error_backtrace('Hacking attempt...', 'Illegal character (\') used in query...', true, __FILE__, __LINE__); |
|
518
|
|
|
} |
|
519
|
|
|
|
|
520
|
85 |
|
if (empty($db_values['security_override']) && (!empty($db_values) || strpos($db_string, '{db_prefix}') !== false)) |
|
521
|
|
|
{ |
|
522
|
|
|
// Store these values for use in the callback function. |
|
523
|
83 |
|
$this->_db_callback_values = $db_values; |
|
|
|
|
|
|
524
|
|
|
|
|
525
|
|
|
// Inject the values passed to this function. |
|
526
|
83 |
|
$count = -1; |
|
527
|
83 |
|
while (($count > 0 && isset($db_values['recursive'])) || $count === -1) |
|
528
|
|
|
{ |
|
529
|
83 |
|
$db_string = preg_replace_callback('~{([a-z_]+)(?::([\.a-zA-Z0-9_-]+))?}~', array($this, 'replacement__callback'), $db_string, -1, $count); |
|
|
|
|
|
|
530
|
|
|
} |
|
531
|
|
|
|
|
532
|
|
|
// No need for them any longer. |
|
533
|
83 |
|
$this->_db_callback_values = array(); |
|
534
|
|
|
} |
|
535
|
|
|
|
|
536
|
85 |
|
return $db_string; |
|
537
|
|
|
} |
|
538
|
|
|
|
|
539
|
|
|
/** |
|
540
|
|
|
* Tracks the initial status (time, file/line, query) for performance evaluation. |
|
541
|
|
|
* |
|
542
|
|
|
* @param string $db_string |
|
543
|
|
|
*/ |
|
544
|
85 |
|
protected function _preQueryDebug($db_string) |
|
545
|
|
|
{ |
|
546
|
85 |
|
global $db_show_debug, $time_start; |
|
547
|
|
|
|
|
548
|
|
|
// Debugging. |
|
549
|
85 |
|
if ($db_show_debug === true) |
|
550
|
|
|
{ |
|
551
|
|
|
// Get the file and line number this function was called. |
|
552
|
|
|
list ($file, $line) = $this->error_backtrace('', '', 'return', __FILE__, __LINE__); |
|
|
|
|
|
|
553
|
|
|
|
|
554
|
|
|
if (!empty($_SESSION['debug_redirect'])) |
|
555
|
|
|
{ |
|
556
|
|
|
$this->_debug->merge_db($_SESSION['debug_redirect']); |
|
557
|
|
|
// @todo this may be off by 1 |
|
558
|
|
|
$this->_query_count += count($_SESSION['debug_redirect']); |
|
559
|
|
|
$_SESSION['debug_redirect'] = array(); |
|
560
|
|
|
} |
|
561
|
|
|
|
|
562
|
|
|
// Don't overload it. |
|
563
|
|
|
$st = microtime(true); |
|
564
|
|
|
$this->db_cache = []; |
|
565
|
|
|
$this->db_cache['q'] = $this->_query_count < 50 ? $db_string : '...'; |
|
566
|
|
|
$this->db_cache['f'] = $file; |
|
567
|
|
|
$this->db_cache['l'] = $line; |
|
568
|
|
|
$this->db_cache['s'] = $st - $time_start; |
|
569
|
|
|
$this->db_cache['st'] = $st; |
|
570
|
|
|
} |
|
571
|
85 |
|
} |
|
572
|
|
|
|
|
573
|
|
|
/** |
|
574
|
|
|
* Closes up the tracking and stores everything in the debug class. |
|
575
|
|
|
*/ |
|
576
|
85 |
|
protected function _postQueryDebug() |
|
577
|
|
|
{ |
|
578
|
85 |
|
global $db_show_debug; |
|
579
|
|
|
|
|
580
|
85 |
|
if ($db_show_debug === true) |
|
581
|
|
|
{ |
|
582
|
|
|
$this->db_cache['t'] = microtime(true) - $this->db_cache['st']; |
|
583
|
|
|
$this->_debug->db_query($this->db_cache); |
|
584
|
|
|
$this->db_cache = []; |
|
585
|
|
|
} |
|
586
|
85 |
|
} |
|
587
|
|
|
|
|
588
|
|
|
/** |
|
589
|
|
|
* Checks the query doesn't have nasty stuff in it. |
|
590
|
|
|
* In case of problems, the method can ends up dying. |
|
591
|
|
|
* |
|
592
|
|
|
* @param string $db_string |
|
593
|
|
|
* @param string $escape_char |
|
594
|
|
|
*/ |
|
595
|
85 |
|
protected function _doSanityCheck($db_string, $escape_char) |
|
596
|
|
|
{ |
|
597
|
85 |
|
global $modSettings; |
|
598
|
|
|
|
|
599
|
|
|
// First, we clean strings out of the query, reduce whitespace, lowercase, and trim - so we can check it over. |
|
600
|
85 |
|
$clean = ''; |
|
601
|
85 |
|
if (empty($modSettings['disableQueryCheck'])) |
|
602
|
|
|
{ |
|
603
|
85 |
|
$old_pos = 0; |
|
604
|
85 |
|
$pos = -1; |
|
605
|
85 |
|
while (true) |
|
606
|
|
|
{ |
|
607
|
85 |
|
$pos = strpos($db_string, '\'', $pos + 1); |
|
608
|
85 |
|
if ($pos === false) |
|
609
|
85 |
|
break; |
|
610
|
77 |
|
$clean .= substr($db_string, $old_pos, $pos - $old_pos); |
|
611
|
|
|
|
|
612
|
77 |
|
while (true) |
|
613
|
|
|
{ |
|
614
|
77 |
|
$pos1 = strpos($db_string, '\'', $pos + 1); |
|
615
|
77 |
|
$pos2 = strpos($db_string, $escape_char, $pos + 1); |
|
616
|
|
|
|
|
617
|
77 |
|
if ($pos1 === false) |
|
618
|
|
|
break; |
|
619
|
77 |
|
elseif ($pos2 === false || $pos2 > $pos1) |
|
620
|
|
|
{ |
|
621
|
77 |
|
$pos = $pos1; |
|
622
|
77 |
|
break; |
|
623
|
|
|
} |
|
624
|
|
|
|
|
625
|
16 |
|
$pos = $pos2 + 1; |
|
626
|
|
|
} |
|
627
|
|
|
|
|
628
|
77 |
|
$clean .= ' %s '; |
|
629
|
77 |
|
$old_pos = $pos + 1; |
|
630
|
|
|
} |
|
631
|
|
|
|
|
632
|
85 |
|
$clean .= substr($db_string, $old_pos); |
|
633
|
85 |
|
$clean = trim(strtolower(preg_replace($this->allowed_comments['from'], $this->allowed_comments['to'], $clean))); |
|
634
|
|
|
|
|
635
|
|
|
// Comments? We don't use comments in our queries, we leave 'em outside! |
|
636
|
85 |
|
if (strpos($clean, '/*') > 2 || strpos($clean, '--') !== false || strpos($clean, ';') !== false) |
|
637
|
|
|
$fail = true; |
|
638
|
|
|
// Trying to change passwords, slow us down, or something? |
|
639
|
85 |
|
elseif (strpos($clean, 'sleep') !== false && preg_match('~(^|[^a-z])sleep($|[^[_a-z])~s', $clean) != 0) |
|
640
|
|
|
$fail = true; |
|
641
|
85 |
|
elseif (strpos($clean, 'benchmark') !== false && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s', $clean) != 0) |
|
642
|
|
|
$fail = true; |
|
643
|
|
|
|
|
644
|
85 |
|
if (!empty($fail) && class_exists('\\ElkArte\\Errors\\Errors')) |
|
645
|
|
|
{ |
|
646
|
|
|
$this->error_backtrace('Hacking attempt...', 'Hacking attempt...' . "\n" . $db_string, E_USER_ERROR, __FILE__, __LINE__); |
|
|
|
|
|
|
647
|
|
|
} |
|
648
|
|
|
} |
|
649
|
85 |
|
} |
|
650
|
|
|
|
|
651
|
|
|
/** |
|
652
|
|
|
* {@inheritDoc} |
|
653
|
|
|
*/ |
|
654
|
|
|
abstract public function error($db_string); |
|
|
|
|
|
|
655
|
|
|
|
|
656
|
|
|
/** |
|
657
|
|
|
* {@inheritDoc} |
|
658
|
|
|
*/ |
|
659
|
|
|
abstract public function insert($method = 'replace', $table, $columns, $data, $keys, $disable_trans = false); |
|
660
|
|
|
|
|
661
|
|
|
/** |
|
662
|
|
|
* {@inheritDoc} |
|
663
|
|
|
*/ |
|
664
|
27 |
|
public function error_backtrace($error_message, $log_message = '', $error_type = false, $file = null, $line = null) |
|
665
|
|
|
{ |
|
666
|
27 |
|
if (empty($log_message)) |
|
667
|
|
|
$log_message = $error_message; |
|
|
|
|
|
|
668
|
|
|
|
|
669
|
27 |
|
foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $step) |
|
670
|
|
|
{ |
|
671
|
|
|
// Found it? |
|
672
|
27 |
|
if (!method_exists($this, $step['function']) && !in_array(substr($step['function'], 0, 7), array('elk_db_', 'preg_re', 'db_erro', 'call_us'))) |
|
673
|
|
|
{ |
|
674
|
27 |
|
$log_message .= '<br />Function: ' . $step['function']; |
|
675
|
27 |
|
break; |
|
676
|
|
|
} |
|
677
|
|
|
|
|
678
|
27 |
|
if (isset($step['line'])) |
|
679
|
|
|
{ |
|
680
|
27 |
|
$file = $step['file']; |
|
|
|
|
|
|
681
|
27 |
|
$line = $step['line']; |
|
|
|
|
|
|
682
|
|
|
} |
|
683
|
|
|
} |
|
684
|
|
|
|
|
685
|
|
|
// A special case - we want the file and line numbers for debugging. |
|
686
|
27 |
|
if ($error_type == 'return') |
|
687
|
27 |
|
return array($file, $line); |
|
688
|
|
|
|
|
689
|
|
|
// Is always a critical error. |
|
690
|
|
|
if (class_exists('\\ElkArte\\Errors\\Errors')) |
|
691
|
|
|
{ |
|
692
|
|
|
\ElkArte\Errors\Errors::instance()->log_error($log_message, 'critical', $file, $line); |
|
693
|
|
|
} |
|
694
|
|
|
|
|
695
|
|
|
if (class_exists('\\ElkArte\\Exceptions\\Exception')) |
|
696
|
|
|
{ |
|
697
|
|
|
throw new \ElkArte\Exceptions\Exception([false, $error_message], false); |
|
|
|
|
|
|
698
|
|
|
} |
|
699
|
|
View Code Duplication |
elseif ($error_type) |
|
700
|
|
|
trigger_error($error_message . ($line !== null ? '<em>(' . basename($file) . '-' . $line . ')</em>' : ''), $error_type); |
|
701
|
|
View Code Duplication |
else |
|
702
|
|
|
trigger_error($error_message . ($line !== null ? '<em>(' . basename($file) . '-' . $line . ')</em>' : '')); |
|
703
|
|
|
|
|
704
|
|
|
return array('', ''); |
|
705
|
|
|
} |
|
706
|
|
|
|
|
707
|
|
|
/** |
|
708
|
|
|
* {@inheritDoc} |
|
709
|
|
|
*/ |
|
710
|
|
|
public function escape_wildcard_string($string, $translate_human_wildcards = false) |
|
711
|
|
|
{ |
|
712
|
|
|
$replacements = array( |
|
713
|
|
|
'%' => '\%', |
|
714
|
|
|
'_' => '\_', |
|
715
|
|
|
'\\' => '\\\\', |
|
716
|
|
|
); |
|
717
|
|
|
|
|
718
|
|
|
if ($translate_human_wildcards) |
|
719
|
|
|
$replacements += array( |
|
720
|
|
|
'*' => '%', |
|
721
|
|
|
); |
|
722
|
|
|
|
|
723
|
|
|
return strtr($string, $replacements); |
|
724
|
|
|
} |
|
725
|
|
|
|
|
726
|
|
|
/** |
|
727
|
|
|
* {@inheritDoc} |
|
728
|
|
|
*/ |
|
729
|
|
|
public function connection() |
|
730
|
|
|
{ |
|
731
|
|
|
// find it, find it |
|
732
|
|
|
return $this->connection; |
|
|
|
|
|
|
733
|
|
|
} |
|
734
|
|
|
|
|
735
|
|
|
/** |
|
736
|
|
|
* {@inheritDoc} |
|
737
|
|
|
*/ |
|
738
|
|
|
public function num_queries() |
|
739
|
|
|
{ |
|
740
|
|
|
return $this->_query_count; |
|
741
|
|
|
} |
|
742
|
|
|
|
|
743
|
|
|
/** |
|
744
|
|
|
* {@inheritDoc} |
|
745
|
|
|
*/ |
|
746
|
28 |
|
public function skip_next_error() |
|
747
|
|
|
{ |
|
748
|
28 |
|
$this->_skip_error = true; |
|
749
|
28 |
|
} |
|
750
|
|
|
|
|
751
|
|
|
/** |
|
752
|
|
|
* Set the unbuffered state for the connection |
|
753
|
|
|
* |
|
754
|
|
|
* @param bool $state |
|
755
|
|
|
*/ |
|
756
|
|
|
public function setUnbuffered($state) |
|
757
|
|
|
{ |
|
758
|
|
|
$this->_unbuffered = (bool) $state; |
|
759
|
|
|
} |
|
760
|
|
|
|
|
761
|
|
|
/** |
|
762
|
|
|
* Finds out if the connection is still valid. |
|
763
|
|
|
* |
|
764
|
|
|
* @return bool |
|
765
|
|
|
*/ |
|
766
|
|
|
public function validConnection() |
|
767
|
|
|
{ |
|
768
|
|
|
return (bool) $this->connection; |
|
769
|
|
|
} |
|
770
|
|
|
|
|
771
|
|
|
/** |
|
772
|
|
|
* Get the version number. |
|
773
|
|
|
* |
|
774
|
|
|
* @return string - the version |
|
775
|
|
|
* @throws \ElkArte\Exceptions\Exception |
|
776
|
|
|
*/ |
|
777
|
|
|
abstract public function client_version(); |
|
778
|
|
|
|
|
779
|
|
|
/** |
|
780
|
|
|
* Return server info. |
|
781
|
|
|
* |
|
782
|
|
|
* @return string |
|
783
|
|
|
*/ |
|
784
|
|
|
abstract public function server_info(); |
|
785
|
|
|
|
|
786
|
|
|
/** |
|
787
|
|
|
* Escape string for the database input |
|
788
|
|
|
* |
|
789
|
|
|
* @param string $string |
|
790
|
|
|
* |
|
791
|
|
|
* @return string |
|
792
|
|
|
*/ |
|
793
|
|
|
abstract public function escape_string($string); |
|
794
|
|
|
|
|
795
|
|
|
/** |
|
796
|
|
|
* Whether the database system is case sensitive. |
|
797
|
|
|
* |
|
798
|
|
|
* @return boolean |
|
799
|
|
|
*/ |
|
800
|
|
|
abstract public function case_sensitive(); |
|
801
|
|
|
|
|
802
|
|
|
/** |
|
803
|
|
|
* Get the name (title) of the database system. |
|
804
|
|
|
* |
|
805
|
|
|
* @return string |
|
806
|
|
|
*/ |
|
807
|
|
|
abstract public function title(); |
|
808
|
|
|
|
|
809
|
|
|
/** |
|
810
|
|
|
* Returns whether the database system supports ignore. |
|
811
|
|
|
* |
|
812
|
|
|
* @return false |
|
|
|
|
|
|
813
|
|
|
*/ |
|
814
|
|
|
abstract public function support_ignore(); |
|
815
|
|
|
|
|
816
|
|
|
/** |
|
817
|
|
|
* Get the version number. |
|
818
|
|
|
* |
|
819
|
|
|
* @return string - the version |
|
820
|
|
|
* @throws \ElkArte\Exceptions\Exception |
|
821
|
|
|
*/ |
|
822
|
|
|
abstract public function server_version(); |
|
823
|
|
|
|
|
824
|
|
|
/** |
|
825
|
|
|
* Temporary function to support migration to the new schema of the db layer |
|
826
|
|
|
* @deprecated since 2.0 |
|
827
|
|
|
*/ |
|
828
|
42 |
|
public function fetch_row($result) |
|
|
|
|
|
|
829
|
|
|
{ |
|
830
|
|
|
// \ElkArte\Errors\Errors::instance()->log_deprecated('Query::fetch_row()', 'Result::fetch_row()'); |
|
831
|
42 |
|
if ($result === false) |
|
832
|
|
|
{ |
|
833
|
|
|
return false; |
|
834
|
|
|
} |
|
835
|
|
|
else |
|
836
|
|
|
{ |
|
837
|
42 |
|
return $result->fetch_row(); |
|
838
|
|
|
} |
|
839
|
|
|
} |
|
840
|
|
|
|
|
841
|
|
|
/** |
|
842
|
|
|
* Temporary function to support migration to the new schema of the db layer |
|
843
|
|
|
* @deprecated since 2.0 |
|
844
|
|
|
*/ |
|
845
|
64 |
|
public function fetch_assoc($result) |
|
|
|
|
|
|
846
|
|
|
{ |
|
847
|
|
|
// \ElkArte\Errors\Errors::instance()->log_deprecated('Query::fetch_assoc()', 'Result::fetch_assoc()'); |
|
848
|
64 |
|
if ($result === false) |
|
849
|
|
|
{ |
|
850
|
|
|
return false; |
|
851
|
|
|
} |
|
852
|
|
|
else |
|
853
|
|
|
{ |
|
854
|
64 |
|
return $result->fetch_assoc(); |
|
855
|
|
|
} |
|
856
|
|
|
} |
|
857
|
|
|
|
|
858
|
|
|
/** |
|
859
|
|
|
* Temporary function to support migration to the new schema of the db layer |
|
860
|
|
|
* @deprecated since 2.0 |
|
861
|
|
|
*/ |
|
862
|
75 |
|
public function free_result($result) |
|
|
|
|
|
|
863
|
|
|
{ |
|
864
|
|
|
// \ElkArte\Errors\Errors::instance()->log_deprecated('Query::free_result()', 'Result::free_result()'); |
|
865
|
75 |
|
if ($result === false) |
|
866
|
|
|
{ |
|
867
|
|
|
return; |
|
868
|
|
|
} |
|
869
|
|
|
else |
|
870
|
|
|
{ |
|
871
|
75 |
|
return $result->free_result(); |
|
872
|
|
|
} |
|
873
|
|
|
} |
|
874
|
|
|
|
|
875
|
|
|
/** |
|
876
|
|
|
* Temporary function to supoprt migration to the new schema of the db layer |
|
877
|
|
|
* @deprecated since 2.0 |
|
878
|
|
|
*/ |
|
879
|
27 |
|
public function affected_rows() |
|
880
|
|
|
{ |
|
881
|
|
|
// \ElkArte\Errors\Errors::instance()->log_deprecated('Query::affected_rows()', 'Result::affected_rows()'); |
|
882
|
27 |
|
return $this->result->affected_rows(); |
|
883
|
|
|
} |
|
884
|
|
|
|
|
885
|
|
|
/** |
|
886
|
|
|
* Temporary function to support migration to the new schema of the db layer |
|
887
|
|
|
* @deprecated since 2.0 |
|
888
|
|
|
*/ |
|
889
|
47 |
|
public function num_rows($result) |
|
|
|
|
|
|
890
|
|
|
{ |
|
891
|
|
|
// \ElkArte\Errors\Errors::instance()->log_deprecated('Query::num_rows()', 'Result::num_rows()'); |
|
892
|
47 |
|
if ($result === false) |
|
893
|
|
|
{ |
|
894
|
|
|
return 0; |
|
895
|
|
|
} |
|
896
|
|
|
else |
|
897
|
|
|
{ |
|
898
|
47 |
|
return $result->num_rows(); |
|
899
|
|
|
} |
|
900
|
|
|
} |
|
901
|
|
|
|
|
902
|
|
|
/** |
|
903
|
|
|
* Temporary function to support migration to the new schema of the db layer |
|
904
|
|
|
* @deprecated since 2.0 |
|
905
|
|
|
*/ |
|
906
|
|
|
public function num_fields($result) |
|
|
|
|
|
|
907
|
|
|
{ |
|
908
|
|
|
// \ElkArte\Errors\Errors::instance()->log_deprecated('Query::num_fields()', 'Result::num_fields()'); |
|
909
|
|
|
if ($result === false) |
|
910
|
|
|
{ |
|
911
|
|
|
return 0; |
|
912
|
|
|
} |
|
913
|
|
|
else |
|
914
|
|
|
{ |
|
915
|
|
|
return $result->num_fields(); |
|
916
|
|
|
} |
|
917
|
|
|
} |
|
918
|
|
|
|
|
919
|
|
|
/** |
|
920
|
|
|
* Temporary function to support migration to the new schema of the db layer |
|
921
|
|
|
* @deprecated since 2.0 |
|
922
|
|
|
*/ |
|
923
|
22 |
|
public function insert_id($table) |
|
924
|
|
|
{ |
|
925
|
|
|
// \ElkArte\Errors\Errors::instance()->log_deprecated('Query::insert_id()', 'Result::insert_id()'); |
|
926
|
22 |
|
return $this->result->insert_id(); |
|
927
|
|
|
} |
|
928
|
|
|
|
|
929
|
|
|
/** |
|
930
|
|
|
* Temporary function to support migration to the new schema of the db layer |
|
931
|
|
|
* @deprecated since 2.0 |
|
932
|
|
|
*/ |
|
933
|
|
|
public function data_seek($result, $counter) |
|
|
|
|
|
|
934
|
|
|
{ |
|
935
|
|
|
// \ElkArte\Errors\Errors::instance()->log_deprecated('Query::data_seek()', 'Result::data_seek()'); |
|
936
|
|
|
return $result->data_seek($counter); |
|
937
|
|
|
} |
|
938
|
|
|
|
|
939
|
|
|
/** |
|
940
|
|
|
* Temporary function: I'm not sure this is the best place to have it, though it was |
|
941
|
|
|
* convenient while fixing other issues. |
|
942
|
|
|
* @deprecated since 2.0 |
|
943
|
|
|
*/ |
|
944
|
|
|
public function supportMediumtext() |
|
945
|
|
|
{ |
|
946
|
|
|
return false; |
|
947
|
|
|
} |
|
948
|
|
|
|
|
949
|
|
|
/** |
|
950
|
|
|
* Temporary function to support migration to the new schema of the db layer |
|
951
|
|
|
* @deprecated since 2.0 |
|
952
|
|
|
*/ |
|
953
|
|
|
abstract public function list_tables($db_name_str = false, $filter = false); |
|
|
|
|
|
|
954
|
|
|
} |
|
955
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountIdthat can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theidproperty of an instance of theAccountclass. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.