~canonical-sysadmins/wordpress/4.7.2

« back to all changes in this revision

Viewing changes to wp-includes/wp-db.php

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * WordPress DB Class
 
4
 *
 
5
 * Original code from {@link http://php.justinvincent.com Justin Vincent (justin@visunet.ie)}
 
6
 *
 
7
 * @package WordPress
 
8
 * @subpackage Database
 
9
 * @since 0.71
 
10
 */
 
11
 
 
12
/**
 
13
 * @since 0.71
 
14
 */
 
15
define( 'EZSQL_VERSION', 'WP1.25' );
 
16
 
 
17
/**
 
18
 * @since 0.71
 
19
 */
 
20
define( 'OBJECT', 'OBJECT' );
 
21
define( 'object', 'OBJECT' ); // Back compat.
 
22
 
 
23
/**
 
24
 * @since 2.5.0
 
25
 */
 
26
define( 'OBJECT_K', 'OBJECT_K' );
 
27
 
 
28
/**
 
29
 * @since 0.71
 
30
 */
 
31
define( 'ARRAY_A', 'ARRAY_A' );
 
32
 
 
33
/**
 
34
 * @since 0.71
 
35
 */
 
36
define( 'ARRAY_N', 'ARRAY_N' );
 
37
 
 
38
/**
 
39
 * WordPress Database Access Abstraction Object
 
40
 *
 
41
 * It is possible to replace this class with your own
 
42
 * by setting the $wpdb global variable in wp-content/db.php
 
43
 * file to your class. The wpdb class will still be included,
 
44
 * so you can extend it or simply use your own.
 
45
 *
 
46
 * @link http://codex.wordpress.org/Function_Reference/wpdb_Class
 
47
 *
 
48
 * @package WordPress
 
49
 * @subpackage Database
 
50
 * @since 0.71
 
51
 */
 
52
class wpdb {
 
53
 
 
54
        /**
 
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.
 
59
         *
 
60
         * @since 0.71
 
61
         * @access private
 
62
         * @var bool
 
63
         */
 
64
        var $show_errors = false;
 
65
 
 
66
        /**
 
67
         * Whether to suppress errors during the DB bootstrapping.
 
68
         *
 
69
         * @access private
 
70
         * @since 2.5.0
 
71
         * @var bool
 
72
         */
 
73
        var $suppress_errors = false;
 
74
 
 
75
        /**
 
76
         * The last error during query.
 
77
         *
 
78
         * @since 2.5.0
 
79
         * @var string
 
80
         */
 
81
        public $last_error = '';
 
82
 
 
83
        /**
 
84
         * Amount of queries made
 
85
         *
 
86
         * @since 1.2.0
 
87
         * @access private
 
88
         * @var int
 
89
         */
 
90
        var $num_queries = 0;
 
91
 
 
92
        /**
 
93
         * Count of rows returned by previous query
 
94
         *
 
95
         * @since 0.71
 
96
         * @access private
 
97
         * @var int
 
98
         */
 
99
        var $num_rows = 0;
 
100
 
 
101
        /**
 
102
         * Count of affected rows by previous query
 
103
         *
 
104
         * @since 0.71
 
105
         * @access private
 
106
         * @var int
 
107
         */
 
108
        var $rows_affected = 0;
 
109
 
 
110
        /**
 
111
         * The ID generated for an AUTO_INCREMENT column by the previous query (usually INSERT).
 
112
         *
 
113
         * @since 0.71
 
114
         * @access public
 
115
         * @var int
 
116
         */
 
117
        var $insert_id = 0;
 
118
 
 
119
        /**
 
120
         * Last query made
 
121
         *
 
122
         * @since 0.71
 
123
         * @access private
 
124
         * @var array
 
125
         */
 
126
        var $last_query;
 
127
 
 
128
        /**
 
129
         * Results of the last query made
 
130
         *
 
131
         * @since 0.71
 
132
         * @access private
 
133
         * @var array|null
 
134
         */
 
135
        var $last_result;
 
136
 
 
137
        /**
 
138
         * MySQL result, which is either a resource or boolean.
 
139
         *
 
140
         * @since 0.71
 
141
         * @access protected
 
142
         * @var mixed
 
143
         */
 
144
        protected $result;
 
145
 
 
146
        /**
 
147
         * Saved info on the table column
 
148
         *
 
149
         * @since 0.71
 
150
         * @access protected
 
151
         * @var array
 
152
         */
 
153
        protected $col_info;
 
154
 
 
155
        /**
 
156
         * Saved queries that were executed
 
157
         *
 
158
         * @since 1.5.0
 
159
         * @access private
 
160
         * @var array
 
161
         */
 
162
        var $queries;
 
163
 
 
164
        /**
 
165
         * The number of times to retry reconnecting before dying.
 
166
         *
 
167
         * @since 3.9.0
 
168
         * @access protected
 
169
         * @see wpdb::check_connection()
 
170
         * @var int
 
171
         */
 
172
        protected $reconnect_retries = 5;
 
173
 
 
174
        /**
 
175
         * WordPress table prefix
 
176
         *
 
177
         * You can set this to have multiple WordPress installations
 
178
         * in a single database. The second reason is for possible
 
179
         * security precautions.
 
180
         *
 
181
         * @since 2.5.0
 
182
         * @access private
 
183
         * @var string
 
184
         */
 
185
        var $prefix = '';
 
186
 
 
187
        /**
 
188
         * WordPress base table prefix.
 
189
         *
 
190
         * @since 3.0.0
 
191
         * @access public
 
192
         * @var string
 
193
         */
 
194
         public $base_prefix;
 
195
 
 
196
        /**
 
197
         * Whether the database queries are ready to start executing.
 
198
         *
 
199
         * @since 2.3.2
 
200
         * @access private
 
201
         * @var bool
 
202
         */
 
203
        var $ready = false;
 
204
 
 
205
        /**
 
206
         * {@internal Missing Description}}
 
207
         *
 
208
         * @since 3.0.0
 
209
         * @access public
 
210
         * @var int
 
211
         */
 
212
        public $blogid = 0;
 
213
 
 
214
        /**
 
215
         * {@internal Missing Description}}
 
216
         *
 
217
         * @since 3.0.0
 
218
         * @access public
 
219
         * @var int
 
220
         */
 
221
        public $siteid = 0;
 
222
 
 
223
        /**
 
224
         * List of WordPress per-blog tables
 
225
         *
 
226
         * @since 2.5.0
 
227
         * @access private
 
228
         * @see wpdb::tables()
 
229
         * @var array
 
230
         */
 
231
        var $tables = array( 'posts', 'comments', 'links', 'options', 'postmeta',
 
232
                'terms', 'term_taxonomy', 'term_relationships', 'commentmeta' );
 
233
 
 
234
        /**
 
235
         * List of deprecated WordPress tables
 
236
         *
 
237
         * categories, post2cat, and link2cat were deprecated in 2.3.0, db version 5539
 
238
         *
 
239
         * @since 2.9.0
 
240
         * @access private
 
241
         * @see wpdb::tables()
 
242
         * @var array
 
243
         */
 
244
        var $old_tables = array( 'categories', 'post2cat', 'link2cat' );
 
245
 
 
246
        /**
 
247
         * List of WordPress global tables
 
248
         *
 
249
         * @since 3.0.0
 
250
         * @access private
 
251
         * @see wpdb::tables()
 
252
         * @var array
 
253
         */
 
254
        var $global_tables = array( 'users', 'usermeta' );
 
255
 
 
256
        /**
 
257
         * List of Multisite global tables
 
258
         *
 
259
         * @since 3.0.0
 
260
         * @access private
 
261
         * @see wpdb::tables()
 
262
         * @var array
 
263
         */
 
264
        var $ms_global_tables = array( 'blogs', 'signups', 'site', 'sitemeta',
 
265
                'sitecategories', 'registration_log', 'blog_versions' );
 
266
 
 
267
        /**
 
268
         * WordPress Comments table
 
269
         *
 
270
         * @since 1.5.0
 
271
         * @access public
 
272
         * @var string
 
273
         */
 
274
        public $comments;
 
275
 
 
276
        /**
 
277
         * WordPress Comment Metadata table
 
278
         *
 
279
         * @since 2.9.0
 
280
         * @access public
 
281
         * @var string
 
282
         */
 
283
        public $commentmeta;
 
284
 
 
285
        /**
 
286
         * WordPress Links table
 
287
         *
 
288
         * @since 1.5.0
 
289
         * @access public
 
290
         * @var string
 
291
         */
 
292
        public $links;
 
293
 
 
294
        /**
 
295
         * WordPress Options table
 
296
         *
 
297
         * @since 1.5.0
 
298
         * @access public
 
299
         * @var string
 
300
         */
 
301
        public $options;
 
302
 
 
303
        /**
 
304
         * WordPress Post Metadata table
 
305
         *
 
306
         * @since 1.5.0
 
307
         * @access public
 
308
         * @var string
 
309
         */
 
310
        public $postmeta;
 
311
 
 
312
        /**
 
313
         * WordPress Posts table
 
314
         *
 
315
         * @since 1.5.0
 
316
         * @access public
 
317
         * @var string
 
318
         */
 
319
        public $posts;
 
320
 
 
321
        /**
 
322
         * WordPress Terms table
 
323
         *
 
324
         * @since 2.3.0
 
325
         * @access public
 
326
         * @var string
 
327
         */
 
328
        public $terms;
 
329
 
 
330
        /**
 
331
         * WordPress Term Relationships table
 
332
         *
 
333
         * @since 2.3.0
 
334
         * @access public
 
335
         * @var string
 
336
         */
 
337
        public $term_relationships;
 
338
 
 
339
        /**
 
340
         * WordPress Term Taxonomy table
 
341
         *
 
342
         * @since 2.3.0
 
343
         * @access public
 
344
         * @var string
 
345
         */
 
346
        public $term_taxonomy;
 
347
 
 
348
        /*
 
349
         * Global and Multisite tables
 
350
         */
 
351
 
 
352
        /**
 
353
         * WordPress User Metadata table
 
354
         *
 
355
         * @since 2.3.0
 
356
         * @access public
 
357
         * @var string
 
358
         */
 
359
        public $usermeta;
 
360
 
 
361
        /**
 
362
         * WordPress Users table
 
363
         *
 
364
         * @since 1.5.0
 
365
         * @access public
 
366
         * @var string
 
367
         */
 
368
        public $users;
 
369
 
 
370
        /**
 
371
         * Multisite Blogs table
 
372
         *
 
373
         * @since 3.0.0
 
374
         * @access public
 
375
         * @var string
 
376
         */
 
377
        public $blogs;
 
378
 
 
379
        /**
 
380
         * Multisite Blog Versions table
 
381
         *
 
382
         * @since 3.0.0
 
383
         * @access public
 
384
         * @var string
 
385
         */
 
386
        public $blog_versions;
 
387
 
 
388
        /**
 
389
         * Multisite Registration Log table
 
390
         *
 
391
         * @since 3.0.0
 
392
         * @access public
 
393
         * @var string
 
394
         */
 
395
        public $registration_log;
 
396
 
 
397
        /**
 
398
         * Multisite Signups table
 
399
         *
 
400
         * @since 3.0.0
 
401
         * @access public
 
402
         * @var string
 
403
         */
 
404
        public $signups;
 
405
 
 
406
        /**
 
407
         * Multisite Sites table
 
408
         *
 
409
         * @since 3.0.0
 
410
         * @access public
 
411
         * @var string
 
412
         */
 
413
        public $site;
 
414
 
 
415
        /**
 
416
         * Multisite Sitewide Terms table
 
417
         *
 
418
         * @since 3.0.0
 
419
         * @access public
 
420
         * @var string
 
421
         */
 
422
        public $sitecategories;
 
423
 
 
424
        /**
 
425
         * Multisite Site Metadata table
 
426
         *
 
427
         * @since 3.0.0
 
428
         * @access public
 
429
         * @var string
 
430
         */
 
431
        public $sitemeta;
 
432
 
 
433
        /**
 
434
         * Format specifiers for DB columns. Columns not listed here default to %s. Initialized during WP load.
 
435
         *
 
436
         * Keys are column names, values are format types: 'ID' => '%d'
 
437
         *
 
438
         * @since 2.8.0
 
439
         * @see wpdb::prepare()
 
440
         * @see wpdb::insert()
 
441
         * @see wpdb::update()
 
442
         * @see wpdb::delete()
 
443
         * @see wp_set_wpdb_vars()
 
444
         * @access public
 
445
         * @var array
 
446
         */
 
447
        public $field_types = array();
 
448
 
 
449
        /**
 
450
         * Database table columns charset
 
451
         *
 
452
         * @since 2.2.0
 
453
         * @access public
 
454
         * @var string
 
455
         */
 
456
        public $charset;
 
457
 
 
458
        /**
 
459
         * Database table columns collate
 
460
         *
 
461
         * @since 2.2.0
 
462
         * @access public
 
463
         * @var string
 
464
         */
 
465
        public $collate;
 
466
 
 
467
        /**
 
468
         * Database Username
 
469
         *
 
470
         * @since 2.9.0
 
471
         * @access protected
 
472
         * @var string
 
473
         */
 
474
        protected $dbuser;
 
475
 
 
476
        /**
 
477
         * Database Password
 
478
         *
 
479
         * @since 3.1.0
 
480
         * @access protected
 
481
         * @var string
 
482
         */
 
483
        protected $dbpassword;
 
484
 
 
485
        /**
 
486
         * Database Name
 
487
         *
 
488
         * @since 3.1.0
 
489
         * @access protected
 
490
         * @var string
 
491
         */
 
492
        protected $dbname;
 
493
 
 
494
        /**
 
495
         * Database Host
 
496
         *
 
497
         * @since 3.1.0
 
498
         * @access protected
 
499
         * @var string
 
500
         */
 
501
        protected $dbhost;
 
502
 
 
503
        /**
 
504
         * Database Handle
 
505
         *
 
506
         * @since 0.71
 
507
         * @access protected
 
508
         * @var string
 
509
         */
 
510
        protected $dbh;
 
511
 
 
512
        /**
 
513
         * A textual description of the last query/get_row/get_var call
 
514
         *
 
515
         * @since 3.0.0
 
516
         * @access public
 
517
         * @var string
 
518
         */
 
519
        public $func_call;
 
520
 
 
521
        /**
 
522
         * Whether MySQL is used as the database engine.
 
523
         *
 
524
         * Set in WPDB::db_connect() to true, by default. This is used when checking
 
525
         * against the required MySQL version for WordPress. Normally, a replacement
 
526
         * database drop-in (db.php) will skip these checks, but setting this to true
 
527
         * will force the checks to occur.
 
528
         *
 
529
         * @since 3.3.0
 
530
         * @access public
 
531
         * @var bool
 
532
         */
 
533
        public $is_mysql = null;
 
534
 
 
535
        /**
 
536
         * A list of incompatible SQL modes.
 
537
         *
 
538
         * @since 3.9.0
 
539
         * @access protected
 
540
         * @var array
 
541
         */
 
542
        protected $incompatible_modes = array( 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY',
 
543
                'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL' );
 
544
 
 
545
        /**
 
546
         * Whether to use mysqli over mysql.
 
547
         *
 
548
         * @since 3.9.0
 
549
         * @access private
 
550
         * @var bool
 
551
         */
 
552
        private $use_mysqli = false;
 
553
 
 
554
        /**
 
555
         * Whether we've managed to successfully connect at some point
 
556
         *
 
557
         * @since 3.9.0
 
558
         * @access private
 
559
         * @var bool
 
560
         */
 
561
        private $has_connected = false;
 
562
 
 
563
        /**
 
564
         * Connects to the database server and selects a database
 
565
         *
 
566
         * PHP5 style constructor for compatibility with PHP5. Does
 
567
         * the actual setting up of the class properties and connection
 
568
         * to the database.
 
569
         *
 
570
         * @link http://core.trac.wordpress.org/ticket/3354
 
571
         * @since 2.0.8
 
572
         *
 
573
         * @param string $dbuser MySQL database user
 
574
         * @param string $dbpassword MySQL database password
 
575
         * @param string $dbname MySQL database name
 
576
         * @param string $dbhost MySQL database host
 
577
         */
 
578
        public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) {
 
579
                register_shutdown_function( array( $this, '__destruct' ) );
 
580
 
 
581
                if ( WP_DEBUG && WP_DEBUG_DISPLAY )
 
582
                        $this->show_errors();
 
583
 
 
584
                /* Use ext/mysqli if it exists and:
 
585
                 *  - WP_USE_EXT_MYSQL is defined as false, or
 
586
                 *  - We are a development version of WordPress, or
 
587
                 *  - We are running PHP 5.5 or greater, or
 
588
                 *  - ext/mysql is not loaded.
 
589
                 */
 
590
                if ( function_exists( 'mysqli_connect' ) ) {
 
591
                        if ( defined( 'WP_USE_EXT_MYSQL' ) ) {
 
592
                                $this->use_mysqli = ! WP_USE_EXT_MYSQL;
 
593
                        } elseif ( version_compare( phpversion(), '5.5', '>=' ) || ! function_exists( 'mysql_connect' ) ) {
 
594
                                $this->use_mysqli = true;
 
595
                        } elseif ( false !== strpos( $GLOBALS['wp_version'], '-' ) ) {
 
596
                                $this->use_mysqli = true;
 
597
                        }
 
598
                }
 
599
 
 
600
                $this->init_charset();
 
601
 
 
602
                $this->dbuser = $dbuser;
 
603
                $this->dbpassword = $dbpassword;
 
604
                $this->dbname = $dbname;
 
605
                $this->dbhost = $dbhost;
 
606
 
 
607
                // wp-config.php creation will manually connect when ready.
 
608
                if ( defined( 'WP_SETUP_CONFIG' ) ) {
 
609
                        return;
 
610
                }
 
611
 
 
612
                $this->db_connect();
 
613
        }
 
614
 
 
615
        /**
 
616
         * PHP5 style destructor and will run when database object is destroyed.
 
617
         *
 
618
         * @see wpdb::__construct()
 
619
         * @since 2.0.8
 
620
         * @return bool true
 
621
         */
 
622
        public function __destruct() {
 
623
                return true;
 
624
        }
 
625
 
 
626
        /**
 
627
         * PHP5 style magic getter, used to lazy-load expensive data.
 
628
         *
 
629
         * @since 3.5.0
 
630
         *
 
631
         * @param string $name The private member to get, and optionally process
 
632
         * @return mixed The private member
 
633
         */
 
634
        public function __get( $name ) {
 
635
                if ( 'col_info' == $name )
 
636
                        $this->load_col_info();
 
637
 
 
638
                return $this->$name;
 
639
        }
 
640
 
 
641
        /**
 
642
         * Magic function, for backwards compatibility.
 
643
         *
 
644
         * @since 3.5.0
 
645
         *
 
646
         * @param string $name  The private member to set
 
647
         * @param mixed  $value The value to set
 
648
         */
 
649
        public function __set( $name, $value ) {
 
650
                $this->$name = $value;
 
651
        }
 
652
 
 
653
        /**
 
654
         * Magic function, for backwards compatibility.
 
655
         *
 
656
         * @since 3.5.0
 
657
         *
 
658
         * @param string $name  The private member to check
 
659
         *
 
660
         * @return bool If the member is set or not
 
661
         */
 
662
        public function __isset( $name ) {
 
663
                return isset( $this->$name );
 
664
        }
 
665
 
 
666
        /**
 
667
         * Magic function, for backwards compatibility.
 
668
         *
 
669
         * @since 3.5.0
 
670
         *
 
671
         * @param string $name  The private member to unset
 
672
         */
 
673
        public function __unset( $name ) {
 
674
                unset( $this->$name );
 
675
        }
 
676
 
 
677
        /**
 
678
         * Set $this->charset and $this->collate
 
679
         *
 
680
         * @since 3.1.0
 
681
         */
 
682
        public function init_charset() {
 
683
                if ( function_exists('is_multisite') && is_multisite() ) {
 
684
                        $this->charset = 'utf8';
 
685
                        if ( defined( 'DB_COLLATE' ) && DB_COLLATE )
 
686
                                $this->collate = DB_COLLATE;
 
687
                        else
 
688
                                $this->collate = 'utf8_general_ci';
 
689
                } elseif ( defined( 'DB_COLLATE' ) ) {
 
690
                        $this->collate = DB_COLLATE;
 
691
                }
 
692
 
 
693
                if ( defined( 'DB_CHARSET' ) )
 
694
                        $this->charset = DB_CHARSET;
 
695
        }
 
696
 
 
697
        /**
 
698
         * Sets the connection's character set.
 
699
         *
 
700
         * @since 3.1.0
 
701
         *
 
702
         * @param resource $dbh     The resource given by mysql_connect
 
703
         * @param string   $charset The character set (optional)
 
704
         * @param string   $collate The collation (optional)
 
705
         */
 
706
        public function set_charset( $dbh, $charset = null, $collate = null ) {
 
707
                if ( ! isset( $charset ) )
 
708
                        $charset = $this->charset;
 
709
                if ( ! isset( $collate ) )
 
710
                        $collate = $this->collate;
 
711
                if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) {
 
712
                        if ( $this->use_mysqli ) {
 
713
                                if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) {
 
714
                                        mysqli_set_charset( $dbh, $charset );
 
715
                                } else {
 
716
                                        $query = $this->prepare( 'SET NAMES %s', $charset );
 
717
                                        if ( ! empty( $collate ) )
 
718
                                                $query .= $this->prepare( ' COLLATE %s', $collate );
 
719
                                        mysqli_query( $query, $dbh );
 
720
                                }
 
721
                        } else {
 
722
                                if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) {
 
723
                                        mysql_set_charset( $charset, $dbh );
 
724
                                } else {
 
725
                                        $query = $this->prepare( 'SET NAMES %s', $charset );
 
726
                                        if ( ! empty( $collate ) )
 
727
                                                $query .= $this->prepare( ' COLLATE %s', $collate );
 
728
                                        mysql_query( $query, $dbh );
 
729
                                }
 
730
                        }
 
