changeset 5 | 5e2f62d02dcd |
parent 0 | d970ebf37754 |
child 7 | cf61fcea0001 |
4:346c88efed21 | 5:5e2f62d02dcd |
---|---|
15 define( 'EZSQL_VERSION', 'WP1.25' ); |
15 define( 'EZSQL_VERSION', 'WP1.25' ); |
16 |
16 |
17 /** |
17 /** |
18 * @since 0.71 |
18 * @since 0.71 |
19 */ |
19 */ |
20 define( 'OBJECT', 'OBJECT', true ); |
20 define( 'OBJECT', 'OBJECT' ); |
21 define( 'object', 'OBJECT' ); // Back compat. |
|
21 |
22 |
22 /** |
23 /** |
23 * @since 2.5.0 |
24 * @since 2.5.0 |
24 */ |
25 */ |
25 define( 'OBJECT_K', 'OBJECT_K' ); |
26 define( 'OBJECT_K', 'OBJECT_K' ); |
40 * It is possible to replace this class with your own |
41 * It is possible to replace this class with your own |
41 * by setting the $wpdb global variable in wp-content/db.php |
42 * by setting the $wpdb global variable in wp-content/db.php |
42 * file to your class. The wpdb class will still be included, |
43 * file to your class. The wpdb class will still be included, |
43 * so you can extend it or simply use your own. |
44 * so you can extend it or simply use your own. |
44 * |
45 * |
45 * @link http://codex.wordpress.org/Function_Reference/wpdb_Class |
46 * @link https://codex.wordpress.org/Function_Reference/wpdb_Class |
46 * |
47 * |
47 * @package WordPress |
48 * @package WordPress |
48 * @subpackage Database |
49 * @subpackage Database |
49 * @since 0.71 |
50 * @since 0.71 |
50 */ |
51 */ |
51 class wpdb { |
52 class wpdb { |
52 |
53 |
53 /** |
54 /** |
54 * Whether to show SQL/DB errors |
55 * Whether to show SQL/DB errors. |
56 * |
|
57 * Default behavior is to show errors if both WP_DEBUG and WP_DEBUG_DISPLAY |
|
58 * evaluated to true. |
|
55 * |
59 * |
56 * @since 0.71 |
60 * @since 0.71 |
57 * @access private |
61 * @access private |
58 * @var bool |
62 * @var bool |
59 */ |
63 */ |
72 * The last error during query. |
76 * The last error during query. |
73 * |
77 * |
74 * @since 2.5.0 |
78 * @since 2.5.0 |
75 * @var string |
79 * @var string |
76 */ |
80 */ |
77 var $last_error = ''; |
81 public $last_error = ''; |
78 |
82 |
79 /** |
83 /** |
80 * Amount of queries made |
84 * Amount of queries made |
81 * |
85 * |
82 * @since 1.2.0 |
86 * @since 1.2.0 |
138 * @var mixed |
142 * @var mixed |
139 */ |
143 */ |
140 protected $result; |
144 protected $result; |
141 |
145 |
142 /** |
146 /** |
147 * Cached column info, for sanity checking data before inserting |
|
148 * |
|
149 * @since 4.2.0 |
|
150 * @access protected |
|
151 * @var array |
|
152 */ |
|
153 protected $col_meta = array(); |
|
154 |
|
155 /** |
|
156 * Calculated character sets on tables |
|
157 * |
|
158 * @since 4.2.0 |
|
159 * @access protected |
|
160 * @var array |
|
161 */ |
|
162 protected $table_charset = array(); |
|
163 |
|
164 /** |
|
165 * Whether text fields in the current query need to be sanity checked. |
|
166 * |
|
167 * @since 4.2.0 |
|
168 * @access protected |
|
169 * @var bool |
|
170 */ |
|
171 protected $check_current_query = true; |
|
172 |
|
173 /** |
|
174 * Flag to ensure we don't run into recursion problems when checking the collation. |
|
175 * |
|
176 * @since 4.2.0 |
|
177 * @access private |
|
178 * @see wpdb::check_safe_collation() |
|
179 * @var boolean |
|
180 */ |
|
181 private $checking_collation = false; |
|
182 |
|
183 /** |
|
143 * Saved info on the table column |
184 * Saved info on the table column |
144 * |
185 * |
145 * @since 0.71 |
186 * @since 0.71 |
146 * @access protected |
187 * @access protected |
147 * @var array |
188 * @var array |
156 * @var array |
197 * @var array |
157 */ |
198 */ |
158 var $queries; |
199 var $queries; |
159 |
200 |
160 /** |
201 /** |
202 * The number of times to retry reconnecting before dying. |
|
203 * |
|
204 * @since 3.9.0 |
|
205 * @access protected |
|
206 * @see wpdb::check_connection() |
|
207 * @var int |
|
208 */ |
|
209 protected $reconnect_retries = 5; |
|
210 |
|
211 /** |
|
161 * WordPress table prefix |
212 * WordPress table prefix |
162 * |
213 * |
163 * You can set this to have multiple WordPress installations |
214 * You can set this to have multiple WordPress installations |
164 * in a single database. The second reason is for possible |
215 * in a single database. The second reason is for possible |
165 * security precautions. |
216 * security precautions. |
169 * @var string |
220 * @var string |
170 */ |
221 */ |
171 var $prefix = ''; |
222 var $prefix = ''; |
172 |
223 |
173 /** |
224 /** |
225 * WordPress base table prefix. |
|
226 * |
|
227 * @since 3.0.0 |
|
228 * @access public |
|
229 * @var string |
|
230 */ |
|
231 public $base_prefix; |
|
232 |
|
233 /** |
|
174 * Whether the database queries are ready to start executing. |
234 * Whether the database queries are ready to start executing. |
175 * |
235 * |
176 * @since 2.3.2 |
236 * @since 2.3.2 |
177 * @access private |
237 * @access private |
178 * @var bool |
238 * @var bool |
179 */ |
239 */ |
180 var $ready = false; |
240 var $ready = false; |
181 |
241 |
182 /** |
242 /** |
183 * {@internal Missing Description}} |
243 * Blog ID. |
184 * |
244 * |
185 * @since 3.0.0 |
245 * @since 3.0.0 |
186 * @access public |
246 * @access public |
187 * @var int |
247 * @var int |
188 */ |
248 */ |
189 var $blogid = 0; |
249 public $blogid = 0; |
190 |
250 |
191 /** |
251 /** |
192 * {@internal Missing Description}} |
252 * Site ID. |
193 * |
253 * |
194 * @since 3.0.0 |
254 * @since 3.0.0 |
195 * @access public |
255 * @access public |
196 * @var int |
256 * @var int |
197 */ |
257 */ |
198 var $siteid = 0; |
258 public $siteid = 0; |
199 |
259 |
200 /** |
260 /** |
201 * List of WordPress per-blog tables |
261 * List of WordPress per-blog tables |
202 * |
262 * |
203 * @since 2.5.0 |
263 * @since 2.5.0 |
246 * |
306 * |
247 * @since 1.5.0 |
307 * @since 1.5.0 |
248 * @access public |
308 * @access public |
249 * @var string |
309 * @var string |
250 */ |
310 */ |
251 var $comments; |
311 public $comments; |
252 |
312 |
253 /** |
313 /** |
254 * WordPress Comment Metadata table |
314 * WordPress Comment Metadata table |
255 * |
315 * |
256 * @since 2.9.0 |
316 * @since 2.9.0 |
257 * @access public |
317 * @access public |
258 * @var string |
318 * @var string |
259 */ |
319 */ |
260 var $commentmeta; |
320 public $commentmeta; |
261 |
321 |
262 /** |
322 /** |
263 * WordPress Links table |
323 * WordPress Links table |
264 * |
324 * |
265 * @since 1.5.0 |
325 * @since 1.5.0 |
266 * @access public |
326 * @access public |
267 * @var string |
327 * @var string |
268 */ |
328 */ |
269 var $links; |
329 public $links; |
270 |
330 |
271 /** |
331 /** |
272 * WordPress Options table |
332 * WordPress Options table |
273 * |
333 * |
274 * @since 1.5.0 |
334 * @since 1.5.0 |
275 * @access public |
335 * @access public |
276 * @var string |
336 * @var string |
277 */ |
337 */ |
278 var $options; |
338 public $options; |
279 |
339 |
280 /** |
340 /** |
281 * WordPress Post Metadata table |
341 * WordPress Post Metadata table |
282 * |
342 * |
283 * @since 1.5.0 |
343 * @since 1.5.0 |
284 * @access public |
344 * @access public |
285 * @var string |
345 * @var string |
286 */ |
346 */ |
287 var $postmeta; |
347 public $postmeta; |
288 |
348 |
289 /** |
349 /** |
290 * WordPress Posts table |
350 * WordPress Posts table |
291 * |
351 * |
292 * @since 1.5.0 |
352 * @since 1.5.0 |
293 * @access public |
353 * @access public |
294 * @var string |
354 * @var string |
295 */ |
355 */ |
296 var $posts; |
356 public $posts; |
297 |
357 |
298 /** |
358 /** |
299 * WordPress Terms table |
359 * WordPress Terms table |
300 * |
360 * |
301 * @since 2.3.0 |
361 * @since 2.3.0 |
302 * @access public |
362 * @access public |
303 * @var string |
363 * @var string |
304 */ |
364 */ |
305 var $terms; |
365 public $terms; |
306 |
366 |
307 /** |
367 /** |
308 * WordPress Term Relationships table |
368 * WordPress Term Relationships table |
309 * |
369 * |
310 * @since 2.3.0 |
370 * @since 2.3.0 |
311 * @access public |
371 * @access public |
312 * @var string |
372 * @var string |
313 */ |
373 */ |
314 var $term_relationships; |
374 public $term_relationships; |
315 |
375 |
316 /** |
376 /** |
317 * WordPress Term Taxonomy table |
377 * WordPress Term Taxonomy table |
318 * |
378 * |
319 * @since 2.3.0 |
379 * @since 2.3.0 |
320 * @access public |
380 * @access public |
321 * @var string |
381 * @var string |
322 */ |
382 */ |
323 var $term_taxonomy; |
383 public $term_taxonomy; |
324 |
384 |
325 /* |
385 /* |
326 * Global and Multisite tables |
386 * Global and Multisite tables |
327 */ |
387 */ |
328 |
388 |
331 * |
391 * |
332 * @since 2.3.0 |
392 * @since 2.3.0 |
333 * @access public |
393 * @access public |
334 * @var string |
394 * @var string |
335 */ |
395 */ |
336 var $usermeta; |
396 public $usermeta; |
337 |
397 |
338 /** |
398 /** |
339 * WordPress Users table |
399 * WordPress Users table |
340 * |
400 * |
341 * @since 1.5.0 |
401 * @since 1.5.0 |
342 * @access public |
402 * @access public |
343 * @var string |
403 * @var string |
344 */ |
404 */ |
345 var $users; |
405 public $users; |
346 |
406 |
347 /** |
407 /** |
348 * Multisite Blogs table |
408 * Multisite Blogs table |
349 * |
409 * |
350 * @since 3.0.0 |
410 * @since 3.0.0 |
351 * @access public |
411 * @access public |
352 * @var string |
412 * @var string |
353 */ |
413 */ |
354 var $blogs; |
414 public $blogs; |
355 |
415 |
356 /** |
416 /** |
357 * Multisite Blog Versions table |
417 * Multisite Blog Versions table |
358 * |
418 * |
359 * @since 3.0.0 |
419 * @since 3.0.0 |
360 * @access public |
420 * @access public |
361 * @var string |
421 * @var string |
362 */ |
422 */ |
363 var $blog_versions; |
423 public $blog_versions; |
364 |
424 |
365 /** |
425 /** |
366 * Multisite Registration Log table |
426 * Multisite Registration Log table |
367 * |
427 * |
368 * @since 3.0.0 |
428 * @since 3.0.0 |
369 * @access public |
429 * @access public |
370 * @var string |
430 * @var string |
371 */ |
431 */ |
372 var $registration_log; |
432 public $registration_log; |
373 |
433 |
374 /** |
434 /** |
375 * Multisite Signups table |
435 * Multisite Signups table |
376 * |
436 * |
377 * @since 3.0.0 |
437 * @since 3.0.0 |
378 * @access public |
438 * @access public |
379 * @var string |
439 * @var string |
380 */ |
440 */ |
381 var $signups; |
441 public $signups; |
382 |
442 |
383 /** |
443 /** |
384 * Multisite Sites table |
444 * Multisite Sites table |
385 * |
445 * |
386 * @since 3.0.0 |
446 * @since 3.0.0 |
387 * @access public |
447 * @access public |
388 * @var string |
448 * @var string |
389 */ |
449 */ |
390 var $site; |
450 public $site; |
391 |
451 |
392 /** |
452 /** |
393 * Multisite Sitewide Terms table |
453 * Multisite Sitewide Terms table |
394 * |
454 * |
395 * @since 3.0.0 |
455 * @since 3.0.0 |
396 * @access public |
456 * @access public |
397 * @var string |
457 * @var string |
398 */ |
458 */ |
399 var $sitecategories; |
459 public $sitecategories; |
400 |
460 |
401 /** |
461 /** |
402 * Multisite Site Metadata table |
462 * Multisite Site Metadata table |
403 * |
463 * |
404 * @since 3.0.0 |
464 * @since 3.0.0 |
405 * @access public |
465 * @access public |
406 * @var string |
466 * @var string |
407 */ |
467 */ |
408 var $sitemeta; |
468 public $sitemeta; |
409 |
469 |
410 /** |
470 /** |
411 * Format specifiers for DB columns. Columns not listed here default to %s. Initialized during WP load. |
471 * Format specifiers for DB columns. Columns not listed here default to %s. Initialized during WP load. |
412 * |
472 * |
413 * Keys are column names, values are format types: 'ID' => '%d' |
473 * Keys are column names, values are format types: 'ID' => '%d' |
419 * @see wpdb::delete() |
479 * @see wpdb::delete() |
420 * @see wp_set_wpdb_vars() |
480 * @see wp_set_wpdb_vars() |
421 * @access public |
481 * @access public |
422 * @var array |
482 * @var array |
423 */ |
483 */ |
424 var $field_types = array(); |
484 public $field_types = array(); |
425 |
485 |
426 /** |
486 /** |
427 * Database table columns charset |
487 * Database table columns charset |
428 * |
488 * |
429 * @since 2.2.0 |
489 * @since 2.2.0 |
430 * @access public |
490 * @access public |
431 * @var string |
491 * @var string |
432 */ |
492 */ |
433 var $charset; |
493 public $charset; |
434 |
494 |
435 /** |
495 /** |
436 * Database table columns collate |
496 * Database table columns collate |
437 * |
497 * |
438 * @since 2.2.0 |
498 * @since 2.2.0 |
439 * @access public |
499 * @access public |
440 * @var string |
500 * @var string |
441 */ |
501 */ |
442 var $collate; |
502 public $collate; |
443 |
503 |
444 /** |
504 /** |
445 * Database Username |
505 * Database Username |
446 * |
506 * |
447 * @since 2.9.0 |
507 * @since 2.9.0 |
491 * |
551 * |
492 * @since 3.0.0 |
552 * @since 3.0.0 |
493 * @access public |
553 * @access public |
494 * @var string |
554 * @var string |
495 */ |
555 */ |
496 var $func_call; |
556 public $func_call; |
497 |
557 |
498 /** |
558 /** |
499 * Whether MySQL is used as the database engine. |
559 * Whether MySQL is used as the database engine. |
500 * |
560 * |
501 * Set in WPDB::db_connect() to true, by default. This is used when checking |
561 * Set in WPDB::db_connect() to true, by default. This is used when checking |
508 * @var bool |
568 * @var bool |
509 */ |
569 */ |
510 public $is_mysql = null; |
570 public $is_mysql = null; |
511 |
571 |
512 /** |
572 /** |
573 * A list of incompatible SQL modes. |
|
574 * |
|
575 * @since 3.9.0 |
|
576 * @access protected |
|
577 * @var array |
|
578 */ |
|
579 protected $incompatible_modes = array( 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY', |
|
580 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL' ); |
|
581 |
|
582 /** |
|
583 * Whether to use mysqli over mysql. |
|
584 * |
|
585 * @since 3.9.0 |
|
586 * @access private |
|
587 * @var bool |
|
588 */ |
|
589 private $use_mysqli = false; |
|
590 |
|
591 /** |
|
592 * Whether we've managed to successfully connect at some point |
|
593 * |
|
594 * @since 3.9.0 |
|
595 * @access private |
|
596 * @var bool |
|
597 */ |
|
598 private $has_connected = false; |
|
599 |
|
600 /** |
|
513 * Connects to the database server and selects a database |
601 * Connects to the database server and selects a database |
514 * |
602 * |
515 * PHP5 style constructor for compatibility with PHP5. Does |
603 * PHP5 style constructor for compatibility with PHP5. Does |
516 * the actual setting up of the class properties and connection |
604 * the actual setting up of the class properties and connection |
517 * to the database. |
605 * to the database. |
518 * |
606 * |
519 * @link http://core.trac.wordpress.org/ticket/3354 |
607 * @link https://core.trac.wordpress.org/ticket/3354 |
520 * @since 2.0.8 |
608 * @since 2.0.8 |
521 * |
609 * |
522 * @param string $dbuser MySQL database user |
610 * @param string $dbuser MySQL database user |
523 * @param string $dbpassword MySQL database password |
611 * @param string $dbpassword MySQL database password |
524 * @param string $dbname MySQL database name |
612 * @param string $dbname MySQL database name |
525 * @param string $dbhost MySQL database host |
613 * @param string $dbhost MySQL database host |
526 */ |
614 */ |
527 function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) { |
615 public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) { |
528 register_shutdown_function( array( $this, '__destruct' ) ); |
616 register_shutdown_function( array( $this, '__destruct' ) ); |
529 |
617 |
530 if ( WP_DEBUG && WP_DEBUG_DISPLAY ) |
618 if ( WP_DEBUG && WP_DEBUG_DISPLAY ) |
531 $this->show_errors(); |
619 $this->show_errors(); |
532 |
620 |
533 $this->init_charset(); |
621 /* Use ext/mysqli if it exists and: |
622 * - WP_USE_EXT_MYSQL is defined as false, or |
|
623 * - We are a development version of WordPress, or |
|
624 * - We are running PHP 5.5 or greater, or |
|
625 * - ext/mysql is not loaded. |
|
626 */ |
|
627 if ( function_exists( 'mysqli_connect' ) ) { |
|
628 if ( defined( 'WP_USE_EXT_MYSQL' ) ) { |
|
629 $this->use_mysqli = ! WP_USE_EXT_MYSQL; |
|
630 } elseif ( version_compare( phpversion(), '5.5', '>=' ) || ! function_exists( 'mysql_connect' ) ) { |
|
631 $this->use_mysqli = true; |
|
632 } elseif ( false !== strpos( $GLOBALS['wp_version'], '-' ) ) { |
|
633 $this->use_mysqli = true; |
|
634 } |
|
635 } |
|
534 |
636 |
535 $this->dbuser = $dbuser; |
637 $this->dbuser = $dbuser; |
536 $this->dbpassword = $dbpassword; |
638 $this->dbpassword = $dbpassword; |
537 $this->dbname = $dbname; |
639 $this->dbname = $dbname; |
538 $this->dbhost = $dbhost; |
640 $this->dbhost = $dbhost; |
539 |
641 |
642 // wp-config.php creation will manually connect when ready. |
|
643 if ( defined( 'WP_SETUP_CONFIG' ) ) { |
|
644 return; |
|
645 } |
|
646 |
|
540 $this->db_connect(); |
647 $this->db_connect(); |
541 } |
648 } |
542 |
649 |
543 /** |
650 /** |
544 * PHP5 style destructor and will run when database object is destroyed. |
651 * PHP5 style destructor and will run when database object is destroyed. |
545 * |
652 * |
546 * @see wpdb::__construct() |
653 * @see wpdb::__construct() |
547 * @since 2.0.8 |
654 * @since 2.0.8 |
548 * @return bool true |
655 * @return bool true |
549 */ |
656 */ |
550 function __destruct() { |
657 public function __destruct() { |
551 return true; |
658 return true; |
552 } |
659 } |
553 |
660 |
554 /** |
661 /** |
555 * PHP5 style magic getter, used to lazy-load expensive data. |
662 * PHP5 style magic getter, used to lazy-load expensive data. |
557 * @since 3.5.0 |
664 * @since 3.5.0 |
558 * |
665 * |
559 * @param string $name The private member to get, and optionally process |
666 * @param string $name The private member to get, and optionally process |
560 * @return mixed The private member |
667 * @return mixed The private member |
561 */ |
668 */ |
562 function __get( $name ) { |
669 public function __get( $name ) { |
563 if ( 'col_info' == $name ) |
670 if ( 'col_info' === $name ) |
564 $this->load_col_info(); |
671 $this->load_col_info(); |
565 |
672 |
566 return $this->$name; |
673 return $this->$name; |
567 } |
674 } |
568 |
675 |
569 /** |
676 /** |
570 * Magic function, for backwards compatibility |
677 * Magic function, for backwards compatibility. |
571 * |
678 * |
572 * @since 3.5.0 |
679 * @since 3.5.0 |
573 * |
680 * |
574 * @param string $name The private member to set |
681 * @param string $name The private member to set |
575 * @param mixed $value The value to set |
682 * @param mixed $value The value to set |
576 */ |
683 */ |
577 function __set( $name, $value ) { |
684 public function __set( $name, $value ) { |
685 $protected_members = array( |
|
686 'col_meta', |
|
687 'table_charset', |
|
688 'check_current_query', |
|
689 ); |
|
690 if ( in_array( $name, $protected_members, true ) ) { |
|
691 return; |
|
692 } |
|
578 $this->$name = $value; |
693 $this->$name = $value; |
579 } |
694 } |
580 |
695 |
581 /** |
696 /** |
582 * Magic function, for backwards compatibility |
697 * Magic function, for backwards compatibility. |
583 * |
698 * |
584 * @since 3.5.0 |
699 * @since 3.5.0 |
585 * |
700 * |
586 * @param string $name The private member to check |
701 * @param string $name The private member to check |
587 * |
702 * |
588 * @return bool If the member is set or not |
703 * @return bool If the member is set or not |
589 */ |
704 */ |
590 function __isset( $name ) { |
705 public function __isset( $name ) { |
591 return isset( $this->$name ); |
706 return isset( $this->$name ); |
592 } |
707 } |
593 |
708 |
594 /** |
709 /** |
595 * Magic function, for backwards compatibility |
710 * Magic function, for backwards compatibility. |
596 * |
711 * |
597 * @since 3.5.0 |
712 * @since 3.5.0 |
598 * |
713 * |
599 * @param string $name The private member to unset |
714 * @param string $name The private member to unset |
600 */ |
715 */ |
601 function __unset( $name ) { |
716 public function __unset( $name ) { |
602 unset( $this->$name ); |
717 unset( $this->$name ); |
603 } |
718 } |
604 |
719 |
605 /** |
720 /** |
606 * Set $this->charset and $this->collate |
721 * Set $this->charset and $this->collate |
607 * |
722 * |
608 * @since 3.1.0 |
723 * @since 3.1.0 |
609 */ |
724 */ |
610 function init_charset() { |
725 public function init_charset() { |
611 if ( function_exists('is_multisite') && is_multisite() ) { |
726 if ( function_exists('is_multisite') && is_multisite() ) { |
612 $this->charset = 'utf8'; |
727 $this->charset = 'utf8'; |
613 if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) |
728 if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) { |
614 $this->collate = DB_COLLATE; |
729 $this->collate = DB_COLLATE; |
615 else |
730 } else { |
616 $this->collate = 'utf8_general_ci'; |
731 $this->collate = 'utf8_general_ci'; |
732 } |
|
617 } elseif ( defined( 'DB_COLLATE' ) ) { |
733 } elseif ( defined( 'DB_COLLATE' ) ) { |
618 $this->collate = DB_COLLATE; |
734 $this->collate = DB_COLLATE; |
619 } |
735 } |
620 |
736 |
621 if ( defined( 'DB_CHARSET' ) ) |
737 if ( defined( 'DB_CHARSET' ) ) { |
622 $this->charset = DB_CHARSET; |
738 $this->charset = DB_CHARSET; |
739 } |
|
740 |
|
741 if ( ( $this->use_mysqli && ! ( $this->dbh instanceof mysqli ) ) |
|
742 || ( empty( $this->dbh ) || ! ( $this->dbh instanceof mysqli ) ) ) { |
|
743 return; |
|
744 } |
|
745 |
|
746 if ( 'utf8' === $this->charset && $this->has_cap( 'utf8mb4' ) ) { |
|
747 $this->charset = 'utf8mb4'; |
|
748 } |
|
749 |
|
750 if ( 'utf8mb4' === $this->charset && ( ! $this->collate || stripos( $this->collate, 'utf8_' ) === 0 ) ) { |
|
751 $this->collate = 'utf8mb4_unicode_ci'; |
|
752 } |
|
623 } |
753 } |
624 |
754 |
625 /** |
755 /** |
626 * Sets the connection's character set. |
756 * Sets the connection's character set. |
627 * |
757 * |
628 * @since 3.1.0 |
758 * @since 3.1.0 |
629 * |
759 * |
630 * @param resource $dbh The resource given by mysql_connect |
760 * @param resource $dbh The resource given by mysql_connect |
631 * @param string $charset The character set (optional) |
761 * @param string $charset Optional. The character set. Default null. |
632 * @param string $collate The collation (optional) |
762 * @param string $collate Optional. The collation. Default null. |
633 */ |
763 */ |
634 function set_charset( $dbh, $charset = null, $collate = null ) { |
764 public function set_charset( $dbh, $charset = null, $collate = null ) { |
635 if ( ! isset( $charset ) ) |
765 if ( ! isset( $charset ) ) |
636 $charset = $this->charset; |
766 $charset = $this->charset; |
637 if ( ! isset( $collate ) ) |
767 if ( ! isset( $collate ) ) |
638 $collate = $this->collate; |
768 $collate = $this->collate; |
639 if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) { |
769 if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) { |
640 if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) { |
770 if ( $this->use_mysqli ) { |
641 mysql_set_charset( $charset, $dbh ); |
771 if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) { |
772 mysqli_set_charset( $dbh, $charset ); |
|
773 } else { |
|
774 $query = $this->prepare( 'SET NAMES %s', $charset ); |
|
775 if ( ! empty( $collate ) ) |
|
776 $query .= $this->prepare( ' COLLATE %s', $collate ); |
|
777 mysqli_query( $dbh, $query ); |
|
778 } |
|
642 } else { |
779 } else { |
643 $query = $this->prepare( 'SET NAMES %s', $charset ); |
780 if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) { |
644 if ( ! empty( $collate ) ) |
781 mysql_set_charset( $charset, $dbh ); |
645 $query .= $this->prepare( ' COLLATE %s', $collate ); |
782 } else { |
646 mysql_query( $query, $dbh ); |
783 $query = $this->prepare( 'SET NAMES %s', $charset ); |
647 } |
784 if ( ! empty( $collate ) ) |
785 $query .= $this->prepare( ' COLLATE %s', $collate ); |
|
786 mysql_query( $query, $dbh ); |
|
787 } |
|
788 } |
|
789 } |
|
790 } |
|
791 |
|
792 /** |
|
793 * Change the current SQL mode, and ensure its WordPress compatibility. |
|
794 * |
|
795 * If no modes are passed, it will ensure the current MySQL server |
|
796 * modes are compatible. |
|
797 * |
|
798 * @since 3.9.0 |
|
799 * |
|
800 * @param array $modes Optional. A list of SQL modes to set. |
|
801 */ |
|
802 public function set_sql_mode( $modes = array() ) { |
|
803 if ( empty( $modes ) ) { |
|
804 if ( $this->use_mysqli ) { |
|
805 $res = mysqli_query( $this->dbh, 'SELECT @@SESSION.sql_mode' ); |
|
806 } else { |
|
807 $res = mysql_query( 'SELECT @@SESSION.sql_mode', $this->dbh ); |
|
808 } |
|
809 |
|
810 if ( empty( $res ) ) { |
|
811 return; |
|
812 } |
|
813 |
|
814 if ( $this->use_mysqli ) { |
|
815 $modes_array = mysqli_fetch_array( $res ); |
|
816 if ( empty( $modes_array[0] ) ) { |
|
817 return; |
|
818 } |
|
819 $modes_str = $modes_array[0]; |
|
820 } else { |
|
821 $modes_str = mysql_result( $res, 0 ); |
|
822 } |
|
823 |
|
824 if ( empty( $modes_str ) ) { |
|
825 return; |
|
826 } |
|
827 |
|
828 $modes = explode( ',', $modes_str ); |
|
829 } |
|
830 |
|
831 $modes = array_change_key_case( $modes, CASE_UPPER ); |
|
832 |
|
833 /** |
|
834 * Filter the list of incompatible SQL modes to exclude. |
|
835 * |
|
836 * @since 3.9.0 |
|
837 * |
|
838 * @param array $incompatible_modes An array of incompatible modes. |
|
839 */ |
|
840 $incompatible_modes = (array) apply_filters( 'incompatible_sql_modes', $this->incompatible_modes ); |
|
841 |
|
842 foreach( $modes as $i => $mode ) { |
|
843 if ( in_array( $mode, $incompatible_modes ) ) { |
|
844 unset( $modes[ $i ] ); |
|
845 } |
|
846 } |
|
847 |
|
848 $modes_str = implode( ',', $modes ); |
|
849 |
|
850 if ( $this->use_mysqli ) { |
|
851 mysqli_query( $this->dbh, "SET SESSION sql_mode='$modes_str'" ); |
|
852 } else { |
|
853 mysql_query( "SET SESSION sql_mode='$modes_str'", $this->dbh ); |
|
648 } |
854 } |
649 } |
855 } |
650 |
856 |
651 /** |
857 /** |
652 * Sets the table prefix for the WordPress tables. |
858 * Sets the table prefix for the WordPress tables. |
655 * |
861 * |
656 * @param string $prefix Alphanumeric name for the new prefix. |
862 * @param string $prefix Alphanumeric name for the new prefix. |
657 * @param bool $set_table_names Optional. Whether the table names, e.g. wpdb::$posts, should be updated or not. |
863 * @param bool $set_table_names Optional. Whether the table names, e.g. wpdb::$posts, should be updated or not. |
658 * @return string|WP_Error Old prefix or WP_Error on error |
864 * @return string|WP_Error Old prefix or WP_Error on error |
659 */ |
865 */ |
660 function set_prefix( $prefix, $set_table_names = true ) { |
866 public function set_prefix( $prefix, $set_table_names = true ) { |
661 |
867 |
662 if ( preg_match( '|[^a-z0-9_]|i', $prefix ) ) |
868 if ( preg_match( '|[^a-z0-9_]|i', $prefix ) ) |
663 return new WP_Error('invalid_db_prefix', 'Invalid database prefix' ); |
869 return new WP_Error('invalid_db_prefix', 'Invalid database prefix' ); |
664 |
870 |
665 $old_prefix = is_multisite() ? '' : $prefix; |
871 $old_prefix = is_multisite() ? '' : $prefix; |
692 * |
898 * |
693 * @since 3.0.0 |
899 * @since 3.0.0 |
694 * @access public |
900 * @access public |
695 * @param int $blog_id |
901 * @param int $blog_id |
696 * @param int $site_id Optional. |
902 * @param int $site_id Optional. |
697 * @return string previous blog id |
903 * @return int previous blog id |
698 */ |
904 */ |
699 function set_blog_id( $blog_id, $site_id = 0 ) { |
905 public function set_blog_id( $blog_id, $site_id = 0 ) { |
700 if ( ! empty( $site_id ) ) |
906 if ( ! empty( $site_id ) ) |
701 $this->siteid = $site_id; |
907 $this->siteid = $site_id; |
702 |
908 |
703 $old_blog_id = $this->blogid; |
909 $old_blog_id = $this->blogid; |
704 $this->blogid = $blog_id; |
910 $this->blogid = $blog_id; |
715 } |
921 } |
716 |
922 |
717 /** |
923 /** |
718 * Gets blog prefix. |
924 * Gets blog prefix. |
719 * |
925 * |
720 * @uses is_multisite() |
|
721 * @since 3.0.0 |
926 * @since 3.0.0 |
722 * @param int $blog_id Optional. |
927 * @param int $blog_id Optional. |
723 * @return string Blog prefix. |
928 * @return string Blog prefix. |
724 */ |
929 */ |
725 function get_blog_prefix( $blog_id = null ) { |
930 public function get_blog_prefix( $blog_id = null ) { |
726 if ( is_multisite() ) { |
931 if ( is_multisite() ) { |
727 if ( null === $blog_id ) |
932 if ( null === $blog_id ) |
728 $blog_id = $this->blogid; |
933 $blog_id = $this->blogid; |
729 $blog_id = (int) $blog_id; |
934 $blog_id = (int) $blog_id; |
730 if ( defined( 'MULTISITE' ) && ( 0 == $blog_id || 1 == $blog_id ) ) |
935 if ( defined( 'MULTISITE' ) && ( 0 == $blog_id || 1 == $blog_id ) ) |
754 * @since 3.0.0 |
959 * @since 3.0.0 |
755 * @uses wpdb::$tables |
960 * @uses wpdb::$tables |
756 * @uses wpdb::$old_tables |
961 * @uses wpdb::$old_tables |
757 * @uses wpdb::$global_tables |
962 * @uses wpdb::$global_tables |
758 * @uses wpdb::$ms_global_tables |
963 * @uses wpdb::$ms_global_tables |
759 * @uses is_multisite() |
|
760 * |
964 * |
761 * @param string $scope Optional. Can be all, global, ms_global, blog, or old tables. Defaults to all. |
965 * @param string $scope Optional. Can be all, global, ms_global, blog, or old tables. Defaults to all. |
762 * @param bool $prefix Optional. Whether to include table prefixes. Default true. If blog |
966 * @param bool $prefix Optional. Whether to include table prefixes. Default true. If blog |
763 * prefix is requested, then the custom users and usermeta tables will be mapped. |
967 * prefix is requested, then the custom users and usermeta tables will be mapped. |
764 * @param int $blog_id Optional. The blog_id to prefix. Defaults to wpdb::$blogid. Used only when prefix is requested. |
968 * @param int $blog_id Optional. The blog_id to prefix. Defaults to wpdb::$blogid. Used only when prefix is requested. |
765 * @return array Table names. When a prefix is requested, the key is the unprefixed table name. |
969 * @return array Table names. When a prefix is requested, the key is the unprefixed table name. |
766 */ |
970 */ |
767 function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) { |
971 public function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) { |
768 switch ( $scope ) { |
972 switch ( $scope ) { |
769 case 'all' : |
973 case 'all' : |
770 $tables = array_merge( $this->global_tables, $this->tables ); |
974 $tables = array_merge( $this->global_tables, $this->tables ); |
771 if ( is_multisite() ) |
975 if ( is_multisite() ) |
772 $tables = array_merge( $tables, $this->ms_global_tables ); |
976 $tables = array_merge( $tables, $this->ms_global_tables ); |
785 case 'old' : |
989 case 'old' : |
786 $tables = $this->old_tables; |
990 $tables = $this->old_tables; |
787 break; |
991 break; |
788 default : |
992 default : |
789 return array(); |
993 return array(); |
790 break; |
|
791 } |
994 } |
792 |
995 |
793 if ( $prefix ) { |
996 if ( $prefix ) { |
794 if ( ! $blog_id ) |
997 if ( ! $blog_id ) |
795 $blog_id = $this->blogid; |
998 $blog_id = $this->blogid; |
824 * |
1027 * |
825 * @param string $db MySQL database name |
1028 * @param string $db MySQL database name |
826 * @param resource $dbh Optional link identifier. |
1029 * @param resource $dbh Optional link identifier. |
827 * @return null Always null. |
1030 * @return null Always null. |
828 */ |
1031 */ |
829 function select( $db, $dbh = null ) { |
1032 public function select( $db, $dbh = null ) { |
830 if ( is_null($dbh) ) |
1033 if ( is_null($dbh) ) |
831 $dbh = $this->dbh; |
1034 $dbh = $this->dbh; |
832 |
1035 |
833 if ( !@mysql_select_db( $db, $dbh ) ) { |
1036 if ( $this->use_mysqli ) { |
1037 $success = @mysqli_select_db( $dbh, $db ); |
|
1038 } else { |
|
1039 $success = @mysql_select_db( $db, $dbh ); |
|
1040 } |
|
1041 if ( ! $success ) { |
|
834 $this->ready = false; |
1042 $this->ready = false; |
835 wp_load_translations_early(); |
1043 if ( ! did_action( 'template_redirect' ) ) { |
836 $this->bail( sprintf( __( '<h1>Can’t select database</h1> |
1044 wp_load_translations_early(); |
1045 $this->bail( sprintf( __( '<h1>Can’t select database</h1> |
|
837 <p>We were able to connect to the database server (which means your username and password is okay) but not able to select the <code>%1$s</code> database.</p> |
1046 <p>We were able to connect to the database server (which means your username and password is okay) but not able to select the <code>%1$s</code> database.</p> |
838 <ul> |
1047 <ul> |
839 <li>Are you sure it exists?</li> |
1048 <li>Are you sure it exists?</li> |
840 <li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li> |
1049 <li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li> |
841 <li>On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?</li> |
1050 <li>On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?</li> |
842 </ul> |
1051 </ul> |
843 <p>If you don\'t know how to set up a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="http://wordpress.org/support/">WordPress Support Forums</a>.</p>' ), htmlspecialchars( $db, ENT_QUOTES ), htmlspecialchars( $this->dbuser, ENT_QUOTES ) ), 'db_select_fail' ); |
1052 <p>If you don\'t know how to set up a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="https://wordpress.org/support/">WordPress Support Forums</a>.</p>' ), htmlspecialchars( $db, ENT_QUOTES ), htmlspecialchars( $this->dbuser, ENT_QUOTES ) ), 'db_select_fail' ); |
1053 } |
|
844 return; |
1054 return; |
845 } |
1055 } |
846 } |
1056 } |
847 |
1057 |
848 /** |
1058 /** |
864 _deprecated_function( __METHOD__, '3.6', 'wpdb::prepare() or esc_sql()' ); |
1074 _deprecated_function( __METHOD__, '3.6', 'wpdb::prepare() or esc_sql()' ); |
865 return addslashes( $string ); |
1075 return addslashes( $string ); |
866 } |
1076 } |
867 |
1077 |
868 /** |
1078 /** |
869 * Real escape, using mysql_real_escape_string() |
1079 * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string() |
870 * |
1080 * |
1081 * @see mysqli_real_escape_string() |
|
871 * @see mysql_real_escape_string() |
1082 * @see mysql_real_escape_string() |
872 * @since 2.8.0 |
1083 * @since 2.8.0 |
873 * @access private |
1084 * @access private |
874 * |
1085 * |
875 * @param string $string to escape |
1086 * @param string $string to escape |
876 * @return string escaped |
1087 * @return string escaped |
877 */ |
1088 */ |
878 function _real_escape( $string ) { |
1089 function _real_escape( $string ) { |
879 if ( $this->dbh ) |
1090 if ( $this->dbh ) { |
880 return mysql_real_escape_string( $string, $this->dbh ); |
1091 if ( $this->use_mysqli ) { |
1092 return mysqli_real_escape_string( $this->dbh, $string ); |
|
1093 } else { |
|
1094 return mysql_real_escape_string( $string, $this->dbh ); |
|
1095 } |
|
1096 } |
|
881 |
1097 |
882 $class = get_class( $this ); |
1098 $class = get_class( $this ); |
883 _doing_it_wrong( $class, "$class must set a database connection for use with escaping.", E_USER_NOTICE ); |
1099 if ( function_exists( '__' ) ) { |
1100 _doing_it_wrong( $class, sprintf( __( '%s must set a database connection for use with escaping.' ), $class ), E_USER_NOTICE ); |
|
1101 } else { |
|
1102 _doing_it_wrong( $class, sprintf( '%s must set a database connection for use with escaping.', $class ), E_USER_NOTICE ); |
|
1103 } |
|
884 return addslashes( $string ); |
1104 return addslashes( $string ); |
885 } |
1105 } |
886 |
1106 |
887 /** |
1107 /** |
888 * Escape data. Works on arrays. |
1108 * Escape data. Works on arrays. |
920 * @see esc_sql() |
1140 * @see esc_sql() |
921 * |
1141 * |
922 * @param mixed $data |
1142 * @param mixed $data |
923 * @return mixed |
1143 * @return mixed |
924 */ |
1144 */ |
925 function escape( $data ) { |
1145 public function escape( $data ) { |
926 if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) |
1146 if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) |
927 _deprecated_function( __METHOD__, '3.6', 'wpdb::prepare() or esc_sql()' ); |
1147 _deprecated_function( __METHOD__, '3.6', 'wpdb::prepare() or esc_sql()' ); |
928 if ( is_array( $data ) ) { |
1148 if ( is_array( $data ) ) { |
929 foreach ( $data as $k => $v ) { |
1149 foreach ( $data as $k => $v ) { |
930 if ( is_array( $v ) ) |
1150 if ( is_array( $v ) ) |
945 * @uses wpdb::_real_escape() |
1165 * @uses wpdb::_real_escape() |
946 * @since 2.3.0 |
1166 * @since 2.3.0 |
947 * @param string $string to escape |
1167 * @param string $string to escape |
948 * @return void |
1168 * @return void |
949 */ |
1169 */ |
950 function escape_by_ref( &$string ) { |
1170 public function escape_by_ref( &$string ) { |
951 if ( ! is_float( $string ) ) |
1171 if ( ! is_float( $string ) ) |
952 $string = $this->_real_escape( $string ); |
1172 $string = $this->_real_escape( $string ); |
953 } |
1173 } |
954 |
1174 |
955 /** |
1175 /** |
970 * |
1190 * |
971 * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}. |
1191 * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}. |
972 * |
1192 * |
973 * Both %d and %s should be left unquoted in the query string. |
1193 * Both %d and %s should be left unquoted in the query string. |
974 * |
1194 * |
975 * <code> |
1195 * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", 'foo', 1337 ) |
976 * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", 'foo', 1337 ) |
1196 * wpdb::prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' ); |
977 * wpdb::prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' ); |
|
978 * </code> |
|
979 * |
1197 * |
980 * @link http://php.net/sprintf Description of syntax. |
1198 * @link http://php.net/sprintf Description of syntax. |
981 * @since 2.3.0 |
1199 * @since 2.3.0 |
982 * |
1200 * |
983 * @param string $query Query statement with sprintf()-like placeholders |
1201 * @param string $query Query statement with sprintf()-like placeholders |
987 * @param mixed $args,... further variables to substitute into the query's placeholders if being called like |
1205 * @param mixed $args,... further variables to substitute into the query's placeholders if being called like |
988 * {@link http://php.net/sprintf sprintf()}. |
1206 * {@link http://php.net/sprintf sprintf()}. |
989 * @return null|false|string Sanitized query string, null if there is no query, false if there is an error and string |
1207 * @return null|false|string Sanitized query string, null if there is no query, false if there is an error and string |
990 * if there was something to prepare |
1208 * if there was something to prepare |
991 */ |
1209 */ |
992 function prepare( $query, $args ) { |
1210 public function prepare( $query, $args ) { |
993 if ( is_null( $query ) ) |
1211 if ( is_null( $query ) ) |
994 return; |
1212 return; |
1213 |
|
1214 // This is not meant to be foolproof -- but it will catch obviously incorrect usage. |
|
1215 if ( strpos( $query, '%' ) === false ) { |
|
1216 _doing_it_wrong( 'wpdb::prepare', sprintf( __( 'The query argument of %s must have a placeholder.' ), 'wpdb::prepare()' ), '3.9' ); |
|
1217 } |
|
995 |
1218 |
996 $args = func_get_args(); |
1219 $args = func_get_args(); |
997 array_shift( $args ); |
1220 array_shift( $args ); |
998 // If args were passed as an array (as in vsprintf), move them up |
1221 // If args were passed as an array (as in vsprintf), move them up |
999 if ( isset( $args[0] ) && is_array($args[0]) ) |
1222 if ( isset( $args[0] ) && is_array($args[0]) ) |
1005 array_walk( $args, array( $this, 'escape_by_ref' ) ); |
1228 array_walk( $args, array( $this, 'escape_by_ref' ) ); |
1006 return @vsprintf( $query, $args ); |
1229 return @vsprintf( $query, $args ); |
1007 } |
1230 } |
1008 |
1231 |
1009 /** |
1232 /** |
1233 * First half of escaping for LIKE special characters % and _ before preparing for MySQL. |
|
1234 * |
|
1235 * Use this only before wpdb::prepare() or esc_sql(). Reversing the order is very bad for security. |
|
1236 * |
|
1237 * Example Prepared Statement: |
|
1238 * $wild = '%'; |
|
1239 * $find = 'only 43% of planets'; |
|
1240 * $like = $wild . $wpdb->esc_like( $find ) . $wild; |
|
1241 * $sql = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like ); |
|
1242 * |
|
1243 * Example Escape Chain: |
|
1244 * $sql = esc_sql( $wpdb->esc_like( $input ) ); |
|
1245 * |
|
1246 * @since 4.0.0 |
|
1247 * @access public |
|
1248 * |
|
1249 * @param string $text The raw text to be escaped. The input typed by the user should have no |
|
1250 * extra or deleted slashes. |
|
1251 * @return string Text in the form of a LIKE phrase. The output is not SQL safe. Call $wpdb::prepare() |
|
1252 * or real_escape next. |
|
1253 */ |
|
1254 public function esc_like( $text ) { |
|
1255 return addcslashes( $text, '_%\\' ); |
|
1256 } |
|
1257 |
|
1258 /** |
|
1010 * Print SQL/DB error. |
1259 * Print SQL/DB error. |
1011 * |
1260 * |
1012 * @since 0.71 |
1261 * @since 0.71 |
1013 * @global array $EZSQL_ERROR Stores error information of query and error string |
1262 * @global array $EZSQL_ERROR Stores error information of query and error string |
1014 * |
1263 * |
1015 * @param string $str The error to display |
1264 * @param string $str The error to display |
1016 * @return bool False if the showing of errors is disabled. |
1265 * @return false|null False if the showing of errors is disabled. |
1017 */ |
1266 */ |
1018 function print_error( $str = '' ) { |
1267 public function print_error( $str = '' ) { |
1019 global $EZSQL_ERROR; |
1268 global $EZSQL_ERROR; |
1020 |
1269 |
1021 if ( !$str ) |
1270 if ( !$str ) { |
1022 $str = mysql_error( $this->dbh ); |
1271 if ( $this->use_mysqli ) { |
1272 $str = mysqli_error( $this->dbh ); |
|
1273 } else { |
|
1274 $str = mysql_error( $this->dbh ); |
|
1275 } |
|
1276 } |
|
1023 $EZSQL_ERROR[] = array( 'query' => $this->last_query, 'error_str' => $str ); |
1277 $EZSQL_ERROR[] = array( 'query' => $this->last_query, 'error_str' => $str ); |
1024 |
1278 |
1025 if ( $this->suppress_errors ) |
1279 if ( $this->suppress_errors ) |
1026 return false; |
1280 return false; |
1027 |
1281 |
1068 * @see wpdb::hide_errors() |
1322 * @see wpdb::hide_errors() |
1069 * |
1323 * |
1070 * @param bool $show Whether to show or hide errors |
1324 * @param bool $show Whether to show or hide errors |
1071 * @return bool Old value for showing errors. |
1325 * @return bool Old value for showing errors. |
1072 */ |
1326 */ |
1073 function show_errors( $show = true ) { |
1327 public function show_errors( $show = true ) { |
1074 $errors = $this->show_errors; |
1328 $errors = $this->show_errors; |
1075 $this->show_errors = $show; |
1329 $this->show_errors = $show; |
1076 return $errors; |
1330 return $errors; |
1077 } |
1331 } |
1078 |
1332 |
1084 * @since 0.71 |
1338 * @since 0.71 |
1085 * @see wpdb::show_errors() |
1339 * @see wpdb::show_errors() |
1086 * |
1340 * |
1087 * @return bool Whether showing of errors was active |
1341 * @return bool Whether showing of errors was active |
1088 */ |
1342 */ |
1089 function hide_errors() { |
1343 public function hide_errors() { |
1090 $show = $this->show_errors; |
1344 $show = $this->show_errors; |
1091 $this->show_errors = false; |
1345 $this->show_errors = false; |
1092 return $show; |
1346 return $show; |
1093 } |
1347 } |
1094 |
1348 |
1101 * @since 2.5.0 |
1355 * @since 2.5.0 |
1102 * @see wpdb::hide_errors() |
1356 * @see wpdb::hide_errors() |
1103 * @param bool $suppress Optional. New value. Defaults to true. |
1357 * @param bool $suppress Optional. New value. Defaults to true. |
1104 * @return bool Old value |
1358 * @return bool Old value |
1105 */ |
1359 */ |
1106 function suppress_errors( $suppress = true ) { |
1360 public function suppress_errors( $suppress = true ) { |
1107 $errors = $this->suppress_errors; |
1361 $errors = $this->suppress_errors; |
1108 $this->suppress_errors = (bool) $suppress; |
1362 $this->suppress_errors = (bool) $suppress; |
1109 return $errors; |
1363 return $errors; |
1110 } |
1364 } |
1111 |
1365 |
1113 * Kill cached query results. |
1367 * Kill cached query results. |
1114 * |
1368 * |
1115 * @since 0.71 |
1369 * @since 0.71 |
1116 * @return void |
1370 * @return void |
1117 */ |
1371 */ |
1118 function flush() { |
1372 public function flush() { |
1119 $this->last_result = array(); |
1373 $this->last_result = array(); |
1120 $this->col_info = null; |
1374 $this->col_info = null; |
1121 $this->last_query = null; |
1375 $this->last_query = null; |
1122 $this->rows_affected = $this->num_rows = 0; |
1376 $this->rows_affected = $this->num_rows = 0; |
1123 $this->last_error = ''; |
1377 $this->last_error = ''; |
1124 |
1378 |
1125 if ( is_resource( $this->result ) ) |
1379 if ( $this->use_mysqli && $this->result instanceof mysqli_result ) { |
1380 mysqli_free_result( $this->result ); |
|
1381 $this->result = null; |
|
1382 |
|
1383 // Sanity check before using the handle |
|
1384 if ( empty( $this->dbh ) || !( $this->dbh instanceof mysqli ) ) { |
|
1385 return; |
|
1386 } |
|
1387 |
|
1388 // Clear out any results from a multi-query |
|
1389 while ( mysqli_more_results( $this->dbh ) ) { |
|
1390 mysqli_next_result( $this->dbh ); |
|
1391 } |
|
1392 } elseif ( is_resource( $this->result ) ) { |
|
1126 mysql_free_result( $this->result ); |
1393 mysql_free_result( $this->result ); |
1127 } |
1394 } |
1128 |
1395 } |
1129 /** |
1396 |
1130 * Connect to and select database |
1397 /** |
1398 * Connect to and select database. |
|
1399 * |
|
1400 * If $allow_bail is false, the lack of database connection will need |
|
1401 * to be handled manually. |
|
1131 * |
1402 * |
1132 * @since 3.0.0 |
1403 * @since 3.0.0 |
1133 */ |
1404 * @since 3.9.0 $allow_bail parameter added. |
1134 function db_connect() { |
1405 * |
1406 * @param bool $allow_bail Optional. Allows the function to bail. Default true. |
|
1407 * @return null|bool True with a successful connection, false on failure. |
|
1408 */ |
|
1409 public function db_connect( $allow_bail = true ) { |
|
1135 |
1410 |
1136 $this->is_mysql = true; |
1411 $this->is_mysql = true; |
1137 |
1412 |
1413 /* |
|
1414 * Deprecated in 3.9+ when using MySQLi. No equivalent |
|
1415 * $new_link parameter exists for mysqli_* functions. |
|
1416 */ |
|
1138 $new_link = defined( 'MYSQL_NEW_LINK' ) ? MYSQL_NEW_LINK : true; |
1417 $new_link = defined( 'MYSQL_NEW_LINK' ) ? MYSQL_NEW_LINK : true; |
1139 $client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0; |
1418 $client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0; |
1140 |
1419 |
1141 if ( WP_DEBUG ) { |
1420 if ( $this->use_mysqli ) { |
1142 $this->dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags ); |
1421 $this->dbh = mysqli_init(); |
1422 |
|
1423 // mysqli_real_connect doesn't support the host param including a port or socket |
|
1424 // like mysql_connect does. This duplicates how mysql_connect detects a port and/or socket file. |
|
1425 $port = null; |
|
1426 $socket = null; |
|
1427 $host = $this->dbhost; |
|
1428 $port_or_socket = strstr( $host, ':' ); |
|
1429 if ( ! empty( $port_or_socket ) ) { |
|
1430 $host = substr( $host, 0, strpos( $host, ':' ) ); |
|
1431 $port_or_socket = substr( $port_or_socket, 1 ); |
|
1432 if ( 0 !== strpos( $port_or_socket, '/' ) ) { |
|
1433 $port = intval( $port_or_socket ); |
|
1434 $maybe_socket = strstr( $port_or_socket, ':' ); |
|
1435 if ( ! empty( $maybe_socket ) ) { |
|
1436 $socket = substr( $maybe_socket, 1 ); |
|
1437 } |
|
1438 } else { |
|
1439 $socket = $port_or_socket; |
|
1440 } |
|
1441 } |
|
1442 |
|
1443 if ( WP_DEBUG ) { |
|
1444 mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags ); |
|
1445 } else { |
|
1446 @mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags ); |
|
1447 } |
|
1448 |
|
1449 if ( $this->dbh->connect_errno ) { |
|
1450 $this->dbh = null; |
|
1451 |
|
1452 /* It's possible ext/mysqli is misconfigured. Fall back to ext/mysql if: |
|
1453 * - We haven't previously connected, and |
|
1454 * - WP_USE_EXT_MYSQL isn't set to false, and |
|
1455 * - ext/mysql is loaded. |
|
1456 */ |
|
1457 $attempt_fallback = true; |
|
1458 |
|
1459 if ( $this->has_connected ) { |
|
1460 $attempt_fallback = false; |
|
1461 } elseif ( defined( 'WP_USE_EXT_MYSQL' ) && ! WP_USE_EXT_MYSQL ) { |
|
1462 $attempt_fallback = false; |
|
1463 } elseif ( ! function_exists( 'mysql_connect' ) ) { |
|
1464 $attempt_fallback = false; |
|
1465 } |
|
1466 |
|
1467 if ( $attempt_fallback ) { |
|
1468 $this->use_mysqli = false; |
|
1469 $this->db_connect(); |
|
1470 } |
|
1471 } |
|
1143 } else { |
1472 } else { |
1144 $this->dbh = @mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags ); |
1473 if ( WP_DEBUG ) { |
1145 } |
1474 $this->dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags ); |
1146 |
1475 } else { |
1147 if ( !$this->dbh ) { |
1476 $this->dbh = @mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags ); |
1477 } |
|
1478 } |
|
1479 |
|
1480 if ( ! $this->dbh && $allow_bail ) { |
|
1148 wp_load_translations_early(); |
1481 wp_load_translations_early(); |
1482 |
|
1483 // Load custom DB error template, if present. |
|
1484 if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) { |
|
1485 require_once( WP_CONTENT_DIR . '/db-error.php' ); |
|
1486 die(); |
|
1487 } |
|
1488 |
|
1149 $this->bail( sprintf( __( " |
1489 $this->bail( sprintf( __( " |
1150 <h1>Error establishing a database connection</h1> |
1490 <h1>Error establishing a database connection</h1> |
1151 <p>This either means that the username and password information in your <code>wp-config.php</code> file is incorrect or we can't contact the database server at <code>%s</code>. This could mean your host's database server is down.</p> |
1491 <p>This either means that the username and password information in your <code>wp-config.php</code> file is incorrect or we can't contact the database server at <code>%s</code>. This could mean your host's database server is down.</p> |
1152 <ul> |
1492 <ul> |
1153 <li>Are you sure you have the correct username and password?</li> |
1493 <li>Are you sure you have the correct username and password?</li> |
1154 <li>Are you sure that you have typed the correct hostname?</li> |
1494 <li>Are you sure that you have typed the correct hostname?</li> |
1155 <li>Are you sure that the database server is running?</li> |
1495 <li>Are you sure that the database server is running?</li> |
1156 </ul> |
1496 </ul> |
1157 <p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='http://wordpress.org/support/'>WordPress Support Forums</a>.</p> |
1497 <p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='https://wordpress.org/support/'>WordPress Support Forums</a>.</p> |
1158 " ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' ); |
1498 " ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' ); |
1159 |
1499 |
1160 return; |
1500 return false; |
1161 } |
1501 } elseif ( $this->dbh ) { |
1162 |
1502 if ( ! $this->has_connected ) { |
1163 $this->set_charset( $this->dbh ); |
1503 $this->init_charset(); |
1164 |
1504 } |
1165 $this->ready = true; |
1505 |
1166 |
1506 $this->has_connected = true; |
1167 $this->select( $this->dbname, $this->dbh ); |
1507 |
1508 $this->set_charset( $this->dbh ); |
|
1509 |
|
1510 $this->ready = true; |
|
1511 $this->set_sql_mode(); |
|
1512 $this->select( $this->dbname, $this->dbh ); |
|
1513 |
|
1514 return true; |
|
1515 } |
|
1516 |
|
1517 return false; |
|
1518 } |
|
1519 |
|
1520 /** |
|
1521 * Check that the connection to the database is still up. If not, try to reconnect. |
|
1522 * |
|
1523 * If this function is unable to reconnect, it will forcibly die, or if after the |
|
1524 * the template_redirect hook has been fired, return false instead. |
|
1525 * |
|
1526 * If $allow_bail is false, the lack of database connection will need |
|
1527 * to be handled manually. |
|
1528 * |
|
1529 * @since 3.9.0 |
|
1530 * |
|
1531 * @param bool $allow_bail Optional. Allows the function to bail. Default true. |
|
1532 * @return bool|null True if the connection is up. |
|
1533 */ |
|
1534 public function check_connection( $allow_bail = true ) { |
|
1535 if ( $this->use_mysqli ) { |
|
1536 if ( @mysqli_ping( $this->dbh ) ) { |
|
1537 return true; |
|
1538 } |
|
1539 } else { |
|
1540 if ( @mysql_ping( $this->dbh ) ) { |
|
1541 return true; |
|
1542 } |
|
1543 } |
|
1544 |
|
1545 $error_reporting = false; |
|
1546 |
|
1547 // Disable warnings, as we don't want to see a multitude of "unable to connect" messages |
|
1548 if ( WP_DEBUG ) { |
|
1549 $error_reporting = error_reporting(); |
|
1550 error_reporting( $error_reporting & ~E_WARNING ); |
|
1551 } |
|
1552 |
|
1553 for ( $tries = 1; $tries <= $this->reconnect_retries; $tries++ ) { |
|
1554 // On the last try, re-enable warnings. We want to see a single instance of the |
|
1555 // "unable to connect" message on the bail() screen, if it appears. |
|
1556 if ( $this->reconnect_retries === $tries && WP_DEBUG ) { |
|
1557 error_reporting( $error_reporting ); |
|
1558 } |
|
1559 |
|
1560 if ( $this->db_connect( false ) ) { |
|
1561 if ( $error_reporting ) { |
|
1562 error_reporting( $error_reporting ); |
|
1563 } |
|
1564 |
|
1565 return true; |
|
1566 } |
|
1567 |
|
1568 sleep( 1 ); |
|
1569 } |
|
1570 |
|
1571 // If template_redirect has already happened, it's too late for wp_die()/dead_db(). |
|
1572 // Let's just return and hope for the best. |
|
1573 if ( did_action( 'template_redirect' ) ) { |
|
1574 return false; |
|
1575 } |
|
1576 |
|
1577 if ( ! $allow_bail ) { |
|
1578 return false; |
|
1579 } |
|
1580 |
|
1581 // We weren't able to reconnect, so we better bail. |
|
1582 $this->bail( sprintf( ( " |
|
1583 <h1>Error reconnecting to the database</h1> |
|
1584 <p>This means that we lost contact with the database server at <code>%s</code>. This could mean your host's database server is down.</p> |
|
1585 <ul> |
|
1586 <li>Are you sure that the database server is running?</li> |
|
1587 <li>Are you sure that the database server is not under particularly heavy load?</li> |
|
1588 </ul> |
|
1589 <p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='https://wordpress.org/support/'>WordPress Support Forums</a>.</p> |
|
1590 " ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' ); |
|
1591 |
|
1592 // Call dead_db() if bail didn't die, because this database is no more. It has ceased to be (at least temporarily). |
|
1593 dead_db(); |
|
1168 } |
1594 } |
1169 |
1595 |
1170 /** |
1596 /** |
1171 * Perform a MySQL database query, using current database connection. |
1597 * Perform a MySQL database query, using current database connection. |
1172 * |
1598 * |
1175 * @since 0.71 |
1601 * @since 0.71 |
1176 * |
1602 * |
1177 * @param string $query Database query |
1603 * @param string $query Database query |
1178 * @return int|false Number of rows affected/selected or false on error |
1604 * @return int|false Number of rows affected/selected or false on error |
1179 */ |
1605 */ |
1180 function query( $query ) { |
1606 public function query( $query ) { |
1181 if ( ! $this->ready ) |
1607 if ( ! $this->ready ) { |
1608 $this->check_current_query = true; |
|
1182 return false; |
1609 return false; |
1610 } |
|
1611 |
|
1183 /** |
1612 /** |
1184 * Filter the database query. |
1613 * Filter the database query. |
1185 * |
1614 * |
1186 * Some queries are made before the plugins have been loaded, and thus cannot be filtered with this method. |
1615 * Some queries are made before the plugins have been loaded, |
1616 * and thus cannot be filtered with this method. |
|
1187 * |
1617 * |
1188 * @since 2.1.0 |
1618 * @since 2.1.0 |
1619 * |
|
1189 * @param string $query Database query. |
1620 * @param string $query Database query. |
1190 */ |
1621 */ |
1191 $query = apply_filters( 'query', $query ); |
1622 $query = apply_filters( 'query', $query ); |
1192 |
1623 |
1193 $return_val = 0; |
|
1194 $this->flush(); |
1624 $this->flush(); |
1195 |
1625 |
1196 // Log how the function was called |
1626 // Log how the function was called |
1197 $this->func_call = "\$db->query(\"$query\")"; |
1627 $this->func_call = "\$db->query(\"$query\")"; |
1198 |
1628 |
1629 // If we're writing to the database, make sure the query will write safely. |
|
1630 if ( $this->check_current_query && ! $this->check_ascii( $query ) ) { |
|
1631 $stripped_query = $this->strip_invalid_text_from_query( $query ); |
|
1632 // strip_invalid_text_from_query() can perform queries, so we need |
|
1633 // to flush again, just to make sure everything is clear. |
|
1634 $this->flush(); |
|
1635 if ( $stripped_query !== $query ) { |
|
1636 $this->insert_id = 0; |
|
1637 return false; |
|
1638 } |
|
1639 } |
|
1640 |
|
1641 $this->check_current_query = true; |
|
1642 |
|
1199 // Keep track of the last query for debug.. |
1643 // Keep track of the last query for debug.. |
1200 $this->last_query = $query; |
1644 $this->last_query = $query; |
1201 |
1645 |
1202 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) |
1646 $this->_do_query( $query ); |
1203 $this->timer_start(); |
1647 |
1204 |
1648 // MySQL server has gone away, try to reconnect |
1205 $this->result = @mysql_query( $query, $this->dbh ); |
1649 $mysql_errno = 0; |
1206 $this->num_queries++; |
1650 if ( ! empty( $this->dbh ) ) { |
1207 |
1651 if ( $this->use_mysqli ) { |
1208 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) |
1652 $mysql_errno = mysqli_errno( $this->dbh ); |
1209 $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); |
1653 } else { |
1654 $mysql_errno = mysql_errno( $this->dbh ); |
|
1655 } |
|
1656 } |
|
1657 |
|
1658 if ( empty( $this->dbh ) || 2006 == $mysql_errno ) { |
|
1659 if ( $this->check_connection() ) { |
|
1660 $this->_do_query( $query ); |
|
1661 } else { |
|
1662 $this->insert_id = 0; |
|
1663 return false; |
|
1664 } |
|
1665 } |
|
1210 |
1666 |
1211 // If there is an error then take note of it.. |
1667 // If there is an error then take note of it.. |
1212 if ( $this->last_error = mysql_error( $this->dbh ) ) { |
1668 if ( $this->use_mysqli ) { |
1669 $this->last_error = mysqli_error( $this->dbh ); |
|
1670 } else { |
|
1671 $this->last_error = mysql_error( $this->dbh ); |
|
1672 } |
|
1673 |
|
1674 if ( $this->last_error ) { |
|
1213 // Clear insert_id on a subsequent failed insert. |
1675 // Clear insert_id on a subsequent failed insert. |
1214 if ( $this->insert_id && preg_match( '/^\s*(insert|replace)\s/i', $query ) ) |
1676 if ( $this->insert_id && preg_match( '/^\s*(insert|replace)\s/i', $query ) ) |
1215 $this->insert_id = 0; |
1677 $this->insert_id = 0; |
1216 |
1678 |
1217 $this->print_error(); |
1679 $this->print_error(); |
1219 } |
1681 } |
1220 |
1682 |
1221 if ( preg_match( '/^\s*(create|alter|truncate|drop)\s/i', $query ) ) { |
1683 if ( preg_match( '/^\s*(create|alter|truncate|drop)\s/i', $query ) ) { |
1222 $return_val = $this->result; |
1684 $return_val = $this->result; |
1223 } elseif ( preg_match( '/^\s*(insert|delete|update|replace)\s/i', $query ) ) { |
1685 } elseif ( preg_match( '/^\s*(insert|delete|update|replace)\s/i', $query ) ) { |
1224 $this->rows_affected = mysql_affected_rows( $this->dbh ); |
1686 if ( $this->use_mysqli ) { |
1687 $this->rows_affected = mysqli_affected_rows( $this->dbh ); |
|
1688 } else { |
|
1689 $this->rows_affected = mysql_affected_rows( $this->dbh ); |
|
1690 } |
|
1225 // Take note of the insert_id |
1691 // Take note of the insert_id |
1226 if ( preg_match( '/^\s*(insert|replace)\s/i', $query ) ) { |
1692 if ( preg_match( '/^\s*(insert|replace)\s/i', $query ) ) { |
1227 $this->insert_id = mysql_insert_id($this->dbh); |
1693 if ( $this->use_mysqli ) { |
1694 $this->insert_id = mysqli_insert_id( $this->dbh ); |
|
1695 } else { |
|
1696 $this->insert_id = mysql_insert_id( $this->dbh ); |
|
1697 } |
|
1228 } |
1698 } |
1229 // Return number of rows affected |
1699 // Return number of rows affected |
1230 $return_val = $this->rows_affected; |
1700 $return_val = $this->rows_affected; |
1231 } else { |
1701 } else { |
1232 $num_rows = 0; |
1702 $num_rows = 0; |
1233 while ( $row = @mysql_fetch_object( $this->result ) ) { |
1703 if ( $this->use_mysqli && $this->result instanceof mysqli_result ) { |
1234 $this->last_result[$num_rows] = $row; |
1704 while ( $row = @mysqli_fetch_object( $this->result ) ) { |
1235 $num_rows++; |
1705 $this->last_result[$num_rows] = $row; |
1706 $num_rows++; |
|
1707 } |
|
1708 } elseif ( is_resource( $this->result ) ) { |
|
1709 while ( $row = @mysql_fetch_object( $this->result ) ) { |
|
1710 $this->last_result[$num_rows] = $row; |
|
1711 $num_rows++; |
|
1712 } |
|
1236 } |
1713 } |
1237 |
1714 |
1238 // Log number of rows the query returned |
1715 // Log number of rows the query returned |
1239 // and return number of rows selected |
1716 // and return number of rows selected |
1240 $this->num_rows = $num_rows; |
1717 $this->num_rows = $num_rows; |
1243 |
1720 |
1244 return $return_val; |
1721 return $return_val; |
1245 } |
1722 } |
1246 |
1723 |
1247 /** |
1724 /** |
1725 * Internal function to perform the mysql_query() call. |
|
1726 * |
|
1727 * @since 3.9.0 |
|
1728 * |
|
1729 * @access private |
|
1730 * @see wpdb::query() |
|
1731 * |
|
1732 * @param string $query The query to run. |
|
1733 */ |
|
1734 private function _do_query( $query ) { |
|
1735 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { |
|
1736 $this->timer_start(); |
|
1737 } |
|
1738 |
|
1739 if ( $this->use_mysqli ) { |
|
1740 $this->result = @mysqli_query( $this->dbh, $query ); |
|
1741 } else { |
|
1742 $this->result = @mysql_query( $query, $this->dbh ); |
|
1743 } |
|
1744 $this->num_queries++; |
|
1745 |
|
1746 if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { |
|
1747 $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() ); |
|
1748 } |
|
1749 } |
|
1750 |
|
1751 /** |
|
1248 * Insert a row into a table. |
1752 * Insert a row into a table. |
1249 * |
1753 * |
1250 * <code> |
1754 * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 'bar' ) ) |
1251 * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 'bar' ) ) |
1755 * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) |
1252 * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) |
|
1253 * </code> |
|
1254 * |
1756 * |
1255 * @since 2.5.0 |
1757 * @since 2.5.0 |
1256 * @see wpdb::prepare() |
1758 * @see wpdb::prepare() |
1257 * @see wpdb::$field_types |
1759 * @see wpdb::$field_types |
1258 * @see wp_set_wpdb_vars() |
1760 * @see wp_set_wpdb_vars() |
1261 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). |
1763 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). |
1262 * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data. If string, that format will be used for all of the values in $data. |
1764 * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data. If string, that format will be used for all of the values in $data. |
1263 * A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
1765 * A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
1264 * @return int|false The number of rows inserted, or false on error. |
1766 * @return int|false The number of rows inserted, or false on error. |
1265 */ |
1767 */ |
1266 function insert( $table, $data, $format = null ) { |
1768 public function insert( $table, $data, $format = null ) { |
1267 return $this->_insert_replace_helper( $table, $data, $format, 'INSERT' ); |
1769 return $this->_insert_replace_helper( $table, $data, $format, 'INSERT' ); |
1268 } |
1770 } |
1269 |
1771 |
1270 /** |
1772 /** |
1271 * Replace a row into a table. |
1773 * Replace a row into a table. |
1272 * |
1774 * |
1273 * <code> |
1775 * wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 'bar' ) ) |
1274 * wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 'bar' ) ) |
1776 * wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) |
1275 * wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) ) |
|
1276 * </code> |
|
1277 * |
1777 * |
1278 * @since 3.0.0 |
1778 * @since 3.0.0 |
1279 * @see wpdb::prepare() |
1779 * @see wpdb::prepare() |
1280 * @see wpdb::$field_types |
1780 * @see wpdb::$field_types |
1281 * @see wp_set_wpdb_vars() |
1781 * @see wp_set_wpdb_vars() |
1284 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). |
1784 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). |
1285 * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data. If string, that format will be used for all of the values in $data. |
1785 * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data. If string, that format will be used for all of the values in $data. |
1286 * A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
1786 * A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
1287 * @return int|false The number of rows affected, or false on error. |
1787 * @return int|false The number of rows affected, or false on error. |
1288 */ |
1788 */ |
1289 function replace( $table, $data, $format = null ) { |
1789 public function replace( $table, $data, $format = null ) { |
1290 return $this->_insert_replace_helper( $table, $data, $format, 'REPLACE' ); |
1790 return $this->_insert_replace_helper( $table, $data, $format, 'REPLACE' ); |
1291 } |
1791 } |
1292 |
1792 |
1293 /** |
1793 /** |
1294 * Helper function for insert and replace. |
1794 * Helper function for insert and replace. |
1307 * A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
1807 * A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
1308 * @param string $type Optional. What type of operation is this? INSERT or REPLACE. Defaults to INSERT. |
1808 * @param string $type Optional. What type of operation is this? INSERT or REPLACE. Defaults to INSERT. |
1309 * @return int|false The number of rows affected, or false on error. |
1809 * @return int|false The number of rows affected, or false on error. |
1310 */ |
1810 */ |
1311 function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) { |
1811 function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) { |
1312 if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) ) |
1812 $this->insert_id = 0; |
1813 |
|
1814 if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) ) { |
|
1313 return false; |
1815 return false; |
1314 $this->insert_id = 0; |
1816 } |
1315 $formats = $format = (array) $format; |
1817 |
1316 $fields = array_keys( $data ); |
1818 $data = $this->process_fields( $table, $data, $format ); |
1317 $formatted_fields = array(); |
1819 if ( false === $data ) { |
1318 foreach ( $fields as $field ) { |
1820 return false; |
1319 if ( !empty( $format ) ) |
1821 } |
1320 $form = ( $form = array_shift( $formats ) ) ? $form : $format[0]; |
1822 |
1321 elseif ( isset( $this->field_types[$field] ) ) |
1823 $formats = $values = array(); |
1322 $form = $this->field_types[$field]; |
1824 foreach ( $data as $value ) { |
1323 else |
1825 $formats[] = $value['format']; |
1324 $form = '%s'; |
1826 $values[] = $value['value']; |
1325 $formatted_fields[] = $form; |
1827 } |
1326 } |
1828 |
1327 $sql = "{$type} INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES (" . implode( ",", $formatted_fields ) . ")"; |
1829 $fields = '`' . implode( '`, `', array_keys( $data ) ) . '`'; |
1328 return $this->query( $this->prepare( $sql, $data ) ); |
1830 $formats = implode( ', ', $formats ); |
1831 |
|
1832 $sql = "$type INTO `$table` ($fields) VALUES ($formats)"; |
|
1833 |
|
1834 $this->check_current_query = false; |
|
1835 return $this->query( $this->prepare( $sql, $values ) ); |
|
1329 } |
1836 } |
1330 |
1837 |
1331 /** |
1838 /** |
1332 * Update a row in the table |
1839 * Update a row in the table |
1333 * |
1840 * |
1334 * <code> |
1841 * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 'bar' ), array( 'ID' => 1 ) ) |
1335 * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 'bar' ), array( 'ID' => 1 ) ) |
1842 * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) ) |
1336 * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) ) |
|
1337 * </code> |
|
1338 * |
1843 * |
1339 * @since 2.5.0 |
1844 * @since 2.5.0 |
1340 * @see wpdb::prepare() |
1845 * @see wpdb::prepare() |
1341 * @see wpdb::$field_types |
1846 * @see wpdb::$field_types |
1342 * @see wp_set_wpdb_vars() |
1847 * @see wp_set_wpdb_vars() |
1347 * @param array|string $format Optional. An array of formats to be mapped to each of the values in $data. If string, that format will be used for all of the values in $data. |
1852 * @param array|string $format Optional. An array of formats to be mapped to each of the values in $data. If string, that format will be used for all of the values in $data. |
1348 * A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
1853 * A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types. |
1349 * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where. If string, that format will be used for all of the items in $where. A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $where will be treated as strings. |
1854 * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where. If string, that format will be used for all of the items in $where. A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $where will be treated as strings. |
1350 * @return int|false The number of rows updated, or false on error. |
1855 * @return int|false The number of rows updated, or false on error. |
1351 */ |
1856 */ |
1352 function update( $table, $data, $where, $format = null, $where_format = null ) { |
1857 public function update( $table, $data, $where, $format = null, $where_format = null ) { |
1353 if ( ! is_array( $data ) || ! is_array( $where ) ) |
1858 if ( ! is_array( $data ) || ! is_array( $where ) ) { |
1354 return false; |
1859 return false; |
1355 |
1860 } |
1356 $formats = $format = (array) $format; |
1861 |
1357 $bits = $wheres = array(); |
1862 $data = $this->process_fields( $table, $data, $format ); |
1358 foreach ( (array) array_keys( $data ) as $field ) { |
1863 if ( false === $data ) { |
1359 if ( !empty( $format ) ) |
1864 return false; |
1360 $form = ( $form = array_shift( $formats ) ) ? $form : $format[0]; |
1865 } |
1361 elseif ( isset($this->field_types[$field]) ) |
1866 $where = $this->process_fields( $table, $where, $where_format ); |
1362 $form = $this->field_types[$field]; |
1867 if ( false === $where ) { |
1363 else |
1868 return false; |
1364 $form = '%s'; |
1869 } |
1365 $bits[] = "`$field` = {$form}"; |
1870 |
1366 } |
1871 $fields = $conditions = $values = array(); |
1367 |
1872 foreach ( $data as $field => $value ) { |
1368 $where_formats = $where_format = (array) $where_format; |
1873 $fields[] = "`$field` = " . $value['format']; |
1369 foreach ( (array) array_keys( $where ) as $field ) { |
1874 $values[] = $value['value']; |
1370 if ( !empty( $where_format ) ) |
1875 } |
1371 $form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[0]; |
1876 foreach ( $where as $field => $value ) { |
1372 elseif ( isset( $this->field_types[$field] ) ) |
1877 $conditions[] = "`$field` = " . $value['format']; |
1373 $form = $this->field_types[$field]; |
1878 $values[] = $value['value']; |
1374 else |
1879 } |
1375 $form = '%s'; |
1880 |
1376 $wheres[] = "`$field` = {$form}"; |
1881 $fields = implode( ', ', $fields ); |
1377 } |
1882 $conditions = implode( ' AND ', $conditions ); |
1378 |
1883 |
1379 $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres ); |
1884 $sql = "UPDATE `$table` SET $fields WHERE $conditions"; |
1380 return $this->query( $this->prepare( $sql, array_merge( array_values( $data ), array_values( $where ) ) ) ); |
1885 |
1886 $this->check_current_query = false; |
|
1887 return $this->query( $this->prepare( $sql, $values ) ); |
|
1381 } |
1888 } |
1382 |
1889 |
1383 /** |
1890 /** |
1384 * Delete a row in the table |
1891 * Delete a row in the table |
1385 * |
1892 * |
1386 * <code> |
1893 * wpdb::delete( 'table', array( 'ID' => 1 ) ) |
1387 * wpdb::delete( 'table', array( 'ID' => 1 ) ) |
1894 * wpdb::delete( 'table', array( 'ID' => 1 ), array( '%d' ) ) |
1388 * wpdb::delete( 'table', array( 'ID' => 1 ), array( '%d' ) ) |
|
1389 * </code> |
|
1390 * |
1895 * |
1391 * @since 3.4.0 |
1896 * @since 3.4.0 |
1392 * @see wpdb::prepare() |
1897 * @see wpdb::prepare() |
1393 * @see wpdb::$field_types |
1898 * @see wpdb::$field_types |
1394 * @see wp_set_wpdb_vars() |
1899 * @see wp_set_wpdb_vars() |
1396 * @param string $table table name |
1901 * @param string $table table name |
1397 * @param array $where A named array of WHERE clauses (in column => value pairs). Multiple clauses will be joined with ANDs. Both $where columns and $where values should be "raw". |
1902 * @param array $where A named array of WHERE clauses (in column => value pairs). Multiple clauses will be joined with ANDs. Both $where columns and $where values should be "raw". |
1398 * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where. If string, that format will be used for all of the items in $where. A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $where will be treated as strings unless otherwise specified in wpdb::$field_types. |
1903 * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where. If string, that format will be used for all of the items in $where. A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $where will be treated as strings unless otherwise specified in wpdb::$field_types. |
1399 * @return int|false The number of rows updated, or false on error. |
1904 * @return int|false The number of rows updated, or false on error. |
1400 */ |
1905 */ |
1401 function delete( $table, $where, $where_format = null ) { |
1906 public function delete( $table, $where, $where_format = null ) { |
1402 if ( ! is_array( $where ) ) |
1907 if ( ! is_array( $where ) ) { |
1403 return false; |
1908 return false; |
1404 |
1909 } |
1405 $bits = $wheres = array(); |
1910 |
1406 |
1911 $where = $this->process_fields( $table, $where, $where_format ); |
1407 $where_formats = $where_format = (array) $where_format; |
1912 if ( false === $where ) { |
1408 |
1913 return false; |
1409 foreach ( array_keys( $where ) as $field ) { |
1914 } |
1410 if ( !empty( $where_format ) ) { |
1915 |
1411 $form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[0]; |
1916 $conditions = $values = array(); |
1917 foreach ( $where as $field => $value ) { |
|
1918 $conditions[] = "`$field` = " . $value['format']; |
|
1919 $values[] = $value['value']; |
|
1920 } |
|
1921 |
|
1922 $conditions = implode( ' AND ', $conditions ); |
|
1923 |
|
1924 $sql = "DELETE FROM `$table` WHERE $conditions"; |
|
1925 |
|
1926 $this->check_current_query = false; |
|
1927 return $this->query( $this->prepare( $sql, $values ) ); |
|
1928 } |
|
1929 |
|
1930 /** |
|
1931 * Processes arrays of field/value pairs and field formats. |
|
1932 * |
|
1933 * This is a helper method for wpdb's CRUD methods, which take field/value |
|
1934 * pairs for inserts, updates, and where clauses. This method first pairs |
|
1935 * each value with a format. Then it determines the charset of that field, |
|
1936 * using that to determine if any invalid text would be stripped. If text is |
|
1937 * stripped, then field processing is rejected and the query fails. |
|
1938 * |
|
1939 * @since 4.2.0 |
|
1940 * @access protected |
|
1941 * |
|
1942 * @param string $table Table name. |
|
1943 * @param array $data Field/value pair. |
|
1944 * @param mixed $format Format for each field. |
|
1945 * @return array|bool Returns an array of fields that contain paired values |
|
1946 * and formats. Returns false for invalid values. |
|
1947 */ |
|
1948 protected function process_fields( $table, $data, $format ) { |
|
1949 $data = $this->process_field_formats( $data, $format ); |
|
1950 if ( false === $data ) { |
|
1951 return false; |
|
1952 } |
|
1953 |
|
1954 $data = $this->process_field_charsets( $data, $table ); |
|
1955 if ( false === $data ) { |
|
1956 return false; |
|
1957 } |
|
1958 |
|
1959 $data = $this->process_field_lengths( $data, $table ); |
|
1960 if ( false === $data ) { |
|
1961 return false; |
|
1962 } |
|
1963 |
|
1964 $converted_data = $this->strip_invalid_text( $data ); |
|
1965 |
|
1966 if ( $data !== $converted_data ) { |
|
1967 return false; |
|
1968 } |
|
1969 |
|
1970 return $data; |
|
1971 } |
|
1972 |
|
1973 /** |
|
1974 * Prepares arrays of value/format pairs as passed to wpdb CRUD methods. |
|
1975 * |
|
1976 * @since 4.2.0 |
|
1977 * @access protected |
|
1978 * |
|
1979 * @param array $data Array of fields to values. |
|
1980 * @param mixed $format Formats to be mapped to the values in $data. |
|
1981 * @return array Array, keyed by field names with values being an array |
|
1982 * of 'value' and 'format' keys. |
|
1983 */ |
|
1984 protected function process_field_formats( $data, $format ) { |
|
1985 $formats = $original_formats = (array) $format; |
|
1986 |
|
1987 foreach ( $data as $field => $value ) { |
|
1988 $value = array( |
|
1989 'value' => $value, |
|
1990 'format' => '%s', |
|
1991 ); |
|
1992 |
|
1993 if ( ! empty( $format ) ) { |
|
1994 $value['format'] = array_shift( $formats ); |
|
1995 if ( ! $value['format'] ) { |
|
1996 $value['format'] = reset( $original_formats ); |
|
1997 } |
|
1412 } elseif ( isset( $this->field_types[ $field ] ) ) { |
1998 } elseif ( isset( $this->field_types[ $field ] ) ) { |
1413 $form = $this->field_types[ $field ]; |
1999 $value['format'] = $this->field_types[ $field ]; |
2000 } |
|
2001 |
|
2002 $data[ $field ] = $value; |
|
2003 } |
|
2004 |
|
2005 return $data; |
|
2006 } |
|
2007 |
|
2008 /** |
|
2009 * Adds field charsets to field/value/format arrays generated by |
|
2010 * the wpdb::process_field_formats() method. |
|
2011 * |
|
2012 * @since 4.2.0 |
|
2013 * @access protected |
|
2014 * |
|
2015 * @param array $data As it comes from the wpdb::process_field_formats() method. |
|
2016 * @param string $table Table name. |
|
2017 * @return The same array as $data with additional 'charset' keys. |
|
2018 */ |
|
2019 protected function process_field_charsets( $data, $table ) { |
|
2020 foreach ( $data as $field => $value ) { |
|
2021 if ( '%d' === $value['format'] || '%f' === $value['format'] ) { |
|
2022 // We can skip this field if we know it isn't a string. |
|
2023 // This checks %d/%f versus ! %s because it's sprintf() could take more. |
|
2024 $value['charset'] = false; |
|
1414 } else { |
2025 } else { |
1415 $form = '%s'; |
2026 $value['charset'] = $this->get_col_charset( $table, $field ); |
1416 } |
2027 if ( is_wp_error( $value['charset'] ) ) { |
1417 |
2028 return false; |
1418 $wheres[] = "$field = $form"; |
2029 } |
1419 } |
2030 } |
1420 |
2031 |
1421 $sql = "DELETE FROM $table WHERE " . implode( ' AND ', $wheres ); |
2032 $data[ $field ] = $value; |
1422 return $this->query( $this->prepare( $sql, $where ) ); |
2033 } |
1423 } |
2034 |
1424 |
2035 return $data; |
2036 } |
|
2037 |
|
2038 /** |
|
2039 * For string fields, record the maximum string length that field can safely save. |
|
2040 * |
|
2041 * @since 4.2.1 |
|
2042 * @access protected |
|
2043 * |
|
2044 * @param array $data As it comes from the wpdb::process_field_charsets() method. |
|
2045 * @param string $table Table name. |
|
2046 * @return array|False The same array as $data with additional 'length' keys, or false if |
|
2047 * any of the values were too long for their corresponding field. |
|
2048 */ |
|
2049 protected function process_field_lengths( $data, $table ) { |
|
2050 foreach ( $data as $field => $value ) { |
|
2051 if ( '%d' === $value['format'] || '%f' === $value['format'] ) { |
|
2052 // We can skip this field if we know it isn't a string. |
|
2053 // This checks %d/%f versus ! %s because it's sprintf() could take more. |
|
2054 $value['length'] = false; |
|
2055 } else { |
|
2056 $value['length'] = $this->get_col_length( $table, $field ); |
|
2057 if ( is_wp_error( $value['length'] ) ) { |
|
2058 return false; |
|
2059 } |
|
2060 } |
|
2061 |
|
2062 $data[ $field ] = $value; |
|
2063 } |
|
2064 |
|
2065 return $data; |
|
2066 } |
|
1425 |
2067 |
1426 /** |
2068 /** |
1427 * Retrieve one variable from the database. |
2069 * Retrieve one variable from the database. |
1428 * |
2070 * |
1429 * Executes a SQL query and returns the value from the SQL result. |
2071 * Executes a SQL query and returns the value from the SQL result. |
1435 * @param string|null $query Optional. SQL query. Defaults to null, use the result from the previous query. |
2077 * @param string|null $query Optional. SQL query. Defaults to null, use the result from the previous query. |
1436 * @param int $x Optional. Column of value to return. Indexed from 0. |
2078 * @param int $x Optional. Column of value to return. Indexed from 0. |
1437 * @param int $y Optional. Row of value to return. Indexed from 0. |
2079 * @param int $y Optional. Row of value to return. Indexed from 0. |
1438 * @return string|null Database query result (as string), or null on failure |
2080 * @return string|null Database query result (as string), or null on failure |
1439 */ |
2081 */ |
1440 function get_var( $query = null, $x = 0, $y = 0 ) { |
2082 public function get_var( $query = null, $x = 0, $y = 0 ) { |
1441 $this->func_call = "\$db->get_var(\"$query\", $x, $y)"; |
2083 $this->func_call = "\$db->get_var(\"$query\", $x, $y)"; |
1442 if ( $query ) |
2084 |
2085 if ( $this->check_safe_collation( $query ) ) { |
|
2086 $this->check_current_query = false; |
|
2087 } |
|
2088 |
|
2089 if ( $query ) { |
|
1443 $this->query( $query ); |
2090 $this->query( $query ); |
2091 } |
|
1444 |
2092 |
1445 // Extract var out of cached results based x,y vals |
2093 // Extract var out of cached results based x,y vals |
1446 if ( !empty( $this->last_result[$y] ) ) { |
2094 if ( !empty( $this->last_result[$y] ) ) { |
1447 $values = array_values( get_object_vars( $this->last_result[$y] ) ); |
2095 $values = array_values( get_object_vars( $this->last_result[$y] ) ); |
1448 } |
2096 } |
1462 * @param string $output Optional. one of ARRAY_A | ARRAY_N | OBJECT constants. Return an associative array (column => value, ...), |
2110 * @param string $output Optional. one of ARRAY_A | ARRAY_N | OBJECT constants. Return an associative array (column => value, ...), |
1463 * a numerically indexed array (0 => value, ...) or an object ( ->column = value ), respectively. |
2111 * a numerically indexed array (0 => value, ...) or an object ( ->column = value ), respectively. |
1464 * @param int $y Optional. Row to return. Indexed from 0. |
2112 * @param int $y Optional. Row to return. Indexed from 0. |
1465 * @return mixed Database query result in format specified by $output or null on failure |
2113 * @return mixed Database query result in format specified by $output or null on failure |
1466 */ |
2114 */ |
1467 function get_row( $query = null, $output = OBJECT, $y = 0 ) { |
2115 public function get_row( $query = null, $output = OBJECT, $y = 0 ) { |
1468 $this->func_call = "\$db->get_row(\"$query\",$output,$y)"; |
2116 $this->func_call = "\$db->get_row(\"$query\",$output,$y)"; |
1469 if ( $query ) |
2117 |
2118 if ( $this->check_safe_collation( $query ) ) { |
|
2119 $this->check_current_query = false; |
|
2120 } |
|
2121 |
|
2122 if ( $query ) { |
|
1470 $this->query( $query ); |
2123 $this->query( $query ); |
1471 else |
2124 } else { |
1472 return null; |
2125 return null; |
2126 } |
|
1473 |
2127 |
1474 if ( !isset( $this->last_result[$y] ) ) |
2128 if ( !isset( $this->last_result[$y] ) ) |
1475 return null; |
2129 return null; |
1476 |
2130 |
1477 if ( $output == OBJECT ) { |
2131 if ( $output == OBJECT ) { |
1478 return $this->last_result[$y] ? $this->last_result[$y] : null; |
2132 return $this->last_result[$y] ? $this->last_result[$y] : null; |
1479 } elseif ( $output == ARRAY_A ) { |
2133 } elseif ( $output == ARRAY_A ) { |
1480 return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null; |
2134 return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null; |
1481 } elseif ( $output == ARRAY_N ) { |
2135 } elseif ( $output == ARRAY_N ) { |
1482 return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null; |
2136 return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null; |
2137 } elseif ( strtoupper( $output ) === OBJECT ) { |
|
2138 // Back compat for OBJECT being previously case insensitive. |
|
2139 return $this->last_result[$y] ? $this->last_result[$y] : null; |
|
1483 } else { |
2140 } else { |
1484 $this->print_error( " \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N" ); |
2141 $this->print_error( " \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N" ); |
1485 } |
2142 } |
1486 } |
2143 } |
1487 |
2144 |
1496 * |
2153 * |
1497 * @param string|null $query Optional. SQL query. Defaults to previous query. |
2154 * @param string|null $query Optional. SQL query. Defaults to previous query. |
1498 * @param int $x Optional. Column to return. Indexed from 0. |
2155 * @param int $x Optional. Column to return. Indexed from 0. |
1499 * @return array Database query result. Array indexed from 0 by SQL result row number. |
2156 * @return array Database query result. Array indexed from 0 by SQL result row number. |
1500 */ |
2157 */ |
1501 function get_col( $query = null , $x = 0 ) { |
2158 public function get_col( $query = null , $x = 0 ) { |
1502 if ( $query ) |
2159 if ( $this->check_safe_collation( $query ) ) { |
2160 $this->check_current_query = false; |
|
2161 } |
|
2162 |
|
2163 if ( $query ) { |
|
1503 $this->query( $query ); |
2164 $this->query( $query ); |
2165 } |
|
1504 |
2166 |
1505 $new_array = array(); |
2167 $new_array = array(); |
1506 // Extract the column values |
2168 // Extract the column values |
1507 for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) { |
2169 for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) { |
1508 $new_array[$i] = $this->get_var( null, $x, $i ); |
2170 $new_array[$i] = $this->get_var( null, $x, $i ); |
1521 * @param string $output Optional. Any of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants. With one of the first three, return an array of rows indexed from 0 by SQL result row number. |
2183 * @param string $output Optional. Any of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants. With one of the first three, return an array of rows indexed from 0 by SQL result row number. |
1522 * Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively. |
2184 * Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively. |
1523 * With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value. Duplicate keys are discarded. |
2185 * With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value. Duplicate keys are discarded. |
1524 * @return mixed Database query results |
2186 * @return mixed Database query results |
1525 */ |
2187 */ |
1526 function get_results( $query = null, $output = OBJECT ) { |
2188 public function get_results( $query = null, $output = OBJECT ) { |
1527 $this->func_call = "\$db->get_results(\"$query\", $output)"; |
2189 $this->func_call = "\$db->get_results(\"$query\", $output)"; |
1528 |
2190 |
1529 if ( $query ) |
2191 if ( $this->check_safe_collation( $query ) ) { |
2192 $this->check_current_query = false; |
|
2193 } |
|
2194 |
|
2195 if ( $query ) { |
|
1530 $this->query( $query ); |
2196 $this->query( $query ); |
1531 else |
2197 } else { |
1532 return null; |
2198 return null; |
2199 } |
|
1533 |
2200 |
1534 $new_array = array(); |
2201 $new_array = array(); |
1535 if ( $output == OBJECT ) { |
2202 if ( $output == OBJECT ) { |
1536 // Return an integer-keyed array of row objects |
2203 // Return an integer-keyed array of row objects |
1537 return $this->last_result; |
2204 return $this->last_result; |
1557 $new_array[] = get_object_vars( $row ); |
2224 $new_array[] = get_object_vars( $row ); |
1558 } |
2225 } |
1559 } |
2226 } |
1560 } |
2227 } |
1561 return $new_array; |
2228 return $new_array; |
2229 } elseif ( strtoupper( $output ) === OBJECT ) { |
|
2230 // Back compat for OBJECT being previously case insensitive. |
|
2231 return $this->last_result; |
|
1562 } |
2232 } |
1563 return null; |
2233 return null; |
2234 } |
|
2235 |
|
2236 /** |
|
2237 * Retrieves the character set for the given table. |
|
2238 * |
|
2239 * @since 4.2.0 |
|
2240 * @access protected |
|
2241 * |
|
2242 * @param string $table Table name. |
|
2243 * @return string|WP_Error Table character set, WP_Error object if it couldn't be found. |
|
2244 */ |
|
2245 protected function get_table_charset( $table ) { |
|
2246 $tablekey = strtolower( $table ); |
|
2247 |
|
2248 /** |
|
2249 * Filter the table charset value before the DB is checked. |
|
2250 * |
|
2251 * Passing a non-null value to the filter will effectively short-circuit |
|
2252 * checking the DB for the charset, returning that value instead. |
|
2253 * |
|
2254 * @since 4.2.0 |
|
2255 * |
|
2256 * @param string $charset The character set to use. Default null. |
|
2257 * @param string $table The name of the table being checked. |
|
2258 */ |
|
2259 $charset = apply_filters( 'pre_get_table_charset', null, $table ); |
|
2260 if ( null !== $charset ) { |
|
2261 return $charset; |
|
2262 } |
|
2263 |
|
2264 if ( isset( $this->table_charset[ $tablekey ] ) ) { |
|
2265 return $this->table_charset[ $tablekey ]; |
|
2266 } |
|
2267 |
|
2268 $charsets = $columns = array(); |
|
2269 |
|
2270 $table_parts = explode( '.', $table ); |
|
2271 $table = '`' . implode( '`.`', $table_parts ) . '`'; |
|
2272 $results = $this->get_results( "SHOW FULL COLUMNS FROM $table" ); |
|
2273 if ( ! $results ) { |
|
2274 return new WP_Error( 'wpdb_get_table_charset_failure' ); |
|
2275 } |
|
2276 |
|
2277 foreach ( $results as $column ) { |
|
2278 $columns[ strtolower( $column->Field ) ] = $column; |
|
2279 } |
|
2280 |
|
2281 $this->col_meta[ $tablekey ] = $columns; |
|
2282 |
|
2283 foreach ( $columns as $column ) { |
|
2284 if ( ! empty( $column->Collation ) ) { |
|
2285 list( $charset ) = explode( '_', $column->Collation ); |
|
2286 |
|
2287 // If the current connection can't support utf8mb4 characters, let's only send 3-byte utf8 characters. |
|
2288 if ( 'utf8mb4' === $charset && ! $this->has_cap( 'utf8mb4' ) ) { |
|
2289 $charset = 'utf8'; |
|
2290 } |
|
2291 |
|
2292 $charsets[ strtolower( $charset ) ] = true; |
|
2293 } |
|
2294 |
|
2295 list( $type ) = explode( '(', $column->Type ); |
|
2296 |
|
2297 // A binary/blob means the whole query gets treated like this. |
|
2298 if ( in_array( strtoupper( $type ), array( 'BINARY', 'VARBINARY', 'TINYBLOB', 'MEDIUMBLOB', 'BLOB', 'LONGBLOB' ) ) ) { |
|
2299 $this->table_charset[ $tablekey ] = 'binary'; |
|
2300 return 'binary'; |
|
2301 } |
|
2302 } |
|
2303 |
|
2304 // utf8mb3 is an alias for utf8. |
|
2305 if ( isset( $charsets['utf8mb3'] ) ) { |
|
2306 $charsets['utf8'] = true; |
|
2307 unset( $charsets['utf8mb3'] ); |
|
2308 } |
|
2309 |
|
2310 // Check if we have more than one charset in play. |
|
2311 $count = count( $charsets ); |
|
2312 if ( 1 === $count ) { |
|
2313 $charset = key( $charsets ); |
|
2314 } elseif ( 0 === $count ) { |
|
2315 // No charsets, assume this table can store whatever. |
|
2316 $charset = false; |
|
2317 } else { |
|
2318 // More than one charset. Remove latin1 if present and recalculate. |
|
2319 unset( $charsets['latin1'] ); |
|
2320 $count = count( $charsets ); |
|
2321 if ( 1 === $count ) { |
|
2322 // Only one charset (besides latin1). |
|
2323 $charset = key( $charsets ); |
|
2324 } elseif ( 2 === $count && isset( $charsets['utf8'], $charsets['utf8mb4'] ) ) { |
|
2325 // Two charsets, but they're utf8 and utf8mb4, use utf8. |
|
2326 $charset = 'utf8'; |
|
2327 } else { |
|
2328 // Two mixed character sets. ascii. |
|
2329 $charset = 'ascii'; |
|
2330 } |
|
2331 } |
|
2332 |
|
2333 $this->table_charset[ $tablekey ] = $charset; |
|
2334 return $charset; |
|
2335 } |
|
2336 |
|
2337 /** |
|
2338 * Retrieves the character set for the given column. |
|
2339 * |
|
2340 * @since 4.2.0 |
|
2341 * @access public |
|
2342 * |
|
2343 * @param string $table Table name. |
|
2344 * @param string $column Column name. |
|
2345 * @return mixed Column character set as a string. False if the column has no |
|
2346 * character set. WP_Error object if there was an error. |
|
2347 */ |
|
2348 public function get_col_charset( $table, $column ) { |
|
2349 $tablekey = strtolower( $table ); |
|
2350 $columnkey = strtolower( $column ); |
|
2351 |
|
2352 /** |
|
2353 * Filter the column charset value before the DB is checked. |
|
2354 * |
|
2355 * Passing a non-null value to the filter will short-circuit |
|
2356 * checking the DB for the charset, returning that value instead. |
|
2357 * |
|
2358 * @since 4.2.0 |
|
2359 * |
|
2360 * @param string $charset The character set to use. Default null. |
|
2361 * @param string $table The name of the table being checked. |
|
2362 * @param string $column The name of the column being checked. |
|
2363 */ |
|
2364 $charset = apply_filters( 'pre_get_col_charset', null, $table, $column ); |
|
2365 if ( null !== $charset ) { |
|
2366 return $charset; |
|
2367 } |
|
2368 |
|
2369 // Skip this entirely if this isn't a MySQL database. |
|
2370 if ( false === $this->is_mysql ) { |
|
2371 return false; |
|
2372 } |
|
2373 |
|
2374 if ( empty( $this->table_charset[ $tablekey ] ) ) { |
|
2375 // This primes column information for us. |
|
2376 $table_charset = $this->get_table_charset( $table ); |
|
2377 if ( is_wp_error( $table_charset ) ) { |
|
2378 return $table_charset; |
|
2379 } |
|
2380 } |
|
2381 |
|
2382 // If still no column information, return the table charset. |
|
2383 if ( empty( $this->col_meta[ $tablekey ] ) ) { |
|
2384 return $this->table_charset[ $tablekey ]; |
|
2385 } |
|
2386 |
|
2387 // If this column doesn't exist, return the table charset. |
|
2388 if ( empty( $this->col_meta[ $tablekey ][ $columnkey ] ) ) { |
|
2389 return $this->table_charset[ $tablekey ]; |
|
2390 } |
|
2391 |
|
2392 // Return false when it's not a string column. |
|
2393 if ( empty( $this->col_meta[ $tablekey ][ $columnkey ]->Collation ) ) { |
|
2394 return false; |
|
2395 } |
|
2396 |
|
2397 list( $charset ) = explode( '_', $this->col_meta[ $tablekey ][ $columnkey ]->Collation ); |
|
2398 return $charset; |
|
2399 } |
|
2400 |
|
2401 /** |
|
2402 * Retrieve the maximum string length allowed in a given column. |
|
2403 * The length may either be specified as a byte length or a character length. |
|
2404 * |
|
2405 * @since 4.2.1 |
|
2406 * @access public |
|
2407 * |
|
2408 * @param string $table Table name. |
|
2409 * @param string $column Column name. |
|
2410 * @return mixed array( 'length' => (int), 'type' => 'byte' | 'char' ) |
|
2411 * false if the column has no length (for example, numeric column) |
|
2412 * WP_Error object if there was an error. |
|
2413 */ |
|
2414 public function get_col_length( $table, $column ) { |
|
2415 $tablekey = strtolower( $table ); |
|
2416 $columnkey = strtolower( $column ); |
|
2417 |
|
2418 // Skip this entirely if this isn't a MySQL database. |
|
2419 if ( false === $this->is_mysql ) { |
|
2420 return false; |
|
2421 } |
|
2422 |
|
2423 if ( empty( $this->col_meta[ $tablekey ] ) ) { |
|
2424 // This primes column information for us. |
|
2425 $table_charset = $this->get_table_charset( $table ); |
|
2426 if ( is_wp_error( $table_charset ) ) { |
|
2427 return $table_charset; |
|
2428 } |
|
2429 } |
|
2430 |
|
2431 if ( empty( $this->col_meta[ $tablekey ][ $columnkey ] ) ) { |
|
2432 return false; |
|
2433 } |
|
2434 |
|
2435 $typeinfo = explode( '(', $this->col_meta[ $tablekey ][ $columnkey ]->Type ); |
|
2436 |
|
2437 $type = strtolower( $typeinfo[0] ); |
|
2438 if ( ! empty( $typeinfo[1] ) ) { |
|
2439 $length = trim( $typeinfo[1], ')' ); |
|
2440 } else { |
|
2441 $length = false; |
|
2442 } |
|
2443 |
|
2444 switch( $type ) { |
|
2445 case 'char': |
|
2446 case 'varchar': |
|
2447 return array( |
|
2448 'type' => 'char', |
|
2449 'length' => (int) $length, |
|
2450 ); |
|
2451 break; |
|
2452 case 'binary': |
|
2453 case 'varbinary': |
|
2454 return array( |
|
2455 'type' => 'byte', |
|
2456 'length' => (int) $length, |
|
2457 ); |
|
2458 break; |
|
2459 case 'tinyblob': |
|
2460 case 'tinytext': |
|
2461 return array( |
|
2462 'type' => 'byte', |
|
2463 'length' => 255, // 2^8 - 1 |
|
2464 ); |
|
2465 break; |
|
2466 case 'blob': |
|
2467 case 'text': |
|
2468 return array( |
|
2469 'type' => 'byte', |
|
2470 'length' => 65535, // 2^16 - 1 |
|
2471 ); |
|
2472 break; |
|
2473 case 'mediumblob': |
|
2474 case 'mediumtext': |
|
2475 return array( |
|
2476 'type' => 'byte', |
|
2477 'length' => 16777215, // 2^24 - 1 |
|
2478 ); |
|
2479 break; |
|
2480 case 'longblob': |
|
2481 case 'longtext': |
|
2482 return array( |
|
2483 'type' => 'byte', |
|
2484 'length' => 4294967295, // 2^32 - 1 |
|
2485 ); |
|
2486 break; |
|
2487 default: |
|
2488 return false; |
|
2489 } |
|
2490 |
|
2491 return false; |
|
2492 } |
|
2493 |
|
2494 /** |
|
2495 * Check if a string is ASCII. |
|
2496 * |
|
2497 * The negative regex is faster for non-ASCII strings, as it allows |
|
2498 * the search to finish as soon as it encounters a non-ASCII character. |
|
2499 * |
|
2500 * @since 4.2.0 |
|
2501 * @access protected |
|
2502 * |
|
2503 * @param string $string String to check. |
|
2504 * @return bool True if ASCII, false if not. |
|
2505 */ |
|
2506 protected function check_ascii( $string ) { |
|
2507 if ( function_exists( 'mb_check_encoding' ) ) { |
|
2508 if ( mb_check_encoding( $string, 'ASCII' ) ) { |
|
2509 return true; |
|
2510 } |
|
2511 } elseif ( ! preg_match( '/[^\x00-\x7F]/', $string ) ) { |
|
2512 return true; |
|
2513 } |
|
2514 |
|
2515 return false; |
|
2516 } |
|
2517 |
|
2518 /** |
|
2519 * Check if the query is accessing a collation considered safe on the current version of MySQL. |
|
2520 * |
|
2521 * @since 4.2.0 |
|
2522 * @access protected |
|
2523 * |
|
2524 * @param string $query The query to check. |
|
2525 * @return bool True if the collation is safe, false if it isn't. |
|
2526 */ |
|
2527 protected function check_safe_collation( $query ) { |
|
2528 if ( $this->checking_collation ) { |
|
2529 return true; |
|
2530 } |
|
2531 |
|
2532 // We don't need to check the collation for queries that don't read data. |
|
2533 $query = ltrim( $query, "\r\n\t (" ); |
|
2534 if ( preg_match( '/^(?:SHOW|DESCRIBE|DESC|EXPLAIN|CREATE)\s/i', $query ) ) { |
|
2535 return true; |
|
2536 } |
|
2537 |
|
2538 // All-ASCII queries don't need extra checking. |
|
2539 if ( $this->check_ascii( $query ) ) { |
|
2540 return true; |
|
2541 } |
|
2542 |
|
2543 $table = $this->get_table_from_query( $query ); |
|
2544 if ( ! $table ) { |
|
2545 return false; |
|
2546 } |
|
2547 |
|
2548 $this->checking_collation = true; |
|
2549 $collation = $this->get_table_charset( $table ); |
|
2550 $this->checking_collation = false; |
|
2551 |
|
2552 // Tables with no collation, or latin1 only, don't need extra checking. |
|
2553 if ( false === $collation || 'latin1' === $collation ) { |
|
2554 return true; |
|
2555 } |
|
2556 |
|
2557 $table = strtolower( $table ); |
|
2558 if ( empty( $this->col_meta[ $table ] ) ) { |
|
2559 return false; |
|
2560 } |
|
2561 |
|
2562 // If any of the columns don't have one of these collations, it needs more sanity checking. |
|
2563 foreach( $this->col_meta[ $table ] as $col ) { |
|
2564 if ( empty( $col->Collation ) ) { |
|
2565 continue; |
|
2566 } |
|
2567 |
|
2568 if ( ! in_array( $col->Collation, array( 'utf8_general_ci', 'utf8_bin', 'utf8mb4_general_ci', 'utf8mb4_bin' ), true ) ) { |
|
2569 return false; |
|
2570 } |
|
2571 } |
|
2572 |
|
2573 return true; |
|
2574 } |
|
2575 |
|
2576 /** |
|
2577 * Strips any invalid characters based on value/charset pairs. |
|
2578 * |
|
2579 * @since 4.2.0 |
|
2580 * @access protected |
|
2581 * |
|
2582 * @param array $data Array of value arrays. Each value array has the keys |
|
2583 * 'value' and 'charset'. An optional 'ascii' key can be |
|
2584 * set to false to avoid redundant ASCII checks. |
|
2585 * @return array|WP_Error The $data parameter, with invalid characters removed from |
|
2586 * each value. This works as a passthrough: any additional keys |
|
2587 * such as 'field' are retained in each value array. If we cannot |
|
2588 * remove invalid characters, a WP_Error object is returned. |
|
2589 */ |
|
2590 protected function strip_invalid_text( $data ) { |
|
2591 $db_check_string = false; |
|
2592 |
|
2593 foreach ( $data as &$value ) { |
|
2594 $charset = $value['charset']; |
|
2595 |
|
2596 if ( is_array( $value['length'] ) ) { |
|
2597 $length = $value['length']['length']; |
|
2598 } else { |
|
2599 $length = false; |
|
2600 } |
|
2601 |
|
2602 // There's no charset to work with. |
|
2603 if ( false === $charset ) { |
|
2604 continue; |
|
2605 } |
|
2606 |
|
2607 // Column isn't a string. |
|
2608 if ( ! is_string( $value['value'] ) ) { |
|
2609 continue; |
|
2610 } |
|
2611 |
|
2612 $truncate_by_byte_length = 'byte' === $value['length']['type']; |
|
2613 |
|
2614 $needs_validation = true; |
|
2615 if ( |
|
2616 // latin1 can store any byte sequence |
|
2617 'latin1' === $charset |
|
2618 || |
|
2619 // ASCII is always OK. |
|
2620 ( ! isset( $value['ascii'] ) && $this->check_ascii( $value['value'] ) ) |
|
2621 ) { |
|
2622 $truncate_by_byte_length = true; |
|
2623 $needs_validation = false; |
|
2624 } |
|
2625 |
|
2626 if ( $truncate_by_byte_length ) { |
|
2627 mbstring_binary_safe_encoding(); |
|
2628 if ( false !== $length && strlen( $value['value'] ) > $length ) { |
|
2629 $value['value'] = substr( $value['value'], 0, $length ); |
|
2630 } |
|
2631 reset_mbstring_encoding(); |
|
2632 |
|
2633 if ( ! $needs_validation ) { |
|
2634 continue; |
|
2635 } |
|
2636 } |
|
2637 |
|
2638 // utf8 can be handled by regex, which is a bunch faster than a DB lookup. |
|
2639 if ( ( 'utf8' === $charset || 'utf8mb3' === $charset || 'utf8mb4' === $charset ) && function_exists( 'mb_strlen' ) ) { |
|
2640 $regex = '/ |
|
2641 ( |
|
2642 (?: [\x00-\x7F] # single-byte sequences 0xxxxxxx |
|
2643 | [\xC2-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx |
|
2644 | \xE0[\xA0-\xBF][\x80-\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 |
|
2645 | [\xE1-\xEC][\x80-\xBF]{2} |
|
2646 | \xED[\x80-\x9F][\x80-\xBF] |
|
2647 | [\xEE-\xEF][\x80-\xBF]{2}'; |
|
2648 |
|
2649 if ( 'utf8mb4' === $charset ) { |
|
2650 $regex .= ' |
|
2651 | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 |
|
2652 | [\xF1-\xF3][\x80-\xBF]{3} |
|
2653 | \xF4[\x80-\x8F][\x80-\xBF]{2} |
|
2654 '; |
|
2655 } |
|
2656 |
|
2657 $regex .= '){1,40} # ...one or more times |
|
2658 ) |
|
2659 | . # anything else |
|
2660 /x'; |
|
2661 $value['value'] = preg_replace( $regex, '$1', $value['value'] ); |
|
2662 |
|
2663 |
|
2664 if ( false !== $length && mb_strlen( $value['value'], 'UTF-8' ) > $length ) { |
|
2665 $value['value'] = mb_substr( $value['value'], 0, $length, 'UTF-8' ); |
|
2666 } |
|
2667 continue; |
|
2668 } |
|
2669 |
|
2670 // We couldn't use any local conversions, send it to the DB. |
|
2671 $value['db'] = $db_check_string = true; |
|
2672 } |
|
2673 unset( $value ); // Remove by reference. |
|
2674 |
|
2675 if ( $db_check_string ) { |
|
2676 $queries = array(); |
|
2677 foreach ( $data as $col => $value ) { |
|
2678 if ( ! empty( $value['db'] ) ) { |
|
2679 if ( ! isset( $queries[ $value['charset'] ] ) ) { |
|
2680 $queries[ $value['charset'] ] = array(); |
|
2681 } |
|
2682 |
|
2683 // We're going to need to truncate by characters or bytes, depending on the length value we have. |
|
2684 if ( 'byte' === $value['length']['type'] ) { |
|
2685 // Split the CONVERT() calls by charset, so we can make sure the connection is right |
|
2686 $queries[ $value['charset'] ][ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING binary ), %d ) USING {$value['charset']} )", $value['value'], $value['length']['length'] ); |
|
2687 } else { |
|
2688 $queries[ $value['charset'] ][ $col ] = $this->prepare( "LEFT( CONVERT( %s USING {$value['charset']} ), %d )", $value['value'], $value['length']['length'] ); |
|
2689 } |
|
2690 |
|
2691 unset( $data[ $col ]['db'] ); |
|
2692 } |
|
2693 } |
|
2694 |
|
2695 $connection_charset = $this->charset; |
|
2696 foreach ( $queries as $charset => $query ) { |
|
2697 if ( ! $query ) { |
|
2698 continue; |
|
2699 } |
|
2700 |
|
2701 // Change the charset to match the string(s) we're converting |
|
2702 if ( $charset !== $connection_charset ) { |
|
2703 $connection_charset = $charset; |
|
2704 $this->set_charset( $this->dbh, $charset ); |
|
2705 } |
|
2706 |
|
2707 $this->check_current_query = false; |
|
2708 |
|
2709 $sql = array(); |
|
2710 foreach ( $query as $column => $column_query ) { |
|
2711 $sql[] = $column_query . " AS x_$column"; |
|
2712 } |
|
2713 |
|
2714 $row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A ); |
|
2715 if ( ! $row ) { |
|
2716 $this->set_charset( $this->dbh, $connection_charset ); |
|
2717 return new WP_Error( 'wpdb_strip_invalid_text_failure' ); |
|
2718 } |
|
2719 |
|
2720 foreach ( array_keys( $query ) as $column ) { |
|
2721 $data[ $column ]['value'] = $row["x_$column"]; |
|
2722 } |
|
2723 } |
|
2724 |
|
2725 // Don't forget to change the charset back! |
|
2726 if ( $connection_charset !== $this->charset ) { |
|
2727 $this->set_charset( $this->dbh ); |
|
2728 } |
|
2729 } |
|
2730 |
|
2731 return $data; |
|
2732 } |
|
2733 |
|
2734 /** |
|
2735 * Strips any invalid characters from the query. |
|
2736 * |
|
2737 * @since 4.2.0 |
|
2738 * @access protected |
|
2739 * |
|
2740 * @param string $query Query to convert. |
|
2741 * @return string|WP_Error The converted query, or a WP_Error object if the conversion fails. |
|
2742 */ |
|
2743 protected function strip_invalid_text_from_query( $query ) { |
|
2744 // We don't need to check the collation for queries that don't read data. |
|
2745 $trimmed_query = ltrim( $query, "\r\n\t (" ); |
|
2746 if ( preg_match( '/^(?:SHOW|DESCRIBE|DESC|EXPLAIN|CREATE)\s/i', $trimmed_query ) ) { |
|
2747 return $query; |
|
2748 } |
|
2749 |
|
2750 $table = $this->get_table_from_query( $query ); |
|
2751 if ( $table ) { |
|
2752 $charset = $this->get_table_charset( $table ); |
|
2753 if ( is_wp_error( $charset ) ) { |
|
2754 return $charset; |
|
2755 } |
|
2756 |
|
2757 // We can't reliably strip text from tables containing binary/blob columns |
|
2758 if ( 'binary' === $charset ) { |
|
2759 return $query; |
|
2760 } |
|
2761 } else { |
|
2762 $charset = $this->charset; |
|
2763 } |
|
2764 |
|
2765 $data = array( |
|
2766 'value' => $query, |
|
2767 'charset' => $charset, |
|
2768 'ascii' => false, |
|
2769 'length' => false, |
|
2770 ); |
|
2771 |
|
2772 $data = $this->strip_invalid_text( array( $data ) ); |
|
2773 if ( is_wp_error( $data ) ) { |
|
2774 return $data; |
|
2775 } |
|
2776 |
|
2777 return $data[0]['value']; |
|
2778 } |
|
2779 |
|
2780 /** |
|
2781 * Strips any invalid characters from the string for a given table and column. |
|
2782 * |
|
2783 * @since 4.2.0 |
|
2784 * @access public |
|
2785 * |
|
2786 * @param string $table Table name. |
|
2787 * @param string $column Column name. |
|
2788 * @param string $value The text to check. |
|
2789 * @return string|WP_Error The converted string, or a WP_Error object if the conversion fails. |
|
2790 */ |
|
2791 public function strip_invalid_text_for_column( $table, $column, $value ) { |
|
2792 if ( ! is_string( $value ) ) { |
|
2793 return $value; |
|
2794 } |
|
2795 |
|
2796 $charset = $this->get_col_charset( $table, $column ); |
|
2797 if ( ! $charset ) { |
|
2798 // Not a string column. |
|
2799 return $value; |
|
2800 } elseif ( is_wp_error( $charset ) ) { |
|
2801 // Bail on real errors. |
|
2802 return $charset; |
|
2803 } |
|
2804 |
|
2805 $data = array( |
|
2806 $column => array( |
|
2807 'value' => $value, |
|
2808 'charset' => $charset, |
|
2809 'length' => $this->get_col_length( $table, $column ), |
|
2810 ) |
|
2811 ); |
|
2812 |
|
2813 $data = $this->strip_invalid_text( $data ); |
|
2814 if ( is_wp_error( $data ) ) { |
|
2815 return $data; |
|
2816 } |
|
2817 |
|
2818 return $data[ $column ]['value']; |
|
2819 } |
|
2820 |
|
2821 /** |
|
2822 * Find the first table name referenced in a query. |
|
2823 * |
|
2824 * @since 4.2.0 |
|
2825 * @access protected |
|
2826 * |
|
2827 * @param string $query The query to search. |
|
2828 * @return string|false $table The table name found, or false if a table couldn't be found. |
|
2829 */ |
|
2830 protected function get_table_from_query( $query ) { |
|
2831 // Remove characters that can legally trail the table name. |
|
2832 $query = rtrim( $query, ';/-#' ); |
|
2833 |
|
2834 // Allow (select...) union [...] style queries. Use the first query's table name. |
|
2835 $query = ltrim( $query, "\r\n\t (" ); |
|
2836 |
|
2837 /* |
|
2838 * Strip everything between parentheses except nested selects and use only 1,000 |
|
2839 * chars of the query. |
|
2840 */ |
|
2841 $query = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', substr( $query, 0, 1000 ) ); |
|
2842 |
|
2843 // Quickly match most common queries. |
|
2844 if ( preg_match( '/^\s*(?:' |
|
2845 . 'SELECT.*?\s+FROM' |
|
2846 . '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?' |
|
2847 . '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?' |
|
2848 . '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?' |
|
2849 . '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:\s+FROM)?' |
|
2850 . ')\s+((?:[0-9a-zA-Z$_.`]|[\xC2-\xDF][\x80-\xBF])+)/is', $query, $maybe ) ) { |
|
2851 return str_replace( '`', '', $maybe[1] ); |
|
2852 } |
|
2853 |
|
2854 // SHOW TABLE STATUS and SHOW TABLES |
|
2855 if ( preg_match( '/^\s*(?:' |
|
2856 . 'SHOW\s+TABLE\s+STATUS.+(?:LIKE\s+|WHERE\s+Name\s*=\s*)' |
|
2857 . '|SHOW\s+(?:FULL\s+)?TABLES.+(?:LIKE\s+|WHERE\s+Name\s*=\s*)' |
|
2858 . ')\W((?:[0-9a-zA-Z$_.`]|[\xC2-\xDF][\x80-\xBF])+)\W/is', $query, $maybe ) ) { |
|
2859 return str_replace( '`', '', $maybe[1] ); |
|
2860 } |
|
2861 |
|
2862 // Big pattern for the rest of the table-related queries. |
|
2863 if ( preg_match( '/^\s*(?:' |
|
2864 . '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM' |
|
2865 . '|DESCRIBE|DESC|EXPLAIN|HANDLER' |
|
2866 . '|(?:LOCK|UNLOCK)\s+TABLE(?:S)?' |
|
2867 . '|(?:RENAME|OPTIMIZE|BACKUP|RESTORE|CHECK|CHECKSUM|ANALYZE|REPAIR).*\s+TABLE' |
|
2868 . '|TRUNCATE(?:\s+TABLE)?' |
|
2869 . '|CREATE(?:\s+TEMPORARY)?\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?' |
|
2870 . '|ALTER(?:\s+IGNORE)?\s+TABLE' |
|
2871 . '|DROP\s+TABLE(?:\s+IF\s+EXISTS)?' |
|
2872 . '|CREATE(?:\s+\w+)?\s+INDEX.*\s+ON' |
|
2873 . '|DROP\s+INDEX.*\s+ON' |
|
2874 . '|LOAD\s+DATA.*INFILE.*INTO\s+TABLE' |
|
2875 . '|(?:GRANT|REVOKE).*ON\s+TABLE' |
|
2876 . '|SHOW\s+(?:.*FROM|.*TABLE)' |
|
2877 . ')\s+\(*\s*((?:[0-9a-zA-Z$_.`]|[\xC2-\xDF][\x80-\xBF])+)\s*\)*/is', $query, $maybe ) ) { |
|
2878 return str_replace( '`', '', $maybe[1] ); |
|
2879 } |
|
2880 |
|
2881 return false; |
|
1564 } |
2882 } |
1565 |
2883 |
1566 /** |
2884 /** |
1567 * Load the column metadata from the last query. |
2885 * Load the column metadata from the last query. |
1568 * |
2886 * |
1572 */ |
2890 */ |
1573 protected function load_col_info() { |
2891 protected function load_col_info() { |
1574 if ( $this->col_info ) |
2892 if ( $this->col_info ) |
1575 return; |
2893 return; |
1576 |
2894 |
1577 for ( $i = 0; $i < @mysql_num_fields( $this->result ); $i++ ) { |
2895 if ( $this->use_mysqli ) { |
1578 $this->col_info[ $i ] = @mysql_fetch_field( $this->result, $i ); |
2896 for ( $i = 0; $i < @mysqli_num_fields( $this->result ); $i++ ) { |
2897 $this->col_info[ $i ] = @mysqli_fetch_field( $this->result ); |
|
2898 } |
|
2899 } else { |
|
2900 for ( $i = 0; $i < @mysql_num_fields( $this->result ); $i++ ) { |
|
2901 $this->col_info[ $i ] = @mysql_fetch_field( $this->result, $i ); |
|
2902 } |
|
1579 } |
2903 } |
1580 } |
2904 } |
1581 |
2905 |
1582 /** |
2906 /** |
1583 * Retrieve column metadata from the last query. |
2907 * Retrieve column metadata from the last query. |
1586 * |
2910 * |
1587 * @param string $info_type Optional. Type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill |
2911 * @param string $info_type Optional. Type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill |
1588 * @param int $col_offset Optional. 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type |
2912 * @param int $col_offset Optional. 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type |
1589 * @return mixed Column Results |
2913 * @return mixed Column Results |
1590 */ |
2914 */ |
1591 function get_col_info( $info_type = 'name', $col_offset = -1 ) { |
2915 public function get_col_info( $info_type = 'name', $col_offset = -1 ) { |
1592 $this->load_col_info(); |
2916 $this->load_col_info(); |
1593 |
2917 |
1594 if ( $this->col_info ) { |
2918 if ( $this->col_info ) { |
1595 if ( $col_offset == -1 ) { |
2919 if ( $col_offset == -1 ) { |
1596 $i = 0; |
2920 $i = 0; |
1609 /** |
2933 /** |
1610 * Starts the timer, for debugging purposes. |
2934 * Starts the timer, for debugging purposes. |
1611 * |
2935 * |
1612 * @since 1.5.0 |
2936 * @since 1.5.0 |
1613 * |
2937 * |
1614 * @return true |
2938 * @return bool |
1615 */ |
2939 */ |
1616 function timer_start() { |
2940 public function timer_start() { |
1617 $this->time_start = microtime( true ); |
2941 $this->time_start = microtime( true ); |
1618 return true; |
2942 return true; |
1619 } |
2943 } |
1620 |
2944 |
1621 /** |
2945 /** |
1623 * |
2947 * |
1624 * @since 1.5.0 |
2948 * @since 1.5.0 |
1625 * |
2949 * |
1626 * @return float Total time spent on the query, in seconds |
2950 * @return float Total time spent on the query, in seconds |
1627 */ |
2951 */ |
1628 function timer_stop() { |
2952 public function timer_stop() { |
1629 return ( microtime( true ) - $this->time_start ); |
2953 return ( microtime( true ) - $this->time_start ); |
1630 } |
2954 } |
1631 |
2955 |
1632 /** |
2956 /** |
1633 * Wraps errors in a nice header and footer and dies. |
2957 * Wraps errors in a nice header and footer and dies. |
1638 * |
2962 * |
1639 * @param string $message The Error message |
2963 * @param string $message The Error message |
1640 * @param string $error_code Optional. A Computer readable string to identify the error. |
2964 * @param string $error_code Optional. A Computer readable string to identify the error. |
1641 * @return false|void |
2965 * @return false|void |
1642 */ |
2966 */ |
1643 function bail( $message, $error_code = '500' ) { |
2967 public function bail( $message, $error_code = '500' ) { |
1644 if ( !$this->show_errors ) { |
2968 if ( !$this->show_errors ) { |
1645 if ( class_exists( 'WP_Error' ) ) |
2969 if ( class_exists( 'WP_Error' ) ) |
1646 $this->error = new WP_Error($error_code, $message); |
2970 $this->error = new WP_Error($error_code, $message); |
1647 else |
2971 else |
1648 $this->error = $message; |
2972 $this->error = $message; |
1658 * @uses $wp_version |
2982 * @uses $wp_version |
1659 * @uses $required_mysql_version |
2983 * @uses $required_mysql_version |
1660 * |
2984 * |
1661 * @return WP_Error |
2985 * @return WP_Error |
1662 */ |
2986 */ |
1663 function check_database_version() { |
2987 public function check_database_version() { |
1664 global $wp_version, $required_mysql_version; |
2988 global $wp_version, $required_mysql_version; |
1665 // Make sure the server has the required MySQL version |
2989 // Make sure the server has the required MySQL version |
1666 if ( version_compare($this->db_version(), $required_mysql_version, '<') ) |
2990 if ( version_compare($this->db_version(), $required_mysql_version, '<') ) |
1667 return new WP_Error('database_version', sprintf( __( '<strong>ERROR</strong>: WordPress %1$s requires MySQL %2$s or higher' ), $wp_version, $required_mysql_version )); |
2991 return new WP_Error('database_version', sprintf( __( '<strong>ERROR</strong>: WordPress %1$s requires MySQL %2$s or higher' ), $wp_version, $required_mysql_version )); |
1668 } |
2992 } |
1676 * @deprecated 3.5.0 |
3000 * @deprecated 3.5.0 |
1677 * @deprecated Use wpdb::has_cap( 'collation' ) |
3001 * @deprecated Use wpdb::has_cap( 'collation' ) |
1678 * |
3002 * |
1679 * @return bool True if collation is supported, false if version does not |
3003 * @return bool True if collation is supported, false if version does not |
1680 */ |
3004 */ |
1681 function supports_collation() { |
3005 public function supports_collation() { |
1682 _deprecated_function( __FUNCTION__, '3.5', 'wpdb::has_cap( \'collation\' )' ); |
3006 _deprecated_function( __FUNCTION__, '3.5', 'wpdb::has_cap( \'collation\' )' ); |
1683 return $this->has_cap( 'collation' ); |
3007 return $this->has_cap( 'collation' ); |
1684 } |
3008 } |
1685 |
3009 |
1686 /** |
3010 /** |
1703 |
3027 |
1704 /** |
3028 /** |
1705 * Determine if a database supports a particular feature. |
3029 * Determine if a database supports a particular feature. |
1706 * |
3030 * |
1707 * @since 2.7.0 |
3031 * @since 2.7.0 |
3032 * @since 4.1.0 Support was added for the 'utf8mb4' feature. |
|
3033 * |
|
1708 * @see wpdb::db_version() |
3034 * @see wpdb::db_version() |
1709 * |
3035 * |
1710 * @param string $db_cap The feature to check for. |
3036 * @param string $db_cap The feature to check for. Accepts 'collation', |
1711 * @return bool |
3037 * 'group_concat', 'subqueries', 'set_charset', |
1712 */ |
3038 * or 'utf8mb4'. |
1713 function has_cap( $db_cap ) { |
3039 * @return bool Whether the database feature is supported, false otherwise. |
3040 */ |
|
3041 public function has_cap( $db_cap ) { |
|
1714 $version = $this->db_version(); |
3042 $version = $this->db_version(); |
1715 |
3043 |
1716 switch ( strtolower( $db_cap ) ) { |
3044 switch ( strtolower( $db_cap ) ) { |
1717 case 'collation' : // @since 2.5.0 |
3045 case 'collation' : // @since 2.5.0 |
1718 case 'group_concat' : // @since 2.7.0 |
3046 case 'group_concat' : // @since 2.7.0 |
1719 case 'subqueries' : // @since 2.7.0 |
3047 case 'subqueries' : // @since 2.7.0 |
1720 return version_compare( $version, '4.1', '>=' ); |
3048 return version_compare( $version, '4.1', '>=' ); |
1721 case 'set_charset' : |
3049 case 'set_charset' : |
1722 return version_compare( $version, '5.0.7', '>=' ); |
3050 return version_compare( $version, '5.0.7', '>=' ); |
1723 }; |
3051 case 'utf8mb4' : // @since 4.1.0 |
3052 if ( version_compare( $version, '5.5.3', '<' ) ) { |
|
3053 return false; |
|
3054 } |
|
3055 if ( $this->use_mysqli ) { |
|
3056 $client_version = mysqli_get_client_info(); |
|
3057 } else { |
|
3058 $client_version = mysql_get_client_info(); |
|
3059 } |
|
3060 |
|
3061 /* |
|
3062 * libmysql has supported utf8mb4 since 5.5.3, same as the MySQL server. |
|
3063 * mysqlnd has supported utf8mb4 since 5.0.9. |
|
3064 */ |
|
3065 if ( false !== strpos( $client_version, 'mysqlnd' ) ) { |
|
3066 $client_version = preg_replace( '/^\D+([\d.]+).*/', '$1', $client_version ); |
|
3067 return version_compare( $client_version, '5.0.9', '>=' ); |
|
3068 } else { |
|
3069 return version_compare( $client_version, '5.5.3', '>=' ); |
|
3070 } |
|
3071 } |
|
1724 |
3072 |
1725 return false; |
3073 return false; |
1726 } |
3074 } |
1727 |
3075 |
1728 /** |
3076 /** |
1733 * |
3081 * |
1734 * @since 2.5.0 |
3082 * @since 2.5.0 |
1735 * |
3083 * |
1736 * @return string The name of the calling function |
3084 * @return string The name of the calling function |
1737 */ |
3085 */ |
1738 function get_caller() { |
3086 public function get_caller() { |
1739 return wp_debug_backtrace_summary( __CLASS__ ); |
3087 return wp_debug_backtrace_summary( __CLASS__ ); |
1740 } |
3088 } |
1741 |
3089 |
1742 /** |
3090 /** |
1743 * The database version number. |
3091 * The database version number. |
1744 * |
3092 * |
1745 * @since 2.7.0 |
3093 * @since 2.7.0 |
1746 * |
3094 * |
1747 * @return false|string false on failure, version number on success |
3095 * @return null|string Null on failure, version number on success. |
1748 */ |
3096 */ |
1749 function db_version() { |
3097 public function db_version() { |
1750 return preg_replace( '/[^0-9.].*/', '', mysql_get_server_info( $this->dbh ) ); |
3098 if ( $this->use_mysqli ) { |
3099 $server_info = mysqli_get_server_info( $this->dbh ); |
|
3100 } else { |
|
3101 $server_info = mysql_get_server_info( $this->dbh ); |
|
3102 } |
|
3103 return preg_replace( '/[^0-9.].*/', '', $server_info ); |
|
1751 } |
3104 } |
1752 } |
3105 } |