731
                }
 
732
        }
 
733
 
 
734
        /**
 
735
         * Change the current SQL mode, and ensure its WordPress compatibility.
 
736
         *
 
737
         * If no modes are passed, it will ensure the current MySQL server
 
738
         * modes are compatible.
 
739
         *
 
740
         * @since 3.9.0
 
741
         *
 
742
         * @param array $modes Optional. A list of SQL modes to set.
 
743
         */
 
744
        public function set_sql_mode( $modes = array() ) {
 
745
                if ( empty( $modes ) ) {
 
746
                        if ( $this->use_mysqli ) {
 
747
                                $res = mysqli_query( $this->dbh, 'SELECT @@SESSION.sql_mode' );
 
748
                        } else {
 
749
                                $res = mysql_query( 'SELECT @@SESSION.sql_mode', $this->dbh );
 
750
                        }
 
751
 
 
752
                        if ( empty( $res ) ) {
 
753
                                return;
 
754
                        }
 
755
 
 
756
                        if ( $this->use_mysqli ) {
 
757
                                $modes_array = mysqli_fetch_array( $res );
 
758
                                if ( empty( $modes_array[0] ) ) {
 
759
                                        return;
 
760
                                }
 
761
                                $modes_str = $modes_array[0];
 
762
                        } else {
 
763
                                $modes_str = mysql_result( $res, 0 );
 
764
                        }
 
765
 
 
766
                        if ( empty( $modes_str ) ) {
 
767
                                return;
 
768
                        }
 
769
 
 
770
                        $modes = explode( ',', $modes_str );
 
771
                }
 
772
 
 
773
                $modes = array_change_key_case( $modes, CASE_UPPER );
 
774
 
 
775
                /**
 
776
                 * Filter the list of incompatible SQL modes to exclude.
 
777
                 *
 
778
                 * @since 3.9.0
 
779
                 *
 
780
                 * @see wpdb::$incompatible_modes
 
781
                 *
 
782
                 * @param array $incompatible_modes An array of incompatible modes.
 
783
                 */
 
784
                $incompatible_modes = (array) apply_filters( 'incompatible_sql_modes', $this->incompatible_modes );
 
785
 
 
786
                foreach( $modes as $i => $mode ) {
 
787
                        if ( in_array( $mode, $incompatible_modes ) ) {
 
788
                                unset( $modes[ $i ] );
 
789
                        }
 
790
                }
 
791
 
 
792
                $modes_str = implode( ',', $modes );
 
793
 
 
794
                if ( $this->use_mysqli ) {
 
795
                        mysqli_query( $this->dbh, "SET SESSION sql_mode='$modes_str'" );
 
796
                } else {
 
797
                        mysql_query( "SET SESSION sql_mode='$modes_str'", $this->dbh );
 
798
                }
 
799
        }
 
800
 
 
801
        /**
 
802
         * Sets the table prefix for the WordPress tables.
 
803
         *
 
804
         * @since 2.5.0
 
805
         *
 
806
         * @param string $prefix Alphanumeric name for the new prefix.
 
807
         * @param bool $set_table_names Optional. Whether the table names, e.g. wpdb::$posts, should be updated or not.
 
808
         * @return string|WP_Error Old prefix or WP_Error on error
 
809
         */
 
810
        public function set_prefix( $prefix, $set_table_names = true ) {
 
811
 
 
812
                if ( preg_match( '|[^a-z0-9_]|i', $prefix ) )
 
813
                        return new WP_Error('invalid_db_prefix', 'Invalid database prefix' );
 
814
 
 
815
                $old_prefix = is_multisite() ? '' : $prefix;
 
816
 
 
817
                if ( isset( $this->base_prefix ) )
 
818
                        $old_prefix = $this->base_prefix;
 
819
 
 
820
                $this->base_prefix = $prefix;
 
821
 
 
822
                if ( $set_table_names ) {
 
823
                        foreach ( $this->tables( 'global' ) as $table => $prefixed_table )
 
824
                                $this->$table = $prefixed_table;
 
825
 
 
826
                        if ( is_multisite() && empty( $this->blogid ) )
 
827
                                return $old_prefix;
 
828
 
 
829
                        $this->prefix = $this->get_blog_prefix();
 
830
 
 
831
                        foreach ( $this->tables( 'blog' ) as $table => $prefixed_table )
 
832
                                $this->$table = $prefixed_table;
 
833
 
 
834
                        foreach ( $this->tables( 'old' ) as $table => $prefixed_table )
 
835
                                $this->$table = $prefixed_table;
 
836
                }
 
837
                return $old_prefix;
 
838
        }
 
839
 
 
840
        /**
 
841
         * Sets blog id.
 
842
         *
 
843
         * @since 3.0.0
 
844
         * @access public
 
845
         * @param int $blog_id
 
846
         * @param int $site_id Optional.
 
847
         * @return string previous blog id
 
848
         */
 
849
        public function set_blog_id( $blog_id, $site_id = 0 ) {
 
850
                if ( ! empty( $site_id ) )
 
851
                        $this->siteid = $site_id;
 
852
 
 
853
                $old_blog_id  = $this->blogid;
 
854
                $this->blogid = $blog_id;
 
855
 
 
856
                $this->prefix = $this->get_blog_prefix();
 
857
 
 
858
                foreach ( $this->tables( 'blog' ) as $table => $prefixed_table )
 
859
                        $this->$table = $prefixed_table;
 
860
 
 
861
                foreach ( $this->tables( 'old' ) as $table => $prefixed_table )
 
862
                        $this->$table = $prefixed_table;
 
863
 
 
864
                return $old_blog_id;
 
865
        }
 
866
 
 
867
        /**
 
868
         * Gets blog prefix.
 
869
         *
 
870
         * @uses is_multisite()
 
871
         * @since 3.0.0
 
872
         * @param int $blog_id Optional.
 
873
         * @return string Blog prefix.
 
874
         */
 
875
        public function get_blog_prefix( $blog_id = null ) {
 
876
                if ( is_multisite() ) {
 
877
                        if ( null === $blog_id )
 
878
                                $blog_id = $this->blogid;
 
879
                        $blog_id = (int) $blog_id;
 
880
                        if ( defined( 'MULTISITE' ) && ( 0 == $blog_id || 1 == $blog_id ) )
 
881
                                return $this->base_prefix;
 
882
                        else
 
883
                                return $this->base_prefix . $blog_id . '_';
 
884
                } else {
 
885
                        return $this->base_prefix;
 
886
                }
 
887
        }
 
888
 
 
889
        /**
 
890
         * Returns an array of WordPress tables.
 
891
         *
 
892
         * Also allows for the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE to
 
893
         * override the WordPress users and usermeta tables that would otherwise
 
894
         * be determined by the prefix.
 
895
         *
 
896
         * The scope argument can take one of the following:
 
897
         *
 
898
         * 'all' - returns 'all' and 'global' tables. No old tables are returned.
 
899
         * 'blog' - returns the blog-level tables for the queried blog.
 
900
         * 'global' - returns the global tables for the installation, returning multisite tables only if running multisite.
 
901
         * 'ms_global' - returns the multisite global tables, regardless if current installation is multisite.
 
902
         * 'old' - returns tables which are deprecated.
 
903
         *
 
904
         * @since 3.0.0
 
905
         * @uses wpdb::$tables
 
906
         * @uses wpdb::$old_tables
 
907
         * @uses wpdb::$global_tables
 
908
         * @uses wpdb::$ms_global_tables
 
909
         * @uses is_multisite()
 
910
         *
 
911
         * @param string $scope Optional. Can be all, global, ms_global, blog, or old tables. Defaults to all.
 
912
         * @param bool $prefix Optional. Whether to include table prefixes. Default true. If blog
 
913
         *      prefix is requested, then the custom users and usermeta tables will be mapped.
 
914
         * @param int $blog_id Optional. The blog_id to prefix. Defaults to wpdb::$blogid. Used only when prefix is requested.
 
915
         * @return array Table names. When a prefix is requested, the key is the unprefixed table name.
 
916
         */
 
917
        public function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) {
 
918
                switch ( $scope ) {
 
919
                        case 'all' :
 
920
                                $tables = array_merge( $this->global_tables, $this->tables );
 
921
                                if ( is_multisite() )
 
922
                                        $tables = array_merge( $tables, $this->ms_global_tables );
 
923
                                break;
 
924
                        case 'blog' :
 
925
                                $tables = $this->tables;
 
926
                                break;
 
927
                        case 'global' :
 
928
                                $tables = $this->global_tables;
 
929
                                if ( is_multisite() )
 
930
                                        $tables = array_merge( $tables, $this->ms_global_tables );
 
931
                                break;
 
932
                        case 'ms_global' :
 
933
                                $tables = $this->ms_global_tables;
 
934
                                break;
 
935
                        case 'old' :
 
936
                                $tables = $this->old_tables;
 
937
                                break;
 
938
                        default :
 
939
                                return array();
 
940
                }
 
941
 
 
942
                if ( $prefix ) {
 
943
                        if ( ! $blog_id )
 
944
                                $blog_id = $this->blogid;
 
945
                        $blog_prefix = $this->get_blog_prefix( $blog_id );
 
946
                        $base_prefix = $this->base_prefix;
 
947
                        $global_tables = array_merge( $this->global_tables, $this->ms_global_tables );
 
948
                        foreach ( $tables as $k => $table ) {
 
949
                                if ( in_array( $table, $global_tables ) )
 
950
                                        $tables[ $table ] = $base_prefix . $table;
 
951
                                else
 
952
                                        $tables[ $table ] = $blog_prefix . $table;
 
953
                                unset( $tables[ $k ] );
 
954
                        }
 
955
 
 
956
                        if ( isset( $tables['users'] ) && defined( 'CUSTOM_USER_TABLE' ) )
 
957
                                $tables['users'] = CUSTOM_USER_TABLE;
 
958
 
 
959
                        if ( isset( $tables['usermeta'] ) && defined( 'CUSTOM_USER_META_TABLE' ) )
 
960
                                $tables['usermeta'] = CUSTOM_USER_META_TABLE;
 
961
                }
 
962
 
 
963
                return $tables;
 
964
        }
 
965
 
 
966
        /**
 
967
         * Selects a database using the current database connection.
 
968
         *
 
969
         * The database name will be changed based on the current database
 
970
         * connection. On failure, the execution will bail and display an DB error.
 
971
         *
 
972
         * @since 0.71
 
973
         *
 
974
         * @param string $db MySQL database name
 
975
         * @param resource $dbh Optional link identifier.
 
976
         * @return null Always null.
 
977
         */
 
978
        public function select( $db, $dbh = null ) {
 
979
                if ( is_null($dbh) )
 
980
                        $dbh = $this->dbh;
 
981
 
 
982
                if ( $this->use_mysqli ) {
 
983
                        $success = @mysqli_select_db( $dbh, $db );
 
984
                } else {
 
985
                        $success = @mysql_select_db( $db, $dbh );
 
986
                }
 
987
                if ( ! $success ) {
 
988
                        $this->ready = false;
 
989
                        if ( ! did_action( 'template_redirect' ) ) {
 
990
                                wp_load_translations_early();
 
991
                                $this->bail( sprintf( __( '<h1>Can&#8217;t select database</h1>
 
992
<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>
 
993
<ul>
 
994
<li>Are you sure it exists?</li>
 
995
<li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li>
 
996
<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>
 
997
</ul>
 
998
<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' );
 
999
                        }
 
1000
                        return;
 
1001
                }
 
1002
        }
 
1003
 
 
1004
        /**
 
1005
         * Do not use, deprecated.
 
1006
         *
 
1007
         * Use esc_sql() or wpdb::prepare() instead.
 
1008
         *
 
1009
         * @since 2.8.0
 
1010
         * @deprecated 3.6.0
 
1011
         * @see wpdb::prepare
 
1012
         * @see esc_sql()
 
1013
         * @access private
 
1014
         *
 
1015
         * @param string $string
 
1016
         * @return string
 
1017
         */
 
1018
        function _weak_escape( $string ) {
 
1019
                if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) )
 
1020
                        _deprecated_function( __METHOD__, '3.6', 'wpdb::prepare() or esc_sql()' );
 
1021
                return addslashes( $string );
 
1022
        }
 
1023
 
 
1024
        /**
 
1025
         * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string()
 
1026
         *
 
1027
         * @see mysqli_real_escape_string()
 
1028
         * @see mysql_real_escape_string()
 
1029
         * @since 2.8.0
 
1030
         * @access private
 
1031
         *
 
1032
         * @param  string $string to escape
 
1033
         * @return string escaped
 
1034
         */
 
1035
        function _real_escape( $string ) {
 
1036
                if ( $this->dbh ) {
 
1037
                        if ( $this->use_mysqli ) {
 
1038
                                return mysqli_real_escape_string( $this->dbh, $string );
 
1039
                        } else {
 
1040
                                return mysql_real_escape_string( $string, $this->dbh );
 
1041
                        }
 
1042
                }
 
1043
 
 
1044
                $class = get_class( $this );
 
1045
                _doing_it_wrong( $class, "$class must set a database connection for use with escaping.", E_USER_NOTICE );
 
1046
                return addslashes( $string );
 
1047
        }
 
1048
 
 
1049
        /**
 
1050
         * Escape data. Works on arrays.
 
1051
         *
 
1052
         * @uses wpdb::_real_escape()
 
1053
         * @since  2.8.0
 
1054
         * @access private
 
1055
         *
 
1056
         * @param  string|array $data
 
1057
         * @return string|array escaped
 
1058
         */
 
1059
        function _escape( $data ) {
 
1060
                if ( is_array( $data ) ) {
 
1061
                        foreach ( $data as $k => $v ) {
 
1062
                                if ( is_array($v) )
 
1063
                                        $data[$k] = $this->_escape( $v );
 
1064
                                else
 
1065
                                        $data[$k] = $this->_real_escape( $v );
 
1066
                        }
 
1067
                } else {
 
1068
                        $data = $this->_real_escape( $data );
 
1069
                }
 
1070
 
 
1071
                return $data;
 
1072
        }
 
1073
 
 
1074
        /**
 
1075
         * Do not use, deprecated.
 
1076
         *
 
1077
         * Use esc_sql() or wpdb::prepare() instead.
 
1078
         *
 
1079
         * @since 0.71
 
1080
         * @deprecated 3.6.0
 
1081
         * @see wpdb::prepare()
 
1082
         * @see esc_sql()
 
1083
         *
 
1084
         * @param mixed $data
 
1085
         * @return mixed
 
1086
         */
 
1087
        public function escape( $data ) {
 
1088
                if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) )
 
1089
                        _deprecated_function( __METHOD__, '3.6', 'wpdb::prepare() or esc_sql()' );
 
1090
                if ( is_array( $data ) ) {
 
1091
                        foreach ( $data as $k => $v ) {
 
1092
                                if ( is_array( $v ) )
 
1093
                                        $data[$k] = $this->escape( $v, 'recursive' );
 
1094
                                else
 
1095
                                        $data[$k] = $this->_weak_escape( $v, 'internal' );
 
1096
                        }
 
1097
                } else {
 
1098
                        $data = $this->_weak_escape( $data, 'internal' );
 
1099
                }
 
1100
 
 
1101
                return $data;
 
1102
        }
 
1103
 
 
1104
        /**
 
1105
         * Escapes content by reference for insertion into the database, for security
 
1106
         *
 
1107
         * @uses wpdb::_real_escape()
 
1108
         * @since 2.3.0
 
1109
         * @param string $string to escape
 
1110
         * @return void
 
1111
         */
 
1112
        public function escape_by_ref( &$string ) {
 
1113
                if ( ! is_float( $string ) )
 
1114
                        $string = $this->_real_escape( $string );
 
1115
        }
 
1116
 
 
1117
        /**
 
1118
         * Prepares a SQL query for safe execution. Uses sprintf()-like syntax.
 
1119
         *
 
1120
         * The following directives can be used in the query format string:
 
1121
         *   %d (integer)
 
1122
         *   %f (float)
 
1123
         *   %s (string)
 
1124
         *   %% (literal percentage sign - no argument needed)
 
1125
         *
 
1126
         * All of %d, %f, and %s are to be left unquoted in the query string and they need an argument passed for them.
 
1127
         * Literals (%) as parts of the query must be properly written as %%.
 
1128
         *
 
1129
         * This function only supports a small subset of the sprintf syntax; it only supports %d (integer), %f (float), and %s (string).
 
1130
         * Does not support sign, padding, alignment, width or precision specifiers.
 
1131
         * Does not support argument numbering/swapping.
 
1132
         *
 
1133
         * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}.
 
1134
         *
 
1135
         * Both %d and %s should be left unquoted in the query string.
 
1136
         *
 
1137
         * <code>
 
1138
         * wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", 'foo', 1337 )
 
1139
         * wpdb::prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' );
 
1140
         * </code>
 
1141
         *
 
1142
         * @link http://php.net/sprintf Description of syntax.
 
1143
         * @since 2.3.0
 
1144
         *
 
1145
         * @param string $query Query statement with sprintf()-like placeholders
 
1146
         * @param array|mixed $args The array of variables to substitute into the query's placeholders if being called like
 
1147
         *      {@link http://php.net/vsprintf vsprintf()}, or the first variable to substitute into the query's placeholders if
 
1148
         *      being called like {@link http://php.net/sprintf sprintf()}.
 
1149
         * @param mixed $args,... further variables to substitute into the query's placeholders if being called like
 
1150
         *      {@link http://php.net/sprintf sprintf()}.
 
1151
         * @return null|false|string Sanitized query string, null if there is no query, false if there is an error and string
 
1152
         *      if there was something to prepare
 
1153
         */
 
1154
        public function prepare( $query, $args ) {
 
1155
                if ( is_null( $query ) )
 
1156
                        return;
 
1157
 
 
1158
                // This is not meant to be foolproof -- but it will catch obviously incorrect usage.
 
1159
                if ( strpos( $query, '%' ) === false ) {
 
1160
                        _doing_it_wrong( 'wpdb::prepare', sprintf( __( 'The query argument of %s must have a placeholder.' ), 'wpdb::prepare()' ), '3.9' );
 
1161
                }
 
1162
 
 
1163
                $args = func_get_args();
 
1164
                array_shift( $args );
 
1165
                // If args were passed as an array (as in vsprintf), move them up
 
1166
                if ( isset( $args[0] ) && is_array($args[0]) )
 
1167
                        $args = $args[0];
 
1168
                $query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it
 
1169
                $query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
 
1170
                $query = preg_replace( '|(?<!%)%f|' , '%F', $query ); // Force floats to be locale unaware
 
1171
                $query = preg_replace( '|(?<!%)%s|', "'%s'", $query ); // quote the strings, avoiding escaped strings like %%s
 
1172
                array_walk( $args, array( $this, 'escape_by_ref' ) );
 
1173
                return @vsprintf( $query, $args );
 
1174
        }
 
1175
 
 
1176
        /**
 
1177
         * First half of escaping for LIKE special characters % and _ before preparing for MySQL.
 
1178
         *
 
1179
         * Use this only before wpdb::prepare() or esc_sql().  Reversing the order is very bad for security.
 
1180
         *
 
1181
         * Example Prepared Statement:
 
1182
         *  $wild = '%';
 
1183
         *  $find = 'only 43% of planets';
 
1184
         *  $like = $wild . $wpdb->esc_like( $find ) . $wild;
 
1185
         *  $sql  = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like );
 
1186
         *
 
1187
         * Example Escape Chain:
 
1188
         *  $sql  = esc_sql( $wpdb->esc_like( $input ) );
 
1189
         *
 
1190
         * @since 4.0.0
 
1191
         * @access public
 
1192
         *
 
1193
         * @param string $text The raw text to be escaped. The input typed by the user should have no
 
1194
         *                     extra or deleted slashes.
 
1195
         * @return string Text in the form of a LIKE phrase. The output is not SQL safe. Call $wpdb::prepare()
 
1196
         *                or real_escape next.
 
1197
         */
 
1198
        public function esc_like( $text ) {
 
1199
                return addcslashes( $text, '_%\\' );
 
1200
        }
 
1201
 
 
1202
        /**
 
1203
         * Print SQL/DB error.
 
1204
         *
 
1205
         * @since 0.71
 
1206
         * @global array $EZSQL_ERROR Stores error information of query and error string
 
1207
         *
 
1208
         * @param string $str The error to display
 
1209
         * @return bool False if the showing of errors is disabled.
 
1210
         */
 
1211
        public function print_error( $str = '' ) {
 
1212
                global $EZSQL_ERROR;
 
1213
 
 
1214
                if ( !$str ) {
 
1215
                        if ( $this->use_mysqli ) {
 
1216
                                $str = mysqli_error( $this->dbh );
 
1217
                        } else {
 
1218
                                $str = mysql_error( $this->dbh );
 
1219
                        }
 
1220
                }
 
1221
                $EZSQL_ERROR[] = array( 'query' => $this->last_query, 'error_str' => $str );
 
1222
 
 
1223
                if ( $this->suppress_errors )
 
1224
                        return false;
 
1225
 
 
1226
                wp_load_translations_early();
 
1227
 
 
1228
                if ( $caller = $this->get_caller() )
 
1229
                        $error_str = sprintf( __( 'WordPress database error %1$s for query %2$s made by %3$s' ), $str, $this->last_query, $caller );
 
1230
                else
 
1231
                        $error_str = sprintf( __( 'WordPress database error %1$s for query %2$s' ), $str, $this->last_query );
 
1232
 
 
1233
                error_log( $error_str );
 
1234
 
 
1235
                // Are we showing errors?
 
1236
                if ( ! $this->show_errors )
 
1237
                        return false;
 
1238
 
 
1239
                // If there is an error then take note of it
 
1240
                if ( is_multisite() ) {
 
1241
                        $msg = "WordPress database error: [$str]\n{$this->last_query}\n";
 
1242
                        if ( defined( 'ERRORLOGFILE' ) )
 
1243
                                error_log( $msg, 3, ERRORLOGFILE );
 
1244
                        if ( defined( 'DIEONDBERROR' ) )
 
1245
                                wp_die( $msg );
 
1246
                } else {
 
1247
                        $str   = htmlspecialchars( $str, ENT_QUOTES );
 
1248
                        $query = htmlspecialchars( $this->last_query, ENT_QUOTES );
 
1249
 
 
1250
                        print "<div id='error'>
 
1251
                        <p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br />
 
1252
                        <code>$query</code></p>
 
1253
                        </div>";
 
1254
                }
 
1255
        }
 
1256
 
 
1257
        /**
 
1258
         * Enables showing of database errors.
 
1259
         *
 
1260
         * This function should be used only to enable showing of errors.
 
1261
         * wpdb::hide_errors() should be used instead for hiding of errors. However,
 
1262
         * this function can be used to enable and disable showing of database
 
1263
         * errors.
 
1264
         *
 
1265
         * @since 0.71
 
1266
         * @see wpdb::hide_errors()
 
1267
         *
 
1268
         * @param bool $show Whether to show or hide errors
 
1269
         * @return bool Old value for showing errors.
 
1270
         */
 
1271
        public function show_errors( $show = true ) {
 
1272
                $errors = $this->show_errors;
 
1273
                $this->show_errors = $show;
 
1274
                return $errors;
 
1275
        }
 
1276
 
 
1277
        /**
 
1278
         * Disables showing of database errors.
 
1279
         *
 
1280
         * By default database errors are not shown.
 
1281
         *
 
1282
         * @since 0.71
 
1283
         * @see wpdb::show_errors()
 
1284
         *
 
1285
         * @return bool Whether showing of errors was active
 
1286
         */
 
1287
        public function hide_errors() {
 
1288
                $show = $this->show_errors;
 
1289
                $this->show_errors = false;
 
1290
                return $show;
 
1291
        }
 
1292
 
 
1293
        /**
 
1294
         * Whether to suppress database errors.
 
1295
         *
 
1296
         * By default database errors are suppressed, with a simple
 
1297
         * call to this function they can be enabled.
 
1298
         *
 
1299
         * @since 2.5.0
 
1300
         * @see wpdb::hide_errors()
 
1301
         * @param bool $suppress Optional. New value. Defaults to true.
 
1302
         * @return bool Old value
 
1303
         */
 
1304
        public function suppress_errors( $suppress = true ) {
 
1305
                $errors = $this->suppress_errors;
 
1306
                $this->suppress_errors = (bool) $suppress;
 
1307
                return $errors;
 
1308
        }
 
1309
 
 
1310
        /**
 
1311
         * Kill cached query results.
 
1312
         *
 
1313
         * @since 0.71
 
1314
         * @return void
 
1315
         */
 
1316
        public function flush() {
 
1317
                $this->last_result = array();
 
1318
                $this->col_info    = null;
 
1319
                $this->last_query  = null;
 
1320
                $this->rows_affected = $this->num_rows = 0;
 
1321
                $this->last_error  = '';
 
1322
 
 
1323
                if ( is_resource( $this->result ) ) {
 
1324
                        if ( $this->use_mysqli ) {
 
1325
                                mysqli_free_result( $this->result );
 
1326
                        } else {
 
1327
                                mysql_free_result( $this->result );
 
1328
                        }
 
1329
                }
 
1330
        }
 
1331
 
 
1332
        /**
 
1333
         * Connect to and select database.
 
1334
         *
 
1335
         * If $allow_bail is false, the lack of database connection will need
 
1336
         * to be handled manually.
 
1337
         *
 
1338
         * @since 3.0.0
 
1339
         * @since 3.9.0 $allow_bail parameter added.
 
1340
         *
 
1341
         * @param bool $allow_bail Optional. Allows the function to bail. Default true.
 
1342
         * @return bool True with a successful connection, false on failure.
 
1343
         */
 
1344
        public function db_connect( $allow_bail = true ) {
 
1345
 
 
1346
                $this->is_mysql = true;
 
1347
 
 
1348
                /*
 
1349
                 * Deprecated in 3.9+ when using MySQLi. No equivalent
 
1350
                 * $new_link parameter exists for mysqli_* functions.
 
1351
                 */
 
1352
                $new_link = defined( 'MYSQL_NEW_LINK' ) ? MYSQL_NEW_LINK : true;
 
1353
                $client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0;
 
1354
 
 
1355
                if ( $this->use_mysqli ) {
 
1356
                        $this->dbh = mysqli_init();
 
1357
 
 
1358
                        // mysqli_real_connect doesn't support the host param including a port or socket
 
1359
                        // like mysql_connect does. This duplicates how mysql_connect detects a port and/or socket file.
 
1360
                        $port = null;
 
1361
                        $socket = null;
 
1362
                        $host = $this->dbhost;
 
1363
                        $port_or_socket = strstr( $host, ':' );
 
1364
                        if ( ! empty( $port_or_socket ) ) {
 
1365
                                $host = substr( $host, 0, strpos( $host, ':' ) );
 
1366
                                $port_or_socket = substr( $port_or_socket, 1 );
 
1367
                                if ( 0 !== strpos( $port_or_socket, '/' ) ) {
 
1368
                                        $port = intval( $port_or_socket );
 
1369
                                        $maybe_socket = strstr( $port_or_socket, ':' );
 
1370
                                        if ( ! empty( $maybe_socket ) ) {
 
1371
                                                $socket = substr( $maybe_socket, 1 );
 
1372
                                        }
 
1373
                                } else {
 
1374
                                        $socket = $port_or_socket;
 
1375
                                }
 
1376
                        }
 
1377
 
 
1378
                        if ( WP_DEBUG ) {
 
1379
                                mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
 
1380
                        } else {
 
1381
                                @mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
 
1382
                        }
 
1383
 
 
1384
                        if ( $this->dbh->connect_errno ) {
 
1385
                                $this->dbh = null;
 
1386
 
 
1387
                                /* It's possible ext/mysqli is misconfigured. Fall back to ext/mysql if:
 
1388
                                 *  - We haven't previously connected, and
 
1389
                                 *  - WP_USE_EXT_MYSQL isn't set to false, and
 
1390
                                 *  - ext/mysql is loaded.
 
1391
                                 */
 
1392
                                $attempt_fallback = true;
 
1393
 
 
1394
                                if ( $this->has_connected ) {
 
1395
                                        $attempt_fallback = false;
 
1396
                                } else if ( defined( 'WP_USE_EXT_MYSQL' ) && ! WP_USE_EXT_MYSQL ) {
 
1397
                                        $attempt_fallback = false;
 
1398
                                } else if ( ! function_exists( 'mysql_connect' ) ) {
 
1399
                                        $attempt_fallback = false;
 
1400
                                }
 
1401
 
 
1402
                                if ( $attempt_fallback ) {
 
1403
                                        $this->use_mysqli = false;
 
1404
                                        $this->db_connect();
 
1405
                                }
 
1406
                        }
 
1407
                } else {
 
1408
                        if ( WP_DEBUG ) {
 
1409
                                $this->dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags );
 
1410
                        } else {
 
1411
                                $this->dbh = @mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags );
 
1412
                        }
 
1413
                }
 
1414
 
 
1415
                if ( ! $this->dbh && $allow_bail ) {
 
1416
                        wp_load_translations_early();
 
1417
 
 
1418
                        // Load custom DB error template, if present.
 
1419
                        if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) {
 
1420
                                require_once( WP_CONTENT_DIR . '/db-error.php' );
 
1421
                                die();
 
1422
                        }
 
1423
 
 
1424
                        $this->bail( sprintf( __( "
 
1425
<h1>Error establishing a database connection</h1>
 
1426
<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>
 
1427
<ul>
 
1428
        <li>Are you sure you have the correct username and password?</li>
 
1429
        <li>Are you sure that you have typed the correct hostname?</li>
 
1430
        <li>Are you sure that the database server is running?</li>
 
1431
</ul>
 
1432
<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>
 
1433
" ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' );
 
1434
 
 
1435
                        return false;
 
1436
                } else if ( $this->dbh ) {
 
1437
                        $this->has_connected = true;
 
1438
                        $this->set_charset( $this->dbh );
 
1439
                        $this->set_sql_mode();
 
1440
                        $this->ready = true;
 
1441
                        $this->select( $this->dbname, $this->dbh );
 
1442
 
 
1443
                        return true;
 
1444
                }
 
1445
 
 
1446
                return false;
 
1447
        }
 
1448
 
 
1449
        /**
 
1450
         * Check that the connection to the database is still up. If not, try to reconnect.
 
1451
         *
 
1452
         * If this function is unable to reconnect, it will forcibly die, or if after the
 
1453
         * the template_redirect hook has been fired, return false instead.
 
1454
         *
 
1455
         * If $allow_bail is false, the lack of database connection will need
 
1456
         * to be handled manually.
 
1457
         *
 
1458
         * @since 3.9.0
 
1459
         *
 
1460
         * @param bool $allow_bail Optional. Allows the function to bail. Default true.
 
1461
         * @return bool True if the connection is up.
 
1462
         */
 
1463
        public function check_connection( $allow_bail = true ) {
 
1464
                if ( $this->use_mysqli ) {
 
1465
                        if ( @mysqli_ping( $this->dbh ) ) {
 
1466
                                return true;
 
1467
                        }
 
1468
                } else {
 
1469
                        if ( @mysql_ping( $this->dbh ) ) {
 
1470
                                return true;
 
1471
                        }
 
1472
                }
 
1473
 
 
1474
                $error_reporting = false;
 
1475
 
 
1476
                // Disable warnings, as we don't want to see a multitude of "unable to connect" messages
 
1477
                if ( WP_DEBUG ) {
 
1478
                        $error_reporting = error_reporting();
 
1479
                        error_reporting( $error_reporting & ~E_WARNING );
 
1480
                }
 
1481
 
 
1482
                for ( $tries = 1; $tries <= $this->reconnect_retries; $tries++ ) {
 
1483
                        // On the last try, re-enable warnings. We want to see a single instance of the
 
1484
                        // "unable to connect" message on the bail() screen, if it appears.
 
1485
                        if ( $this->reconnect_retries === $tries && WP_DEBUG ) {
 
1486
                                error_reporting( $error_reporting );
 
1487
                        }
 
1488
 
 
1489
                        if ( $this->db_connect( false ) ) {
 
1490
                                if ( $error_reporting ) {
 
1491
                                        error_reporting( $error_reporting );
 
1492
                                }
 
1493
 
 
1494
                                return true;
 
1495
                        }
 
1496
 
 
1497
                        sleep( 1 );
 
1498
                }
 
1499
 
 
1500
                // If template_redirect has already happened, it's too late for wp_die()/dead_db().
 
1501
                // Let's just return and hope for the best.
 
1502
                if ( did_action( 'template_redirect' ) ) {
 
1503
                        return false;
 
1504
                }
 
1505
 
 
1506
                if ( ! $allow_bail ) {
 
1507
                        return false;
 
1508
                }
 
1509
 
 
1510
                // We weren't able to reconnect, so we better bail.
 
1511
                $this->bail( sprintf( ( "
 
1512
<h1>Error reconnecting to the database</h1>
 
1513
<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>
 
1514
<ul>
 
1515
        <li>Are you sure that the database server is running?</li>
 
1516
        <li>Are you sure that the database server is not under particularly heavy load?</li>
 
1517
</ul>
 
1518
<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>
 
1519
" ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' );
 
1520
 
 
1521
                // Call dead_db() if bail didn't die, because this database is no more. It has ceased to be (at least temporarily).
 
1522
                dead_db();
 
1523
        }
 
1524
 
 
1525
        /**
 
1526
         * Perform a MySQL database query, using current database connection.
 
1527
         *
 
1528
         * More information can be found on the codex page.
 
1529
         *
 
1530
         * @since 0.71
 
1531
         *
 
1532
         * @param string $query Database query
 
1533
         * @return int|false Number of rows affected/selected or false on error
 
1534
         */
 
1535
        public function query( $query ) {
 
1536
                if ( ! $this->ready )
 
1537
                        return false;
 
1538
 
 
1539
                /**
 
1540
                 * Filter the database query.
 
1541
                 *
 
1542
                 * Some queries are made before the plugins have been loaded,
 
1543
                 * and thus cannot be filtered with this method.
 
1544
                 *
 
1545
                 * @since 2.1.0
 
1546
                 *
 
1547
                 * @param string $query Database query.
 
1548
                 */
 
1549
                $query = apply_filters( 'query', $query );
 
1550
 
 
1551
                $this->flush();
 
1552
 
 
1553
                // Log how the function was called
 
1554
                $this->func_call = "\$db->query(\"$query\")";
 
1555
 
 
1556
                // Keep track of the last query for debug..
 
1557
                $this->last_query = $query;
 
1558
 
 
1559
                $this->_do_query( $query );
 
1560
 
 
1561
                // MySQL server has gone away, try to reconnect
 
1562
                $mysql_errno = 0;
 
1563
                if ( ! empty( $this->dbh ) ) {
 
1564
                        if ( $this->use_mysqli ) {
 
1565
                                $mysql_errno = mysqli_errno( $this->dbh );
 
1566
                        } else {
 
1567
                                $mysql_errno = mysql_errno( $this->dbh );
 
1568
                        }
 
1569
                }
 
1570
 
 
1571
                if ( empty( $this->dbh ) || 2006 == $mysql_errno ) {
 
1572
                        if ( $this->check_connection() ) {
 
1573
                                $this->_do_query( $query );
 
1574
                        } else {
 
1575
                                $this->insert_id = 0;
 
1576
                                return false;
 
1577
                        }
 
1578
                }
 
1579
 
 
1580
                // If there is an error then take note of it..
 
1581
                if ( $this->use_mysqli ) {
 
1582
                        $this->last_error = mysqli_error( $this->dbh );
 
1583
                } else {
 
1584
                        $this->last_error = mysql_error( $this->dbh );
 
1585
                }
 
1586
 
 
1587
                if ( $this->last_error ) {
 
1588
                        // Clear insert_id on a subsequent failed insert.
 
1589
                        if ( $this->insert_id && preg_match( '/^\s*(insert|replace)\s/i', $query ) )
 
1590
                                $this->insert_id = 0;
 
1591
 
 
1592
                        $this->print_error();
 
1593
                        return false;
 
1594
                }
 
1595
 
 
1596
                if ( preg_match( '/^\s*(create|alter|truncate|drop)\s/i', $query ) ) {
 
1597
                        $return_val = $this->result;
 
1598
                } elseif ( preg_match( '/^\s*(insert|delete|update|replace)\s/i', $query ) ) {
 
1599
                        if ( $this->use_mysqli ) {
 
1600
                                $this->rows_affected = mysqli_affected_rows( $this->dbh );
 
1601
                        } else {
 
1602
                                $this->rows_affected = mysql_affected_rows( $this->dbh );
 
1603
                        }
 
1604
                        // Take note of the insert_id
 
1605
                        if ( preg_match( '/^\s*(insert|replace)\s/i', $query ) ) {
 
1606
                                if ( $this->use_mysqli ) {
 
1607
                                        $this->insert_id = mysqli_insert_id( $this->dbh );
 
1608
                                } else {
 
1609
                                        $this->insert_id = mysql_insert_id( $this->dbh );
 
1610
                                }
 
1611
                        }
 
1612
                        // Return number of rows affected
 
1613
                        $return_val = $this->rows_affected;
 
1614
                } else {
 
1615
                        $num_rows = 0;
 
1616
                        if ( $this->use_mysqli ) {
 
1617
                                while ( $row = @mysqli_fetch_object( $this->result ) ) {
 
1618
                                        $this->last_result[$num_rows] = $row;
 
1619
                                        $num_rows++;
 
1620
                                }
 
1621
                        } else {
 
1622
                                while ( $row = @mysql_fetch_object( $this->result ) ) {
 
1623
                                        $this->last_result[$num_rows] = $row;
 
1624
                                        $num_rows++;
 
1625
                                }
 
1626
                        }
 
1627
 
 
1628
                        // Log number of rows the query returned
 
1629
                        // and return number of rows selected
 
1630
                        $this->num_rows = $num_rows;
 
1631
                        $return_val     = $num_rows;
 
1632
                }
 
1633
 
 
1634
                return $return_val;
 
1635
        }
 
1636
 
 
1637
        /**
 
1638
         * Internal function to perform the mysql_query() call.
 
1639
         *
 
1640
         * @since 3.9.0
 
1641
         *
 
1642
         * @access private
 
1643
         * @see wpdb::query()
 
1644
         *
 
1645
         * @param string $query The query to run.
 
1646
         */
 
1647
        private function _do_query( $query ) {
 
1648
                if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
 
1649
                        $this->timer_start();
 
1650
                }
 
1651
 
 
1652
                if ( $this->use_mysqli ) {
 
1653
                        $this->result = @mysqli_query( $this->dbh, $query );
 
1654
                } else {
 
1655
                        $this->result = @mysql_query( $query, $this->dbh );
 
1656
                }
 
1657
                $this->num_queries++;
 
1658
 
 
1659
                if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
 
1660
                        $this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
 
1661
                }
 
1662
        }
 
1663
 
 
1664
        /**
 
1665
         * Insert a row into a table.
 
1666
         *
 
1667
         * <code>
 
1668
         * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 'bar' ) )
 
1669
         * wpdb::insert( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
 
1670
         * </code>
 
1671
         *
 
1672
         * @since 2.5.0
 
1673
         * @see wpdb::prepare()
 
1674
         * @see wpdb::$field_types
 
1675
         * @see wp_set_wpdb_vars()
 
1676
         *
 
1677
         * @param string $table table name
 
1678
         * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
 
1679
         * @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.
 
1680
         *      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.
 
1681
         * @return int|false The number of rows inserted, or false on error.
 
1682
         */
 
1683
        public function insert( $table, $data, $format = null ) {
 
1684
                return $this->_insert_replace_helper( $table, $data, $format, 'INSERT' );
 
1685
        }
 
1686
 
 
1687
        /**
 
1688
         * Replace a row into a table.
 
1689
         *
 
1690
         * <code>
 
1691
         * wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 'bar' ) )
 
1692
         * wpdb::replace( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( '%s', '%d' ) )
 
1693
         * </code>
 
1694
         *
 
1695
         * @since 3.0.0
 
1696
         * @see wpdb::prepare()
 
1697
         * @see wpdb::$field_types
 
1698
         * @see wp_set_wpdb_vars()
 
1699
         *
 
1700
         * @param string $table table name
 
1701
         * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
 
1702
         * @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.
 
1703
         *      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.
 
1704
         * @return int|false The number of rows affected, or false on error.
 
1705
         */
 
1706
        public function replace( $table, $data, $format = null ) {
 
1707
                return $this->_insert_replace_helper( $table, $data, $format, 'REPLACE' );
 
1708
        }
 
1709
 
 
1710
        /**
 
1711
         * Helper function for insert and replace.
 
1712
         *
 
1713
         * Runs an insert or replace query based on $type argument.
 
1714
         *
 
1715
         * @access private
 
1716
         * @since 3.0.0
 
1717
         * @see wpdb::prepare()
 
1718
         * @see wpdb::$field_types
 
1719
         * @see wp_set_wpdb_vars()
 
1720
         *
 
1721
         * @param string $table table name
 
1722
         * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
 
1723
         * @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.
 
1724
         *      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.
 
1725
         * @param string $type Optional. What type of operation is this? INSERT or REPLACE. Defaults to INSERT.
 
1726
         * @return int|false The number of rows affected, or false on error.
 
1727
         */
 
1728
        function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) {
 
1729
                if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) )
 
1730
                        return false;
 
1731
                $this->insert_id = 0;
 
1732
                $formats = $format = (array) $format;
 
1733
                $fields = array_keys( $data );
 
1734
                $formatted_fields = array();
 
1735
                foreach ( $fields as $field ) {
 
1736
                        if ( !empty( $format ) )
 
1737
                                $form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
 
1738
                        elseif ( isset( $this->field_types[$field] ) )
 
1739
                                $form = $this->field_types[$field];
 
1740
                        else
 
1741
                                $form = '%s';
 
1742
                        $formatted_fields[] = $form;
 
1743
                }
 
1744
                $sql = "{$type} INTO `$table` (`" . implode( '`,`', $fields ) . "`) VALUES (" . implode( ",", $formatted_fields ) . ")";
 
1745
                return $this->query( $this->prepare( $sql, $data ) );
 
1746
        }
 
1747
 
 
1748
        /**
 
1749
         * Update a row in the table
 
1750
         *
 
1751
         * <code>
 
1752
         * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 'bar' ), array( 'ID' => 1 ) )
 
1753
         * wpdb::update( 'table', array( 'column' => 'foo', 'field' => 1337 ), array( 'ID' => 1 ), array( '%s', '%d' ), array( '%d' ) )
 
1754
         * </code>
 
1755
         *
 
1756
         * @since 2.5.0
 
1757
         * @see wpdb::prepare()
 
1758
         * @see wpdb::$field_types
 
1759
         * @see wp_set_wpdb_vars()
 
1760
         *
 
1761
         * @param string $table table name
 
1762
         * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
 
1763
         * @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".
 
1764
         * @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.
 
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.
 
1766
         * @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.
 
1767
         * @return int|false The number of rows updated, or false on error.
 
1768
         */
 
1769
        public function update( $table, $data, $where, $format = null, $where_format = null ) {
 
1770
                if ( ! is_array( $data ) || ! is_array( $where ) )
 
1771
                        return false;
 
1772
 
 
1773
                $formats = $format = (array) $format;
 
1774
                $bits = $wheres = array();
 
1775
                foreach ( (array) array_keys( $data ) as $field ) {
 
1776
                        if ( !empty( $format ) )
 
1777
                                $form = ( $form = array_shift( $formats ) ) ? $form : $format[0];
 
1778
                        elseif ( isset($this->field_types[$field]) )
 
1779
                                $form = $this->field_types[$field];
 
1780
                        else
 
1781
                                $form = '%s';
 
1782
                        $bits[] = "`$field` = {$form}";
 
1783
                }
 
1784
 
 
1785
                $where_formats = $where_format = (array) $where_format;
 
1786
                foreach ( (array) array_keys( $where ) as $field ) {
 
1787
                        if ( !empty( $where_format ) )
 
1788
                                $form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[0];
 
1789
                        elseif ( isset( $this->field_types[$field] ) )
 
1790
                                $form = $this->field_types[$field];
 
1791
                        else
 
1792
                                $form = '%s';
 
1793
                        $wheres[] = "`$field` = {$form}";
 
1794
                }
 
1795
 
 
1796
                $sql = "UPDATE `$table` SET " . implode( ', ', $bits ) . ' WHERE ' . implode( ' AND ', $wheres );
 
1797
                return $this->query( $this->prepare( $sql, array_merge( array_values( $data ), array_values( $where ) ) ) );
 
1798
        }
 
1799
 
 
1800
        /**
 
1801
         * Delete a row in the table
 
1802
         *
 
1803
         * <code>
 
1804
         * wpdb::delete( 'table', array( 'ID' => 1 ) )
 
1805
         * wpdb::delete( 'table', array( 'ID' => 1 ), array( '%d' ) )
 
1806
         * </code>
 
1807
         *
 
1808
         * @since 3.4.0
 
1809
         * @see wpdb::prepare()
 
1810
         * @see wpdb::$field_types
 
1811
         * @see wp_set_wpdb_vars()
 
1812
         *
 
1813
         * @param string $table table name
 
1814
         * @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".
 
1815
         * @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.
 
1816
         * @return int|false The number of rows updated, or false on error.
 
1817
         */
 
1818
        public function delete( $table, $where, $where_format = null ) {
 
1819
                if ( ! is_array( $where ) )
 
1820
                        return false;
 
1821
 
 
1822
                $wheres = array();
 
1823
 
 
1824
                $where_formats = $where_format = (array) $where_format;
 
1825
 
 
1826
                foreach ( array_keys( $where ) as $field ) {
 
1827
                        if ( !empty( $where_format ) ) {
 
1828
                                $form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[0];
 
1829
                        } elseif ( isset( $this->field_types[ $field ] ) ) {
 
1830
                                $form = $this->field_types[ $field ];
 
1831
                        } else {
 
1832
                                $form = '%s';
 
1833
                        }
 
1834
 
 
1835
                        $wheres[] = "$field = $form";
 
1836
                }
 
1837
 
 
1838
                $sql = "DELETE FROM $table WHERE " . implode( ' AND ', $wheres );
 
1839
                return $this->query( $this->prepare( $sql, $where ) );
 
1840
        }
 
1841
 
 
1842
 
 
1843
        /**
 
1844
         * Retrieve one variable from the database.
 
1845
         *
 
1846
         * Executes a SQL query and returns the value from the SQL result.
 
1847
         * If the SQL result contains more than one column and/or more than one row, this function returns the value in the column and row specified.
 
1848
         * If $query is null, this function returns the value in the specified column and row from the previous SQL result.
 
1849
         *
 
1850
         * @since 0.71
 
1851
         *
 
1852
         * @param string|null $query Optional. SQL query. Defaults to null, use the result from the previous query.
 
1853
         * @param int $x Optional. Column of value to return. Indexed from 0.
 
1854
         * @param int $y Optional. Row of value to return. Indexed from 0.
 
1855
         * @return string|null Database query result (as string), or null on failure
 
1856
         */
 
1857
        public function get_var( $query = null, $x = 0, $y = 0 ) {
 
1858
                $this->func_call = "\$db->get_var(\"$query\", $x, $y)";
 
1859
                if ( $query )
 
1860
                        $this->query( $query );
 
1861
 
 
1862
                // Extract var out of cached results based x,y vals
 
1863
                if ( !empty( $this->last_result[$y] ) ) {
 
1864
                        $values = array_values( get_object_vars( $this->last_result[$y] ) );
 
1865
                }
 
1866
 
 
1867
                // If there is a value return it else return null
 
1868
                return ( isset( $values[$x] ) && $values[$x] !== '' ) ? $values[$x] : null;
 
1869
        }
 
1870
 
 
1871
        /**
 
1872
         * Retrieve one row from the database.
 
1873
         *
 
1874
         * Executes a SQL query and returns the row from the SQL result.
 
1875
         *
 
1876
         * @since 0.71
 
1877
         *
 
1878
         * @param string|null $query SQL query.
 
1879
         * @param string $output Optional. one of ARRAY_A | ARRAY_N | OBJECT constants. Return an associative array (column => value, ...),
 
1880
         *      a numerically indexed array (0 => value, ...) or an object ( ->column = value ), respectively.
 
1881
         * @param int $y Optional. Row to return. Indexed from 0.
 
1882
         * @return mixed Database query result in format specified by $output or null on failure
 
1883
         */
 
1884
        public function get_row( $query = null, $output = OBJECT, $y = 0 ) {
 
1885
                $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
 
1886
                if ( $query )
 
1887
                        $this->query( $query );
 
1888
                else
 
1889
                        return null;
 
1890
 
 
1891
                if ( !isset( $this->last_result[$y] ) )
 
1892
                        return null;
 
1893
 
 
1894
                if ( $output == OBJECT ) {
 
1895
                        return $this->last_result[$y] ? $this->last_result[$y] : null;
 
1896
                } elseif ( $output == ARRAY_A ) {
 
1897
                        return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null;
 
1898
                } elseif ( $output == ARRAY_N ) {
 
1899
                        return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null;
 
1900
                } elseif ( strtoupper( $output ) === OBJECT ) {
 
1901
                        // Back compat for OBJECT being previously case insensitive.
 
1902
                        return $this->last_result[$y] ? $this->last_result[$y] : null;
 
1903
                } else {
 
1904
                        $this->print_error( " \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N" );
 
1905
                }
 
1906
        }
 
1907
 
 
1908
        /**
 
1909
         * Retrieve one column from the database.
 
1910
         *
 
1911
         * Executes a SQL query and returns the column from the SQL result.
 
1912
         * If the SQL result contains more than one column, this function returns the column specified.
 
1913
         * If $query is null, this function returns the specified column from the previous SQL result.
 
1914
         *
 
1915
         * @since 0.71
 
1916
         *
 
1917
         * @param string|null $query Optional. SQL query. Defaults to previous query.
 
1918
         * @param int $x Optional. Column to return. Indexed from 0.
 
1919
         * @return array Database query result. Array indexed from 0 by SQL result row number.
 
1920
         */
 
1921
        public function get_col( $query = null , $x = 0 ) {
 
1922
                if ( $query )
 
1923
                        $this->query( $query );
 
1924
 
 
1925
                $new_array = array();
 
1926
                // Extract the column values
 
1927
                for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) {
 
1928
                        $new_array[$i] = $this->get_var( null, $x, $i );
 
1929
                }
 
1930
                return $new_array;
 
1931
        }
 
1932
 
 
1933
        /**
 
1934
         * Retrieve an entire SQL result set from the database (i.e., many rows)
 
1935
         *
 
1936
         * Executes a SQL query and returns the entire SQL result.
 
1937
         *
 
1938
         * @since 0.71
 
1939
         *
 
1940
         * @param string $query SQL query.
 
1941
         * @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.
 
1942
         *      Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively.
 
1943
         *      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.
 
1944
         * @return mixed Database query results
 
1945
         */
 
1946
        public function get_results( $query = null, $output = OBJECT ) {
 
1947
                $this->func_call = "\$db->get_results(\"$query\", $output)";
 
1948
 
 
1949
                if ( $query )
 
1950
                        $this->query( $query );
 
1951
                else
 
1952
                        return null;
 
1953
 
 
1954
                $new_array = array();
 
1955
                if ( $output == OBJECT ) {
 
1956
                        // Return an integer-keyed array of row objects
 
1957
                        return $this->last_result;
 
1958
                } elseif ( $output == OBJECT_K ) {
 
1959
                        // Return an array of row objects with keys from column 1
 
1960
                        // (Duplicates are discarded)
 
1961
                        foreach ( $this->last_result as $row ) {
 
1962
                                $var_by_ref = get_object_vars( $row );
 
1963
                                $key = array_shift( $var_by_ref );
 
1964
                                if ( ! isset( $new_array[ $key ] ) )
 
1965
                                        $new_array[ $key ] = $row;
 
1966
                        }
 
1967
                        return $new_array;
 
1968
                } elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
 
1969
                        // Return an integer-keyed array of...
 
1970
                        if ( $this->last_result ) {
 
1971
                                foreach( (array) $this->last_result as $row ) {
 
1972
                                        if ( $output == ARRAY_N ) {
 
1973
                                                // ...integer-keyed row arrays
 
1974
                                                $new_array[] = array_values( get_object_vars( $row ) );
 
1975
                                        } else {
 
1976
                                                // ...column name-keyed row arrays
 
1977
                                                $new_array[] = get_object_vars( $row );
 
1978
                                        }
 
1979
                                }
 
1980
                        }
 
1981
                        return $new_array;
 
1982
                } elseif ( strtoupper( $output ) === OBJECT ) {
 
1983
                        // Back compat for OBJECT being previously case insensitive.
 
1984
                        return $this->last_result;
 
1985
                }
 
1986
                return null;
 
1987
        }
 
1988
 
 
1989
        /**
 
1990
         * Load the column metadata from the last query.
 
1991
         *
 
1992
         * @since 3.5.0
 
1993
         *
 
1994
         * @access protected
 
1995
         */
 
1996
        protected function load_col_info() {
 
1997
                if ( $this->col_info )
 
1998
                        return;
 
1999
 
 
2000
                if ( $this->use_mysqli ) {
 
2001
                        for ( $i = 0; $i < @mysqli_num_fields( $this->result ); $i++ ) {
 
2002
                                $this->col_info[ $i ] = @mysqli_fetch_field( $this->result );
 
2003
                        }
 
2004
                } else {
 
2005
                        for ( $i = 0; $i < @mysql_num_fields( $this->result ); $i++ ) {
 
2006
                                $this->col_info[ $i ] = @mysql_fetch_field( $this->result, $i );
 
2007
                        }
 
2008
                }
 
2009
        }
 
2010
 
 
2011
        /**
 
2012
         * Retrieve column metadata from the last query.
 
2013
         *
 
2014
         * @since 0.71
 
2015
         *
 
2016
         * @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
 
2017
         * @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
 
2018
         * @return mixed Column Results
 
2019
         */
 
2020
        public function get_col_info( $info_type = 'name', $col_offset = -1 ) {
 
2021
                $this->load_col_info();
 
2022
 
 
2023
                if ( $this->col_info ) {
 
2024
                        if ( $col_offset == -1 ) {
 
2025
                                $i = 0;
 
2026
                                $new_array = array();
 
2027
                                foreach( (array) $this->col_info as $col ) {
 
2028
                                        $new_array[$i] = $col->{$info_type};
 
2029
                                        $i++;
 
2030
                                }
 
2031
                                return $new_array;
 
2032
                        } else {
 
2033
                                return $this->col_info[$col_offset]->{$info_type};
 
2034
                        }
 
2035
                }
 
2036
        }
 
2037
 
 
2038
        /**
 
2039
         * Starts the timer, for debugging purposes.
 
2040
         *
 
2041
         * @since 1.5.0
 
2042
         *
 
2043
         * @return true
 
2044
         */
 
2045
        public function timer_start() {
 
2046
                $this->time_start = microtime( true );
 
2047
                return true;
 
2048
        }
 
2049
 
 
2050
        /**
 
2051
         * Stops the debugging timer.
 
2052
         *
 
2053
         * @since 1.5.0
 
2054
         *
 
2055
         * @return float Total time spent on the query, in seconds
 
2056
         */
 
2057
        public function timer_stop() {
 
2058
                return ( microtime( true ) - $this->time_start );
 
2059
        }
 
2060
 
 
2061
        /**
 
2062
         * Wraps errors in a nice header and footer and dies.
 
2063
         *
 
2064
         * Will not die if wpdb::$show_errors is false.
 
2065
         *
 
2066
         * @since 1.5.0
 
2067
         *
 
2068
         * @param string $message The Error message
 
2069
         * @param string $error_code Optional. A Computer readable string to identify the error.
 
2070
         * @return false|void
 
2071
         */
 
2072
        public function bail( $message, $error_code = '500' ) {
 
2073
                if ( !$this->show_errors ) {
 
2074
                        if ( class_exists( 'WP_Error' ) )
 
2075
                                $this->error = new WP_Error($error_code, $message);
 
2076
                        else
 
2077
                                $this->error = $message;
 
2078
                        return false;
 
2079
                }
 
2080
                wp_die($message);
 
2081
        }
 
2082
 
 
2083
        /**
 
2084
         * Whether MySQL database is at least the required minimum version.
 
2085
         *
 
2086
         * @since 2.5.0
 
2087
         * @uses $wp_version
 
2088
         * @uses $required_mysql_version
 
2089
         *
 
2090
         * @return WP_Error
 
2091
         */
 
2092
        public function check_database_version() {
 
2093
                global $wp_version, $required_mysql_version;
 
2094
                // Make sure the server has the required MySQL version
 
2095
                if ( version_compare($this->db_version(), $required_mysql_version, '<') )
 
2096
                        return new WP_Error('database_version', sprintf( __( '<strong>ERROR</strong>: WordPress %1$s requires MySQL %2$s or higher' ), $wp_version, $required_mysql_version ));
 
2097
        }
 
2098
 
 
2099
        /**
 
2100
         * Whether the database supports collation.
 
2101
         *
 
2102
         * Called when WordPress is generating the table scheme.
 
2103
         *
 
2104
         * @since 2.5.0
 
2105
         * @deprecated 3.5.0
 
2106
         * @deprecated Use wpdb::has_cap( 'collation' )
 
2107
         *
 
2108
         * @return bool True if collation is supported, false if version does not
 
2109
         */
 
2110
        public function supports_collation() {
 
2111
                _deprecated_function( __FUNCTION__, '3.5', 'wpdb::has_cap( \'collation\' )' );
 
2112
                return $this->has_cap( 'collation' );
 
2113
        }
 
2114
 
 
2115
        /**
 
2116
         * The database character collate.
 
2117
         *
 
2118
         * @since 3.5.0
 
2119
         *
 
2120
         * @return string The database character collate.
 
2121
         */
 
2122
        public function get_charset_collate() {
 
2123
                $charset_collate = '';
 
2124
 
 
2125
                if ( ! empty( $this->charset ) )
 
2126
                        $charset_collate = "DEFAULT CHARACTER SET $this->charset";
 
2127
                if ( ! empty( $this->collate ) )
 
2128
                        $charset_collate .= " COLLATE $this->collate";
 
2129
 
 
2130
                return $charset_collate;
 
2131
        }
 
2132
 
 
2133
        /**
 
2134
         * Determine if a database supports a particular feature.
 
2135
         *
 
2136
         * @since 2.7.0
 
2137
         * @see wpdb::db_version()
 
2138
         *
 
2139
         * @param string $db_cap The feature to check for.
 
2140
         * @return bool
 
2141
         */
 
2142
        public function has_cap( $db_cap ) {
 
2143
                $version = $this->db_version();
 
2144
 
 
2145
                switch ( strtolower( $db_cap ) ) {
 
2146
                        case 'collation' :    // @since 2.5.0
 
2147
                        case 'group_concat' : // @since 2.7.0
 
2148
                        case 'subqueries' :   // @since 2.7.0
 
2149
                                return version_compare( $version, '4.1', '>=' );
 
2150
                        case 'set_charset' :
 
2151
                                return version_compare( $version, '5.0.7', '>=' );
 
2152
                };
 
2153
 
 
2154
                return false;
 
2155
        }
 
2156
 
 
2157
        /**
 
2158
         * Retrieve the name of the function that called wpdb.
 
2159
         *
 
2160
         * Searches up the list of functions until it reaches
 
2161
         * the one that would most logically had called this method.
 
2162
         *
 
2163
         * @since 2.5.0
 
2164
         *
 
2165
         * @return string The name of the calling function
 
2166
         */
 
2167
        public function get_caller() {
 
2168
                return wp_debug_backtrace_summary( __CLASS__ );
 
2169
        }
 
2170
 
 
2171
        /**
 
2172
         * The database version number.
 
2173
         *
 
2174
         * @since 2.7.0
 
2175
         *
 
2176
         * @return false|string false on failure, version number on success
 
2177
         */
 
2178
        public function db_version() {
 
2179
                if ( $this->use_mysqli ) {
 
2180
                        $server_info = mysqli_get_server_info( $this->dbh );
 
2181
                } else {
 
2182
                        $server_info = mysql_get_server_info( $this->dbh );
 
2183
                }
 
2184
                return preg_replace( '/[^0-9.].*/', '', $server_info );
 
2185
        }
 
2186
}