wp/wp-includes/wp-db.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
    43  * file to your class. The wpdb class will still be included,
    43  * file to your class. The wpdb class will still be included,
    44  * so you can extend it or simply use your own.
    44  * so you can extend it or simply use your own.
    45  *
    45  *
    46  * @link https://codex.wordpress.org/Function_Reference/wpdb_Class
    46  * @link https://codex.wordpress.org/Function_Reference/wpdb_Class
    47  *
    47  *
    48  * @package WordPress
       
    49  * @subpackage Database
       
    50  * @since 0.71
    48  * @since 0.71
    51  */
    49  */
    52 class wpdb {
    50 class wpdb {
    53 
    51 
    54 	/**
    52 	/**
    56 	 *
    54 	 *
    57 	 * Default behavior is to show errors if both WP_DEBUG and WP_DEBUG_DISPLAY
    55 	 * Default behavior is to show errors if both WP_DEBUG and WP_DEBUG_DISPLAY
    58 	 * evaluated to true.
    56 	 * evaluated to true.
    59 	 *
    57 	 *
    60 	 * @since 0.71
    58 	 * @since 0.71
    61 	 * @access private
       
    62 	 * @var bool
    59 	 * @var bool
    63 	 */
    60 	 */
    64 	var $show_errors = false;
    61 	var $show_errors = false;
    65 
    62 
    66 	/**
    63 	/**
    67 	 * Whether to suppress errors during the DB bootstrapping.
    64 	 * Whether to suppress errors during the DB bootstrapping.
    68 	 *
    65 	 *
    69 	 * @access private
       
    70 	 * @since 2.5.0
    66 	 * @since 2.5.0
    71 	 * @var bool
    67 	 * @var bool
    72 	 */
    68 	 */
    73 	var $suppress_errors = false;
    69 	var $suppress_errors = false;
    74 
    70 
    82 
    78 
    83 	/**
    79 	/**
    84 	 * Amount of queries made
    80 	 * Amount of queries made
    85 	 *
    81 	 *
    86 	 * @since 1.2.0
    82 	 * @since 1.2.0
    87 	 * @access private
       
    88 	 * @var int
    83 	 * @var int
    89 	 */
    84 	 */
    90 	var $num_queries = 0;
    85 	public $num_queries = 0;
    91 
    86 
    92 	/**
    87 	/**
    93 	 * Count of rows returned by previous query
    88 	 * Count of rows returned by previous query
    94 	 *
    89 	 *
    95 	 * @since 0.71
    90 	 * @since 0.71
    96 	 * @access private
       
    97 	 * @var int
    91 	 * @var int
    98 	 */
    92 	 */
    99 	var $num_rows = 0;
    93 	public $num_rows = 0;
   100 
    94 
   101 	/**
    95 	/**
   102 	 * Count of affected rows by previous query
    96 	 * Count of affected rows by previous query
   103 	 *
    97 	 *
   104 	 * @since 0.71
    98 	 * @since 0.71
   105 	 * @access private
       
   106 	 * @var int
    99 	 * @var int
   107 	 */
   100 	 */
   108 	var $rows_affected = 0;
   101 	var $rows_affected = 0;
   109 
   102 
   110 	/**
   103 	/**
   111 	 * The ID generated for an AUTO_INCREMENT column by the previous query (usually INSERT).
   104 	 * The ID generated for an AUTO_INCREMENT column by the previous query (usually INSERT).
   112 	 *
   105 	 *
   113 	 * @since 0.71
   106 	 * @since 0.71
   114 	 * @access public
       
   115 	 * @var int
   107 	 * @var int
   116 	 */
   108 	 */
   117 	var $insert_id = 0;
   109 	public $insert_id = 0;
   118 
   110 
   119 	/**
   111 	/**
   120 	 * Last query made
   112 	 * Last query made
   121 	 *
   113 	 *
   122 	 * @since 0.71
   114 	 * @since 0.71
   123 	 * @access private
       
   124 	 * @var array
   115 	 * @var array
   125 	 */
   116 	 */
   126 	var $last_query;
   117 	var $last_query;
   127 
   118 
   128 	/**
   119 	/**
   129 	 * Results of the last query made
   120 	 * Results of the last query made
   130 	 *
   121 	 *
   131 	 * @since 0.71
   122 	 * @since 0.71
   132 	 * @access private
       
   133 	 * @var array|null
   123 	 * @var array|null
   134 	 */
   124 	 */
   135 	var $last_result;
   125 	var $last_result;
   136 
   126 
   137 	/**
   127 	/**
   138 	 * MySQL result, which is either a resource or boolean.
   128 	 * MySQL result, which is either a resource or boolean.
   139 	 *
   129 	 *
   140 	 * @since 0.71
   130 	 * @since 0.71
   141 	 * @access protected
       
   142 	 * @var mixed
   131 	 * @var mixed
   143 	 */
   132 	 */
   144 	protected $result;
   133 	protected $result;
   145 
   134 
   146 	/**
   135 	/**
   147 	 * Cached column info, for sanity checking data before inserting
   136 	 * Cached column info, for sanity checking data before inserting
   148 	 *
   137 	 *
   149 	 * @since 4.2.0
   138 	 * @since 4.2.0
   150 	 * @access protected
       
   151 	 * @var array
   139 	 * @var array
   152 	 */
   140 	 */
   153 	protected $col_meta = array();
   141 	protected $col_meta = array();
   154 
   142 
   155 	/**
   143 	/**
   156 	 * Calculated character sets on tables
   144 	 * Calculated character sets on tables
   157 	 *
   145 	 *
   158 	 * @since 4.2.0
   146 	 * @since 4.2.0
   159 	 * @access protected
       
   160 	 * @var array
   147 	 * @var array
   161 	 */
   148 	 */
   162 	protected $table_charset = array();
   149 	protected $table_charset = array();
   163 
   150 
   164 	/**
   151 	/**
   165 	 * Whether text fields in the current query need to be sanity checked.
   152 	 * Whether text fields in the current query need to be sanity checked.
   166 	 *
   153 	 *
   167 	 * @since 4.2.0
   154 	 * @since 4.2.0
   168 	 * @access protected
       
   169 	 * @var bool
   155 	 * @var bool
   170 	 */
   156 	 */
   171 	protected $check_current_query = true;
   157 	protected $check_current_query = true;
   172 
   158 
   173 	/**
   159 	/**
   174 	 * Flag to ensure we don't run into recursion problems when checking the collation.
   160 	 * Flag to ensure we don't run into recursion problems when checking the collation.
   175 	 *
   161 	 *
   176 	 * @since 4.2.0
   162 	 * @since 4.2.0
   177 	 * @access private
       
   178 	 * @see wpdb::check_safe_collation()
   163 	 * @see wpdb::check_safe_collation()
   179 	 * @var boolean
   164 	 * @var bool
   180 	 */
   165 	 */
   181 	private $checking_collation = false;
   166 	private $checking_collation = false;
   182 
   167 
   183 	/**
   168 	/**
   184 	 * Saved info on the table column
   169 	 * Saved info on the table column
   185 	 *
   170 	 *
   186 	 * @since 0.71
   171 	 * @since 0.71
   187 	 * @access protected
       
   188 	 * @var array
   172 	 * @var array
   189 	 */
   173 	 */
   190 	protected $col_info;
   174 	protected $col_info;
   191 
   175 
   192 	/**
   176 	/**
   193 	 * Saved queries that were executed
   177 	 * Saved queries that were executed
   194 	 *
   178 	 *
   195 	 * @since 1.5.0
   179 	 * @since 1.5.0
   196 	 * @access private
       
   197 	 * @var array
   180 	 * @var array
   198 	 */
   181 	 */
   199 	var $queries;
   182 	var $queries;
   200 
   183 
   201 	/**
   184 	/**
   202 	 * The number of times to retry reconnecting before dying.
   185 	 * The number of times to retry reconnecting before dying.
   203 	 *
   186 	 *
   204 	 * @since 3.9.0
   187 	 * @since 3.9.0
   205 	 * @access protected
       
   206 	 * @see wpdb::check_connection()
   188 	 * @see wpdb::check_connection()
   207 	 * @var int
   189 	 * @var int
   208 	 */
   190 	 */
   209 	protected $reconnect_retries = 5;
   191 	protected $reconnect_retries = 5;
   210 
   192 
   214 	 * You can set this to have multiple WordPress installations
   196 	 * You can set this to have multiple WordPress installations
   215 	 * in a single database. The second reason is for possible
   197 	 * in a single database. The second reason is for possible
   216 	 * security precautions.
   198 	 * security precautions.
   217 	 *
   199 	 *
   218 	 * @since 2.5.0
   200 	 * @since 2.5.0
   219 	 * @access private
       
   220 	 * @var string
   201 	 * @var string
   221 	 */
   202 	 */
   222 	var $prefix = '';
   203 	public $prefix = '';
   223 
   204 
   224 	/**
   205 	/**
   225 	 * WordPress base table prefix.
   206 	 * WordPress base table prefix.
   226 	 *
   207 	 *
   227 	 * @since 3.0.0
   208 	 * @since 3.0.0
   228 	 * @access public
       
   229 	 * @var string
   209 	 * @var string
   230 	 */
   210 	 */
   231 	 public $base_prefix;
   211 	 public $base_prefix;
   232 
   212 
   233 	/**
   213 	/**
   234 	 * Whether the database queries are ready to start executing.
   214 	 * Whether the database queries are ready to start executing.
   235 	 *
   215 	 *
   236 	 * @since 2.3.2
   216 	 * @since 2.3.2
   237 	 * @access private
       
   238 	 * @var bool
   217 	 * @var bool
   239 	 */
   218 	 */
   240 	var $ready = false;
   219 	var $ready = false;
   241 
   220 
   242 	/**
   221 	/**
   243 	 * Blog ID.
   222 	 * Blog ID.
   244 	 *
   223 	 *
   245 	 * @since 3.0.0
   224 	 * @since 3.0.0
   246 	 * @access public
       
   247 	 * @var int
   225 	 * @var int
   248 	 */
   226 	 */
   249 	public $blogid = 0;
   227 	public $blogid = 0;
   250 
   228 
   251 	/**
   229 	/**
   252 	 * Site ID.
   230 	 * Site ID.
   253 	 *
   231 	 *
   254 	 * @since 3.0.0
   232 	 * @since 3.0.0
   255 	 * @access public
       
   256 	 * @var int
   233 	 * @var int
   257 	 */
   234 	 */
   258 	public $siteid = 0;
   235 	public $siteid = 0;
   259 
   236 
   260 	/**
   237 	/**
   261 	 * List of WordPress per-blog tables
   238 	 * List of WordPress per-blog tables
   262 	 *
   239 	 *
   263 	 * @since 2.5.0
   240 	 * @since 2.5.0
   264 	 * @access private
       
   265 	 * @see wpdb::tables()
   241 	 * @see wpdb::tables()
   266 	 * @var array
   242 	 * @var array
   267 	 */
   243 	 */
   268 	var $tables = array( 'posts', 'comments', 'links', 'options', 'postmeta',
   244 	var $tables = array( 'posts', 'comments', 'links', 'options', 'postmeta',
   269 		'terms', 'term_taxonomy', 'term_relationships', 'commentmeta' );
   245 		'terms', 'term_taxonomy', 'term_relationships', 'termmeta', 'commentmeta' );
   270 
   246 
   271 	/**
   247 	/**
   272 	 * List of deprecated WordPress tables
   248 	 * List of deprecated WordPress tables
   273 	 *
   249 	 *
   274 	 * categories, post2cat, and link2cat were deprecated in 2.3.0, db version 5539
   250 	 * categories, post2cat, and link2cat were deprecated in 2.3.0, db version 5539
   275 	 *
   251 	 *
   276 	 * @since 2.9.0
   252 	 * @since 2.9.0
   277 	 * @access private
       
   278 	 * @see wpdb::tables()
   253 	 * @see wpdb::tables()
   279 	 * @var array
   254 	 * @var array
   280 	 */
   255 	 */
   281 	var $old_tables = array( 'categories', 'post2cat', 'link2cat' );
   256 	var $old_tables = array( 'categories', 'post2cat', 'link2cat' );
   282 
   257 
   283 	/**
   258 	/**
   284 	 * List of WordPress global tables
   259 	 * List of WordPress global tables
   285 	 *
   260 	 *
   286 	 * @since 3.0.0
   261 	 * @since 3.0.0
   287 	 * @access private
       
   288 	 * @see wpdb::tables()
   262 	 * @see wpdb::tables()
   289 	 * @var array
   263 	 * @var array
   290 	 */
   264 	 */
   291 	var $global_tables = array( 'users', 'usermeta' );
   265 	var $global_tables = array( 'users', 'usermeta' );
   292 
   266 
   293 	/**
   267 	/**
   294 	 * List of Multisite global tables
   268 	 * List of Multisite global tables
   295 	 *
   269 	 *
   296 	 * @since 3.0.0
   270 	 * @since 3.0.0
   297 	 * @access private
       
   298 	 * @see wpdb::tables()
   271 	 * @see wpdb::tables()
   299 	 * @var array
   272 	 * @var array
   300 	 */
   273 	 */
   301 	var $ms_global_tables = array( 'blogs', 'signups', 'site', 'sitemeta',
   274 	var $ms_global_tables = array( 'blogs', 'signups', 'site', 'sitemeta',
   302 		'sitecategories', 'registration_log', 'blog_versions' );
   275 		'sitecategories', 'registration_log', 'blog_versions' );
   303 
   276 
   304 	/**
   277 	/**
   305 	 * WordPress Comments table
   278 	 * WordPress Comments table
   306 	 *
   279 	 *
   307 	 * @since 1.5.0
   280 	 * @since 1.5.0
   308 	 * @access public
       
   309 	 * @var string
   281 	 * @var string
   310 	 */
   282 	 */
   311 	public $comments;
   283 	public $comments;
   312 
   284 
   313 	/**
   285 	/**
   314 	 * WordPress Comment Metadata table
   286 	 * WordPress Comment Metadata table
   315 	 *
   287 	 *
   316 	 * @since 2.9.0
   288 	 * @since 2.9.0
   317 	 * @access public
       
   318 	 * @var string
   289 	 * @var string
   319 	 */
   290 	 */
   320 	public $commentmeta;
   291 	public $commentmeta;
   321 
   292 
   322 	/**
   293 	/**
   323 	 * WordPress Links table
   294 	 * WordPress Links table
   324 	 *
   295 	 *
   325 	 * @since 1.5.0
   296 	 * @since 1.5.0
   326 	 * @access public
       
   327 	 * @var string
   297 	 * @var string
   328 	 */
   298 	 */
   329 	public $links;
   299 	public $links;
   330 
   300 
   331 	/**
   301 	/**
   332 	 * WordPress Options table
   302 	 * WordPress Options table
   333 	 *
   303 	 *
   334 	 * @since 1.5.0
   304 	 * @since 1.5.0
   335 	 * @access public
       
   336 	 * @var string
   305 	 * @var string
   337 	 */
   306 	 */
   338 	public $options;
   307 	public $options;
   339 
   308 
   340 	/**
   309 	/**
   341 	 * WordPress Post Metadata table
   310 	 * WordPress Post Metadata table
   342 	 *
   311 	 *
   343 	 * @since 1.5.0
   312 	 * @since 1.5.0
   344 	 * @access public
       
   345 	 * @var string
   313 	 * @var string
   346 	 */
   314 	 */
   347 	public $postmeta;
   315 	public $postmeta;
   348 
   316 
   349 	/**
   317 	/**
   350 	 * WordPress Posts table
   318 	 * WordPress Posts table
   351 	 *
   319 	 *
   352 	 * @since 1.5.0
   320 	 * @since 1.5.0
   353 	 * @access public
       
   354 	 * @var string
   321 	 * @var string
   355 	 */
   322 	 */
   356 	public $posts;
   323 	public $posts;
   357 
   324 
   358 	/**
   325 	/**
   359 	 * WordPress Terms table
   326 	 * WordPress Terms table
   360 	 *
   327 	 *
   361 	 * @since 2.3.0
   328 	 * @since 2.3.0
   362 	 * @access public
       
   363 	 * @var string
   329 	 * @var string
   364 	 */
   330 	 */
   365 	public $terms;
   331 	public $terms;
   366 
   332 
   367 	/**
   333 	/**
   368 	 * WordPress Term Relationships table
   334 	 * WordPress Term Relationships table
   369 	 *
   335 	 *
   370 	 * @since 2.3.0
   336 	 * @since 2.3.0
   371 	 * @access public
       
   372 	 * @var string
   337 	 * @var string
   373 	 */
   338 	 */
   374 	public $term_relationships;
   339 	public $term_relationships;
   375 
   340 
   376 	/**
   341 	/**
   377 	 * WordPress Term Taxonomy table
   342 	 * WordPress Term Taxonomy table
   378 	 *
   343 	 *
   379 	 * @since 2.3.0
   344 	 * @since 2.3.0
   380 	 * @access public
       
   381 	 * @var string
   345 	 * @var string
   382 	 */
   346 	 */
   383 	public $term_taxonomy;
   347 	public $term_taxonomy;
   384 
   348 
   385 	/*
   349 	/**
   386 	 * Global and Multisite tables
   350 	 * WordPress Term Meta table.
   387 	 */
   351 	 *
       
   352 	 * @since 4.4.0
       
   353 	 * @var string
       
   354 	 */
       
   355 	public $termmeta;
       
   356 
       
   357 	//
       
   358 	// Global and Multisite tables
       
   359 	//
   388 
   360 
   389 	/**
   361 	/**
   390 	 * WordPress User Metadata table
   362 	 * WordPress User Metadata table
   391 	 *
   363 	 *
   392 	 * @since 2.3.0
   364 	 * @since 2.3.0
   393 	 * @access public
       
   394 	 * @var string
   365 	 * @var string
   395 	 */
   366 	 */
   396 	public $usermeta;
   367 	public $usermeta;
   397 
   368 
   398 	/**
   369 	/**
   399 	 * WordPress Users table
   370 	 * WordPress Users table
   400 	 *
   371 	 *
   401 	 * @since 1.5.0
   372 	 * @since 1.5.0
   402 	 * @access public
       
   403 	 * @var string
   373 	 * @var string
   404 	 */
   374 	 */
   405 	public $users;
   375 	public $users;
   406 
   376 
   407 	/**
   377 	/**
   408 	 * Multisite Blogs table
   378 	 * Multisite Blogs table
   409 	 *
   379 	 *
   410 	 * @since 3.0.0
   380 	 * @since 3.0.0
   411 	 * @access public
       
   412 	 * @var string
   381 	 * @var string
   413 	 */
   382 	 */
   414 	public $blogs;
   383 	public $blogs;
   415 
   384 
   416 	/**
   385 	/**
   417 	 * Multisite Blog Versions table
   386 	 * Multisite Blog Versions table
   418 	 *
   387 	 *
   419 	 * @since 3.0.0
   388 	 * @since 3.0.0
   420 	 * @access public
       
   421 	 * @var string
   389 	 * @var string
   422 	 */
   390 	 */
   423 	public $blog_versions;
   391 	public $blog_versions;
   424 
   392 
   425 	/**
   393 	/**
   426 	 * Multisite Registration Log table
   394 	 * Multisite Registration Log table
   427 	 *
   395 	 *
   428 	 * @since 3.0.0
   396 	 * @since 3.0.0
   429 	 * @access public
       
   430 	 * @var string
   397 	 * @var string
   431 	 */
   398 	 */
   432 	public $registration_log;
   399 	public $registration_log;
   433 
   400 
   434 	/**
   401 	/**
   435 	 * Multisite Signups table
   402 	 * Multisite Signups table
   436 	 *
   403 	 *
   437 	 * @since 3.0.0
   404 	 * @since 3.0.0
   438 	 * @access public
       
   439 	 * @var string
   405 	 * @var string
   440 	 */
   406 	 */
   441 	public $signups;
   407 	public $signups;
   442 
   408 
   443 	/**
   409 	/**
   444 	 * Multisite Sites table
   410 	 * Multisite Sites table
   445 	 *
   411 	 *
   446 	 * @since 3.0.0
   412 	 * @since 3.0.0
   447 	 * @access public
       
   448 	 * @var string
   413 	 * @var string
   449 	 */
   414 	 */
   450 	public $site;
   415 	public $site;
   451 
   416 
   452 	/**
   417 	/**
   453 	 * Multisite Sitewide Terms table
   418 	 * Multisite Sitewide Terms table
   454 	 *
   419 	 *
   455 	 * @since 3.0.0
   420 	 * @since 3.0.0
   456 	 * @access public
       
   457 	 * @var string
   421 	 * @var string
   458 	 */
   422 	 */
   459 	public $sitecategories;
   423 	public $sitecategories;
   460 
   424 
   461 	/**
   425 	/**
   462 	 * Multisite Site Metadata table
   426 	 * Multisite Site Metadata table
   463 	 *
   427 	 *
   464 	 * @since 3.0.0
   428 	 * @since 3.0.0
   465 	 * @access public
       
   466 	 * @var string
   429 	 * @var string
   467 	 */
   430 	 */
   468 	public $sitemeta;
   431 	public $sitemeta;
   469 
   432 
   470 	/**
   433 	/**
   476 	 * @see wpdb::prepare()
   439 	 * @see wpdb::prepare()
   477 	 * @see wpdb::insert()
   440 	 * @see wpdb::insert()
   478 	 * @see wpdb::update()
   441 	 * @see wpdb::update()
   479 	 * @see wpdb::delete()
   442 	 * @see wpdb::delete()
   480 	 * @see wp_set_wpdb_vars()
   443 	 * @see wp_set_wpdb_vars()
   481 	 * @access public
       
   482 	 * @var array
   444 	 * @var array
   483 	 */
   445 	 */
   484 	public $field_types = array();
   446 	public $field_types = array();
   485 
   447 
   486 	/**
   448 	/**
   487 	 * Database table columns charset
   449 	 * Database table columns charset
   488 	 *
   450 	 *
   489 	 * @since 2.2.0
   451 	 * @since 2.2.0
   490 	 * @access public
       
   491 	 * @var string
   452 	 * @var string
   492 	 */
   453 	 */
   493 	public $charset;
   454 	public $charset;
   494 
   455 
   495 	/**
   456 	/**
   496 	 * Database table columns collate
   457 	 * Database table columns collate
   497 	 *
   458 	 *
   498 	 * @since 2.2.0
   459 	 * @since 2.2.0
   499 	 * @access public
       
   500 	 * @var string
   460 	 * @var string
   501 	 */
   461 	 */
   502 	public $collate;
   462 	public $collate;
   503 
   463 
   504 	/**
   464 	/**
   505 	 * Database Username
   465 	 * Database Username
   506 	 *
   466 	 *
   507 	 * @since 2.9.0
   467 	 * @since 2.9.0
   508 	 * @access protected
       
   509 	 * @var string
   468 	 * @var string
   510 	 */
   469 	 */
   511 	protected $dbuser;
   470 	protected $dbuser;
   512 
   471 
   513 	/**
   472 	/**
   514 	 * Database Password
   473 	 * Database Password
   515 	 *
   474 	 *
   516 	 * @since 3.1.0
   475 	 * @since 3.1.0
   517 	 * @access protected
       
   518 	 * @var string
   476 	 * @var string
   519 	 */
   477 	 */
   520 	protected $dbpassword;
   478 	protected $dbpassword;
   521 
   479 
   522 	/**
   480 	/**
   523 	 * Database Name
   481 	 * Database Name
   524 	 *
   482 	 *
   525 	 * @since 3.1.0
   483 	 * @since 3.1.0
   526 	 * @access protected
       
   527 	 * @var string
   484 	 * @var string
   528 	 */
   485 	 */
   529 	protected $dbname;
   486 	protected $dbname;
   530 
   487 
   531 	/**
   488 	/**
   532 	 * Database Host
   489 	 * Database Host
   533 	 *
   490 	 *
   534 	 * @since 3.1.0
   491 	 * @since 3.1.0
   535 	 * @access protected
       
   536 	 * @var string
   492 	 * @var string
   537 	 */
   493 	 */
   538 	protected $dbhost;
   494 	protected $dbhost;
   539 
   495 
   540 	/**
   496 	/**
   541 	 * Database Handle
   497 	 * Database Handle
   542 	 *
   498 	 *
   543 	 * @since 0.71
   499 	 * @since 0.71
   544 	 * @access protected
       
   545 	 * @var string
   500 	 * @var string
   546 	 */
   501 	 */
   547 	protected $dbh;
   502 	protected $dbh;
   548 
   503 
   549 	/**
   504 	/**
   550 	 * A textual description of the last query/get_row/get_var call
   505 	 * A textual description of the last query/get_row/get_var call
   551 	 *
   506 	 *
   552 	 * @since 3.0.0
   507 	 * @since 3.0.0
   553 	 * @access public
       
   554 	 * @var string
   508 	 * @var string
   555 	 */
   509 	 */
   556 	public $func_call;
   510 	public $func_call;
   557 
   511 
   558 	/**
   512 	/**
   562 	 * against the required MySQL version for WordPress. Normally, a replacement
   516 	 * against the required MySQL version for WordPress. Normally, a replacement
   563 	 * database drop-in (db.php) will skip these checks, but setting this to true
   517 	 * database drop-in (db.php) will skip these checks, but setting this to true
   564 	 * will force the checks to occur.
   518 	 * will force the checks to occur.
   565 	 *
   519 	 *
   566 	 * @since 3.3.0
   520 	 * @since 3.3.0
   567 	 * @access public
       
   568 	 * @var bool
   521 	 * @var bool
   569 	 */
   522 	 */
   570 	public $is_mysql = null;
   523 	public $is_mysql = null;
   571 
   524 
   572 	/**
   525 	/**
   573 	 * A list of incompatible SQL modes.
   526 	 * A list of incompatible SQL modes.
   574 	 *
   527 	 *
   575 	 * @since 3.9.0
   528 	 * @since 3.9.0
   576 	 * @access protected
       
   577 	 * @var array
   529 	 * @var array
   578 	 */
   530 	 */
   579 	protected $incompatible_modes = array( 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY',
   531 	protected $incompatible_modes = array( 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY',
   580 		'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL' );
   532 		'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL' );
   581 
   533 
   582 	/**
   534 	/**
   583 	 * Whether to use mysqli over mysql.
   535 	 * Whether to use mysqli over mysql.
   584 	 *
   536 	 *
   585 	 * @since 3.9.0
   537 	 * @since 3.9.0
   586 	 * @access private
       
   587 	 * @var bool
   538 	 * @var bool
   588 	 */
   539 	 */
   589 	private $use_mysqli = false;
   540 	private $use_mysqli = false;
   590 
   541 
   591 	/**
   542 	/**
   592 	 * Whether we've managed to successfully connect at some point
   543 	 * Whether we've managed to successfully connect at some point
   593 	 *
   544 	 *
   594 	 * @since 3.9.0
   545 	 * @since 3.9.0
   595 	 * @access private
       
   596 	 * @var bool
   546 	 * @var bool
   597 	 */
   547 	 */
   598 	private $has_connected = false;
   548 	private $has_connected = false;
   599 
   549 
   600 	/**
   550 	/**
   605 	 * to the database.
   555 	 * to the database.
   606 	 *
   556 	 *
   607 	 * @link https://core.trac.wordpress.org/ticket/3354
   557 	 * @link https://core.trac.wordpress.org/ticket/3354
   608 	 * @since 2.0.8
   558 	 * @since 2.0.8
   609 	 *
   559 	 *
   610 	 * @param string $dbuser MySQL database user
   560 	 * @global string $wp_version
       
   561 	 *
       
   562 	 * @param string $dbuser     MySQL database user
   611 	 * @param string $dbpassword MySQL database password
   563 	 * @param string $dbpassword MySQL database password
   612 	 * @param string $dbname MySQL database name
   564 	 * @param string $dbname     MySQL database name
   613 	 * @param string $dbhost MySQL database host
   565 	 * @param string $dbhost     MySQL database host
   614 	 */
   566 	 */
   615 	public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) {
   567 	public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) {
   616 		register_shutdown_function( array( $this, '__destruct' ) );
   568 		register_shutdown_function( array( $this, '__destruct' ) );
   617 
   569 
   618 		if ( WP_DEBUG && WP_DEBUG_DISPLAY )
   570 		if ( WP_DEBUG && WP_DEBUG_DISPLAY )
   619 			$this->show_errors();
   571 			$this->show_errors();
   620 
   572 
   621 		/* Use ext/mysqli if it exists and:
   573 		// Use ext/mysqli if it exists unless WP_USE_EXT_MYSQL is defined as true
   622 		 *  - WP_USE_EXT_MYSQL is defined as false, or
       
   623 		 *  - We are a development version of WordPress, or
       
   624 		 *  - We are running PHP 5.5 or greater, or
       
   625 		 *  - ext/mysql is not loaded.
       
   626 		 */
       
   627 		if ( function_exists( 'mysqli_connect' ) ) {
   574 		if ( function_exists( 'mysqli_connect' ) ) {
       
   575 			$this->use_mysqli = true;
       
   576 
   628 			if ( defined( 'WP_USE_EXT_MYSQL' ) ) {
   577 			if ( defined( 'WP_USE_EXT_MYSQL' ) ) {
   629 				$this->use_mysqli = ! WP_USE_EXT_MYSQL;
   578 				$this->use_mysqli = ! WP_USE_EXT_MYSQL;
   630 			} elseif ( version_compare( phpversion(), '5.5', '>=' ) || ! function_exists( 'mysql_connect' ) ) {
       
   631 				$this->use_mysqli = true;
       
   632 			} elseif ( false !== strpos( $GLOBALS['wp_version'], '-' ) ) {
       
   633 				$this->use_mysqli = true;
       
   634 			}
   579 			}
   635 		}
   580 		}
   636 
   581 
   637 		$this->dbuser = $dbuser;
   582 		$this->dbuser = $dbuser;
   638 		$this->dbpassword = $dbpassword;
   583 		$this->dbpassword = $dbpassword;
   650 	/**
   595 	/**
   651 	 * PHP5 style destructor and will run when database object is destroyed.
   596 	 * PHP5 style destructor and will run when database object is destroyed.
   652 	 *
   597 	 *
   653 	 * @see wpdb::__construct()
   598 	 * @see wpdb::__construct()
   654 	 * @since 2.0.8
   599 	 * @since 2.0.8
   655 	 * @return bool true
   600 	 * @return true
   656 	 */
   601 	 */
   657 	public function __destruct() {
   602 	public function __destruct() {
   658 		return true;
   603 		return true;
   659 	}
   604 	}
   660 
   605 
   661 	/**
   606 	/**
   662 	 * PHP5 style magic getter, used to lazy-load expensive data.
   607 	 * Makes private properties readable for backward compatibility.
   663 	 *
   608 	 *
   664 	 * @since 3.5.0
   609 	 * @since 3.5.0
   665 	 *
   610 	 *
   666 	 * @param string $name The private member to get, and optionally process
   611 	 * @param string $name The private member to get, and optionally process
   667 	 * @return mixed The private member
   612 	 * @return mixed The private member
   672 
   617 
   673 		return $this->$name;
   618 		return $this->$name;
   674 	}
   619 	}
   675 
   620 
   676 	/**
   621 	/**
   677 	 * Magic function, for backwards compatibility.
   622 	 * Makes private properties settable for backward compatibility.
   678 	 *
   623 	 *
   679 	 * @since 3.5.0
   624 	 * @since 3.5.0
   680 	 *
   625 	 *
   681 	 * @param string $name  The private member to set
   626 	 * @param string $name  The private member to set
   682 	 * @param mixed  $value The value to set
   627 	 * @param mixed  $value The value to set
   692 		}
   637 		}
   693 		$this->$name = $value;
   638 		$this->$name = $value;
   694 	}
   639 	}
   695 
   640 
   696 	/**
   641 	/**
   697 	 * Magic function, for backwards compatibility.
   642 	 * Makes private properties check-able for backward compatibility.
   698 	 *
   643 	 *
   699 	 * @since 3.5.0
   644 	 * @since 3.5.0
   700 	 *
   645 	 *
   701 	 * @param string $name  The private member to check
   646 	 * @param string $name  The private member to check
   702 	 *
   647 	 *
   705 	public function __isset( $name ) {
   650 	public function __isset( $name ) {
   706 		return isset( $this->$name );
   651 		return isset( $this->$name );
   707 	}
   652 	}
   708 
   653 
   709 	/**
   654 	/**
   710 	 * Magic function, for backwards compatibility.
   655 	 * Makes private properties un-settable for backward compatibility.
   711 	 *
   656 	 *
   712 	 * @since 3.5.0
   657 	 * @since 3.5.0
   713 	 *
   658 	 *
   714 	 * @param string $name  The private member to unset
   659 	 * @param string $name  The private member to unset
   715 	 */
   660 	 */
   721 	 * Set $this->charset and $this->collate
   666 	 * Set $this->charset and $this->collate
   722 	 *
   667 	 *
   723 	 * @since 3.1.0
   668 	 * @since 3.1.0
   724 	 */
   669 	 */
   725 	public function init_charset() {
   670 	public function init_charset() {
       
   671 		$charset = '';
       
   672 		$collate = '';
       
   673 
   726 		if ( function_exists('is_multisite') && is_multisite() ) {
   674 		if ( function_exists('is_multisite') && is_multisite() ) {
   727 			$this->charset = 'utf8';
   675 			$charset = 'utf8';
   728 			if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) {
   676 			if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) {
   729 				$this->collate = DB_COLLATE;
   677 				$collate = DB_COLLATE;
   730 			} else {
   678 			} else {
   731 				$this->collate = 'utf8_general_ci';
   679 				$collate = 'utf8_general_ci';
   732 			}
   680 			}
   733 		} elseif ( defined( 'DB_COLLATE' ) ) {
   681 		} elseif ( defined( 'DB_COLLATE' ) ) {
   734 			$this->collate = DB_COLLATE;
   682 			$collate = DB_COLLATE;
   735 		}
   683 		}
   736 
   684 
   737 		if ( defined( 'DB_CHARSET' ) ) {
   685 		if ( defined( 'DB_CHARSET' ) ) {
   738 			$this->charset = DB_CHARSET;
   686 			$charset = DB_CHARSET;
   739 		}
   687 		}
   740 
   688 
   741 		if ( ( $this->use_mysqli && ! ( $this->dbh instanceof mysqli ) )
   689 		$charset_collate = $this->determine_charset( $charset, $collate );
   742 		  || ( empty( $this->dbh ) || ! ( $this->dbh instanceof mysqli ) ) ) {
   690 
   743 			return;
   691 		$this->charset = $charset_collate['charset'];
   744 		}
   692 		$this->collate = $charset_collate['collate'];
   745 
   693 	}
   746 		if ( 'utf8' === $this->charset && $this->has_cap( 'utf8mb4' ) ) {
   694 
   747 			$this->charset = 'utf8mb4';
   695 	/**
   748 		}
   696 	 * Determines the best charset and collation to use given a charset and collation.
   749 
   697 	 *
   750 		if ( 'utf8mb4' === $this->charset && ( ! $this->collate || stripos( $this->collate, 'utf8_' ) === 0 ) ) {
   698 	 * For example, when able, utf8mb4 should be used instead of utf8.
   751 			$this->collate = 'utf8mb4_unicode_ci';
   699 	 *
   752 		}
   700 	 * @since 4.6.0
       
   701 	 *
       
   702 	 * @param string $charset The character set to check.
       
   703 	 * @param string $collate The collation to check.
       
   704 	 * @return array The most appropriate character set and collation to use.
       
   705 	 */
       
   706 	public function determine_charset( $charset, $collate ) {
       
   707 		if ( ( $this->use_mysqli && ! ( $this->dbh instanceof mysqli ) ) || empty( $this->dbh ) ) {
       
   708 			return compact( 'charset', 'collate' );
       
   709 		}
       
   710 
       
   711 		if ( 'utf8' === $charset && $this->has_cap( 'utf8mb4' ) ) {
       
   712 			$charset = 'utf8mb4';
       
   713 		}
       
   714 
       
   715 		if ( 'utf8mb4' === $charset && ! $this->has_cap( 'utf8mb4' ) ) {
       
   716 			$charset = 'utf8';
       
   717 			$collate = str_replace( 'utf8mb4_', 'utf8_', $collate );
       
   718 		}
       
   719 
       
   720 		if ( 'utf8mb4' === $charset ) {
       
   721 			// _general_ is outdated, so we can upgrade it to _unicode_, instead.
       
   722 			if ( ! $collate || 'utf8_general_ci' === $collate ) {
       
   723 				$collate = 'utf8mb4_unicode_ci';
       
   724 			} else {
       
   725 				$collate = str_replace( 'utf8_', 'utf8mb4_', $collate );
       
   726 			}
       
   727 		}
       
   728 
       
   729 		// _unicode_520_ is a better collation, we should use that when it's available.
       
   730 		if ( $this->has_cap( 'utf8mb4_520' ) && 'utf8mb4_unicode_ci' === $collate ) {
       
   731 			$collate = 'utf8mb4_unicode_520_ci';
       
   732 		}
       
   733 
       
   734 		return compact( 'charset', 'collate' );
   753 	}
   735 	}
   754 
   736 
   755 	/**
   737 	/**
   756 	 * Sets the connection's character set.
   738 	 * Sets the connection's character set.
   757 	 *
   739 	 *
   765 		if ( ! isset( $charset ) )
   747 		if ( ! isset( $charset ) )
   766 			$charset = $this->charset;
   748 			$charset = $this->charset;
   767 		if ( ! isset( $collate ) )
   749 		if ( ! isset( $collate ) )
   768 			$collate = $this->collate;
   750 			$collate = $this->collate;
   769 		if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) {
   751 		if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) {
       
   752 			$set_charset_succeeded = true;
       
   753 
   770 			if ( $this->use_mysqli ) {
   754 			if ( $this->use_mysqli ) {
   771 				if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) {
   755 				if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) {
   772 					mysqli_set_charset( $dbh, $charset );
   756 					$set_charset_succeeded = mysqli_set_charset( $dbh, $charset );
   773 				} else {
   757 				}
       
   758 
       
   759 				if ( $set_charset_succeeded ) {
   774 					$query = $this->prepare( 'SET NAMES %s', $charset );
   760 					$query = $this->prepare( 'SET NAMES %s', $charset );
   775 					if ( ! empty( $collate ) )
   761 					if ( ! empty( $collate ) )
   776 						$query .= $this->prepare( ' COLLATE %s', $collate );
   762 						$query .= $this->prepare( ' COLLATE %s', $collate );
   777 					mysqli_query( $dbh, $query );
   763 					mysqli_query( $dbh, $query );
   778 				}
   764 				}
   779 			} else {
   765 			} else {
   780 				if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) {
   766 				if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) {
   781 					mysql_set_charset( $charset, $dbh );
   767 					$set_charset_succeeded = mysql_set_charset( $charset, $dbh );
   782 				} else {
   768 				}
       
   769 				if ( $set_charset_succeeded ) {
   783 					$query = $this->prepare( 'SET NAMES %s', $charset );
   770 					$query = $this->prepare( 'SET NAMES %s', $charset );
   784 					if ( ! empty( $collate ) )
   771 					if ( ! empty( $collate ) )
   785 						$query .= $this->prepare( ' COLLATE %s', $collate );
   772 						$query .= $this->prepare( ' COLLATE %s', $collate );
   786 					mysql_query( $query, $dbh );
   773 					mysql_query( $query, $dbh );
   787 				}
   774 				}
   829 		}
   816 		}
   830 
   817 
   831 		$modes = array_change_key_case( $modes, CASE_UPPER );
   818 		$modes = array_change_key_case( $modes, CASE_UPPER );
   832 
   819 
   833 		/**
   820 		/**
   834 		 * Filter the list of incompatible SQL modes to exclude.
   821 		 * Filters the list of incompatible SQL modes to exclude.
   835 		 *
   822 		 *
   836 		 * @since 3.9.0
   823 		 * @since 3.9.0
   837 		 *
   824 		 *
   838 		 * @param array $incompatible_modes An array of incompatible modes.
   825 		 * @param array $incompatible_modes An array of incompatible modes.
   839 		 */
   826 		 */
   840 		$incompatible_modes = (array) apply_filters( 'incompatible_sql_modes', $this->incompatible_modes );
   827 		$incompatible_modes = (array) apply_filters( 'incompatible_sql_modes', $this->incompatible_modes );
   841 
   828 
   842 		foreach( $modes as $i => $mode ) {
   829 		foreach ( $modes as $i => $mode ) {
   843 			if ( in_array( $mode, $incompatible_modes ) ) {
   830 			if ( in_array( $mode, $incompatible_modes ) ) {
   844 				unset( $modes[ $i ] );
   831 				unset( $modes[ $i ] );
   845 			}
   832 			}
   846 		}
   833 		}
   847 
   834 
   857 	/**
   844 	/**
   858 	 * Sets the table prefix for the WordPress tables.
   845 	 * Sets the table prefix for the WordPress tables.
   859 	 *
   846 	 *
   860 	 * @since 2.5.0
   847 	 * @since 2.5.0
   861 	 *
   848 	 *
   862 	 * @param string $prefix Alphanumeric name for the new prefix.
   849 	 * @param string $prefix          Alphanumeric name for the new prefix.
   863 	 * @param bool $set_table_names Optional. Whether the table names, e.g. wpdb::$posts, should be updated or not.
   850 	 * @param bool   $set_table_names Optional. Whether the table names, e.g. wpdb::$posts, should be updated or not.
   864 	 * @return string|WP_Error Old prefix or WP_Error on error
   851 	 * @return string|WP_Error Old prefix or WP_Error on error
   865 	 */
   852 	 */
   866 	public function set_prefix( $prefix, $set_table_names = true ) {
   853 	public function set_prefix( $prefix, $set_table_names = true ) {
   867 
   854 
   868 		if ( preg_match( '|[^a-z0-9_]|i', $prefix ) )
   855 		if ( preg_match( '|[^a-z0-9_]|i', $prefix ) )
   895 
   882 
   896 	/**
   883 	/**
   897 	 * Sets blog id.
   884 	 * Sets blog id.
   898 	 *
   885 	 *
   899 	 * @since 3.0.0
   886 	 * @since 3.0.0
   900 	 * @access public
   887 	 *
   901 	 * @param int $blog_id
   888 	 * @param int $blog_id
   902 	 * @param int $site_id Optional.
   889 	 * @param int $network_id Optional.
   903 	 * @return int previous blog id
   890 	 * @return int previous blog id
   904 	 */
   891 	 */
   905 	public function set_blog_id( $blog_id, $site_id = 0 ) {
   892 	public function set_blog_id( $blog_id, $network_id = 0 ) {
   906 		if ( ! empty( $site_id ) )
   893 		if ( ! empty( $network_id ) ) {
   907 			$this->siteid = $site_id;
   894 			$this->siteid = $network_id;
       
   895 		}
   908 
   896 
   909 		$old_blog_id  = $this->blogid;
   897 		$old_blog_id  = $this->blogid;
   910 		$this->blogid = $blog_id;
   898 		$this->blogid = $blog_id;
   911 
   899 
   912 		$this->prefix = $this->get_blog_prefix();
   900 		$this->prefix = $this->get_blog_prefix();
   960 	 * @uses wpdb::$tables
   948 	 * @uses wpdb::$tables
   961 	 * @uses wpdb::$old_tables
   949 	 * @uses wpdb::$old_tables
   962 	 * @uses wpdb::$global_tables
   950 	 * @uses wpdb::$global_tables
   963 	 * @uses wpdb::$ms_global_tables
   951 	 * @uses wpdb::$ms_global_tables
   964 	 *
   952 	 *
   965 	 * @param string $scope Optional. Can be all, global, ms_global, blog, or old tables. Defaults to all.
   953 	 * @param string $scope   Optional. Can be all, global, ms_global, blog, or old tables. Defaults to all.
   966 	 * @param bool $prefix Optional. Whether to include table prefixes. Default true. If blog
   954 	 * @param bool   $prefix  Optional. Whether to include table prefixes. Default true. If blog
   967 	 * 	prefix is requested, then the custom users and usermeta tables will be mapped.
   955 	 *                        prefix is requested, then the custom users and usermeta tables will be mapped.
   968 	 * @param int $blog_id Optional. The blog_id to prefix. Defaults to wpdb::$blogid. Used only when prefix is requested.
   956 	 * @param int    $blog_id Optional. The blog_id to prefix. Defaults to wpdb::$blogid. Used only when prefix is requested.
   969 	 * @return array Table names. When a prefix is requested, the key is the unprefixed table name.
   957 	 * @return array Table names. When a prefix is requested, the key is the unprefixed table name.
   970 	 */
   958 	 */
   971 	public function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) {
   959 	public function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) {
   972 		switch ( $scope ) {
   960 		switch ( $scope ) {
   973 			case 'all' :
   961 			case 'all' :
  1023 	 * The database name will be changed based on the current database
  1011 	 * The database name will be changed based on the current database
  1024 	 * connection. On failure, the execution will bail and display an DB error.
  1012 	 * connection. On failure, the execution will bail and display an DB error.
  1025 	 *
  1013 	 *
  1026 	 * @since 0.71
  1014 	 * @since 0.71
  1027 	 *
  1015 	 *
  1028 	 * @param string $db MySQL database name
  1016 	 * @param string        $db  MySQL database name
  1029 	 * @param resource $dbh Optional link identifier.
  1017 	 * @param resource|null $dbh Optional link identifier.
  1030 	 * @return null Always null.
       
  1031 	 */
  1018 	 */
  1032 	public function select( $db, $dbh = null ) {
  1019 	public function select( $db, $dbh = null ) {
  1033 		if ( is_null($dbh) )
  1020 		if ( is_null($dbh) )
  1034 			$dbh = $this->dbh;
  1021 			$dbh = $this->dbh;
  1035 
  1022 
  1036 		if ( $this->use_mysqli ) {
  1023 		if ( $this->use_mysqli ) {
  1037 			$success = @mysqli_select_db( $dbh, $db );
  1024 			$success = mysqli_select_db( $dbh, $db );
  1038 		} else {
  1025 		} else {
  1039 			$success = @mysql_select_db( $db, $dbh );
  1026 			$success = mysql_select_db( $db, $dbh );
  1040 		}
  1027 		}
  1041 		if ( ! $success ) {
  1028 		if ( ! $success ) {
  1042 			$this->ready = false;
  1029 			$this->ready = false;
  1043 			if ( ! did_action( 'template_redirect' ) ) {
  1030 			if ( ! did_action( 'template_redirect' ) ) {
  1044 				wp_load_translations_early();
  1031 				wp_load_translations_early();
  1045 				$this->bail( sprintf( __( '<h1>Can&#8217;t select database</h1>
  1032 
  1046 <p>We were able to connect to the database server (which means your username and password is okay) but not able to select the <code>%1$s</code> database.</p>
  1033 				$message = '<h1>' . __( 'Can&#8217;t select database' ) . "</h1>\n";
  1047 <ul>
  1034 
  1048 <li>Are you sure it exists?</li>
  1035 				$message .= '<p>' . sprintf(
  1049 <li>Does the user <code>%2$s</code> have permission to use the <code>%1$s</code> database?</li>
  1036 					/* translators: %s: database name */
  1050 <li>On some systems the name of your database is prefixed with your username, so it would be like <code>username_%1$s</code>. Could that be the problem?</li>
  1037 					__( 'We were able to connect to the database server (which means your username and password is okay) but not able to select the %s database.' ),
  1051 </ul>
  1038 					'<code>' . htmlspecialchars( $db, ENT_QUOTES ) . '</code>'
  1052 <p>If you don\'t know how to set up a database you should <strong>contact your host</strong>. If all else fails you may find help at the <a href="https://wordpress.org/support/">WordPress Support Forums</a>.</p>' ), htmlspecialchars( $db, ENT_QUOTES ), htmlspecialchars( $this->dbuser, ENT_QUOTES ) ), 'db_select_fail' );
  1039 				) . "</p>\n";
  1053 			}
  1040 
  1054 			return;
  1041 				$message .= "<ul>\n";
       
  1042 				$message .= '<li>' . __( 'Are you sure it exists?' ) . "</li>\n";
       
  1043 
       
  1044 				$message .= '<li>' . sprintf(
       
  1045 					/* translators: 1: database user, 2: database name */
       
  1046 					__( 'Does the user %1$s have permission to use the %2$s database?' ),
       
  1047 					'<code>' . htmlspecialchars( $this->dbuser, ENT_QUOTES )  . '</code>',
       
  1048 					'<code>' . htmlspecialchars( $db, ENT_QUOTES ) . '</code>'
       
  1049 				) . "</li>\n";
       
  1050 
       
  1051 				$message .= '<li>' . sprintf(
       
  1052 					/* translators: %s: database name */
       
  1053 					__( '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?' ),
       
  1054 					htmlspecialchars( $db, ENT_QUOTES )
       
  1055 				). "</li>\n";
       
  1056 
       
  1057 				$message .= "</ul>\n";
       
  1058 
       
  1059 				$message .= '<p>' . sprintf(
       
  1060 					/* translators: %s: support forums URL */
       
  1061 					__( 'If you don&#8217;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="%s">WordPress Support Forums</a>.' ),
       
  1062 					__( 'https://wordpress.org/support/' )
       
  1063 				) . "</p>\n";
       
  1064 
       
  1065 				$this->bail( $message, 'db_select_fail' );
       
  1066 			}
  1055 		}
  1067 		}
  1056 	}
  1068 	}
  1057 
  1069 
  1058 	/**
  1070 	/**
  1059 	 * Do not use, deprecated.
  1071 	 * Do not use, deprecated.
  1060 	 *
  1072 	 *
  1061 	 * Use esc_sql() or wpdb::prepare() instead.
  1073 	 * Use esc_sql() or wpdb::prepare() instead.
  1062 	 *
  1074 	 *
  1063 	 * @since 2.8.0
  1075 	 * @since 2.8.0
  1064 	 * @deprecated 3.6.0
  1076 	 * @deprecated 3.6.0 Use wpdb::prepare()
  1065 	 * @see wpdb::prepare
  1077 	 * @see wpdb::prepare
  1066 	 * @see esc_sql()
  1078 	 * @see esc_sql()
  1067 	 * @access private
       
  1068 	 *
  1079 	 *
  1069 	 * @param string $string
  1080 	 * @param string $string
  1070 	 * @return string
  1081 	 * @return string
  1071 	 */
  1082 	 */
  1072 	function _weak_escape( $string ) {
  1083 	function _weak_escape( $string ) {
  1073 		if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) )
  1084 		if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) )
  1074 			_deprecated_function( __METHOD__, '3.6', 'wpdb::prepare() or esc_sql()' );
  1085 			_deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' );
  1075 		return addslashes( $string );
  1086 		return addslashes( $string );
  1076 	}
  1087 	}
  1077 
  1088 
  1078 	/**
  1089 	/**
  1079 	 * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string()
  1090 	 * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string()
  1080 	 *
  1091 	 *
  1081 	 * @see mysqli_real_escape_string()
  1092 	 * @see mysqli_real_escape_string()
  1082 	 * @see mysql_real_escape_string()
  1093 	 * @see mysql_real_escape_string()
  1083 	 * @since 2.8.0
  1094 	 * @since 2.8.0
  1084 	 * @access private
       
  1085 	 *
  1095 	 *
  1086 	 * @param  string $string to escape
  1096 	 * @param  string $string to escape
  1087 	 * @return string escaped
  1097 	 * @return string escaped
  1088 	 */
  1098 	 */
  1089 	function _real_escape( $string ) {
  1099 	function _real_escape( $string ) {
  1090 		if ( $this->dbh ) {
  1100 		if ( $this->dbh ) {
  1091 			if ( $this->use_mysqli ) {
  1101 			if ( $this->use_mysqli ) {
  1092 				return mysqli_real_escape_string( $this->dbh, $string );
  1102 				$escaped = mysqli_real_escape_string( $this->dbh, $string );
  1093 			} else {
  1103 			} else {
  1094 				return mysql_real_escape_string( $string, $this->dbh );
  1104 				$escaped = mysql_real_escape_string( $string, $this->dbh );
  1095 			}
  1105 			}
  1096 		}
       
  1097 
       
  1098 		$class = get_class( $this );
       
  1099 		if ( function_exists( '__' ) ) {
       
  1100 			_doing_it_wrong( $class, sprintf( __( '%s must set a database connection for use with escaping.' ), $class ), E_USER_NOTICE );
       
  1101 		} else {
  1106 		} else {
  1102 			_doing_it_wrong( $class, sprintf( '%s must set a database connection for use with escaping.', $class ), E_USER_NOTICE );
  1107 			$class = get_class( $this );
  1103 		}
  1108 			if ( function_exists( '__' ) ) {
  1104 		return addslashes( $string );
  1109 				/* translators: %s: database access abstraction class, usually wpdb or a class extending wpdb */
       
  1110 				_doing_it_wrong( $class, sprintf( __( '%s must set a database connection for use with escaping.' ), $class ), '3.6.0' );
       
  1111 			} else {
       
  1112 				_doing_it_wrong( $class, sprintf( '%s must set a database connection for use with escaping.', $class ), '3.6.0' );
       
  1113 			}
       
  1114 			$escaped = addslashes( $string );
       
  1115 		}
       
  1116 
       
  1117 		return $this->add_placeholder_escape( $escaped );
  1105 	}
  1118 	}
  1106 
  1119 
  1107 	/**
  1120 	/**
  1108 	 * Escape data. Works on arrays.
  1121 	 * Escape data. Works on arrays.
  1109 	 *
  1122 	 *
  1110 	 * @uses wpdb::_real_escape()
  1123 	 * @uses wpdb::_real_escape()
  1111 	 * @since  2.8.0
  1124 	 * @since  2.8.0
  1112 	 * @access private
       
  1113 	 *
  1125 	 *
  1114 	 * @param  string|array $data
  1126 	 * @param  string|array $data
  1115 	 * @return string|array escaped
  1127 	 * @return string|array escaped
  1116 	 */
  1128 	 */
  1117 	function _escape( $data ) {
  1129 	public function _escape( $data ) {
  1118 		if ( is_array( $data ) ) {
  1130 		if ( is_array( $data ) ) {
  1119 			foreach ( $data as $k => $v ) {
  1131 			foreach ( $data as $k => $v ) {
  1120 				if ( is_array($v) )
  1132 				if ( is_array( $v ) ) {
  1121 					$data[$k] = $this->_escape( $v );
  1133 					$data[$k] = $this->_escape( $v );
  1122 				else
  1134 				} else {
  1123 					$data[$k] = $this->_real_escape( $v );
  1135 					$data[$k] = $this->_real_escape( $v );
       
  1136 				}
  1124 			}
  1137 			}
  1125 		} else {
  1138 		} else {
  1126 			$data = $this->_real_escape( $data );
  1139 			$data = $this->_real_escape( $data );
  1127 		}
  1140 		}
  1128 
  1141 
  1133 	 * Do not use, deprecated.
  1146 	 * Do not use, deprecated.
  1134 	 *
  1147 	 *
  1135 	 * Use esc_sql() or wpdb::prepare() instead.
  1148 	 * Use esc_sql() or wpdb::prepare() instead.
  1136 	 *
  1149 	 *
  1137 	 * @since 0.71
  1150 	 * @since 0.71
  1138 	 * @deprecated 3.6.0
  1151 	 * @deprecated 3.6.0 Use wpdb::prepare()
  1139 	 * @see wpdb::prepare()
  1152 	 * @see wpdb::prepare()
  1140 	 * @see esc_sql()
  1153 	 * @see esc_sql()
  1141 	 *
  1154 	 *
  1142 	 * @param mixed $data
  1155 	 * @param mixed $data
  1143 	 * @return mixed
  1156 	 * @return mixed
  1144 	 */
  1157 	 */
  1145 	public function escape( $data ) {
  1158 	public function escape( $data ) {
  1146 		if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) )
  1159 		if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) )
  1147 			_deprecated_function( __METHOD__, '3.6', 'wpdb::prepare() or esc_sql()' );
  1160 			_deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' );
  1148 		if ( is_array( $data ) ) {
  1161 		if ( is_array( $data ) ) {
  1149 			foreach ( $data as $k => $v ) {
  1162 			foreach ( $data as $k => $v ) {
  1150 				if ( is_array( $v ) )
  1163 				if ( is_array( $v ) )
  1151 					$data[$k] = $this->escape( $v, 'recursive' );
  1164 					$data[$k] = $this->escape( $v, 'recursive' );
  1152 				else
  1165 				else
  1161 
  1174 
  1162 	/**
  1175 	/**
  1163 	 * Escapes content by reference for insertion into the database, for security
  1176 	 * Escapes content by reference for insertion into the database, for security
  1164 	 *
  1177 	 *
  1165 	 * @uses wpdb::_real_escape()
  1178 	 * @uses wpdb::_real_escape()
       
  1179 	 *
  1166 	 * @since 2.3.0
  1180 	 * @since 2.3.0
       
  1181 	 *
  1167 	 * @param string $string to escape
  1182 	 * @param string $string to escape
  1168 	 * @return void
       
  1169 	 */
  1183 	 */
  1170 	public function escape_by_ref( &$string ) {
  1184 	public function escape_by_ref( &$string ) {
  1171 		if ( ! is_float( $string ) )
  1185 		if ( ! is_float( $string ) )
  1172 			$string = $this->_real_escape( $string );
  1186 			$string = $this->_real_escape( $string );
  1173 	}
  1187 	}
  1174 
  1188 
  1175 	/**
  1189 	/**
  1176 	 * Prepares a SQL query for safe execution. Uses sprintf()-like syntax.
  1190 	 * Prepares a SQL query for safe execution. Uses sprintf()-like syntax.
  1177 	 *
  1191 	 *
  1178 	 * The following directives can be used in the query format string:
  1192 	 * The following placeholders can be used in the query string:
  1179 	 *   %d (integer)
  1193 	 *   %d (integer)
  1180 	 *   %f (float)
  1194 	 *   %f (float)
  1181 	 *   %s (string)
  1195 	 *   %s (string)
  1182 	 *   %% (literal percentage sign - no argument needed)
  1196 	 *
  1183 	 *
  1197 	 * All placeholders MUST be left unquoted in the query string. A corresponding argument MUST be passed for each placeholder.
  1184 	 * All of %d, %f, and %s are to be left unquoted in the query string and they need an argument passed for them.
  1198 	 *
  1185 	 * Literals (%) as parts of the query must be properly written as %%.
  1199 	 * For compatibility with old behavior, numbered or formatted string placeholders (eg, %1$s, %5s) will not have quotes
  1186 	 *
  1200 	 * added by this function, so should be passed with appropriate quotes around them for your usage.
  1187 	 * This function only supports a small subset of the sprintf syntax; it only supports %d (integer), %f (float), and %s (string).
  1201 	 *
  1188 	 * Does not support sign, padding, alignment, width or precision specifiers.
  1202 	 * Literal percentage signs (%) in the query string must be written as %%. Percentage wildcards (for example,
  1189 	 * Does not support argument numbering/swapping.
  1203 	 * to use in LIKE syntax) must be passed via a substitution argument containing the complete LIKE string, these
  1190 	 *
  1204 	 * cannot be inserted directly in the query string. Also see {@see esc_like()}.
  1191 	 * May be called like {@link http://php.net/sprintf sprintf()} or like {@link http://php.net/vsprintf vsprintf()}.
  1205 	 *
  1192 	 *
  1206 	 * Arguments may be passed as individual arguments to the method, or as a single array containing all arguments. A combination
  1193 	 * Both %d and %s should be left unquoted in the query string.
  1207 	 * of the two is not supported.
  1194 	 *
  1208 	 *
  1195 	 *     wpdb::prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d", 'foo', 1337 )
  1209 	 * Examples:
  1196 	 *     wpdb::prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' );
  1210 	 *     $wpdb->prepare( "SELECT * FROM `table` WHERE `column` = %s AND `field` = %d OR `other_field` LIKE %s", array( 'foo', 1337, '%bar' ) );
  1197 	 *
  1211 	 *     $wpdb->prepare( "SELECT DATE_FORMAT(`field`, '%%c') FROM `table` WHERE `column` = %s", 'foo' );
  1198 	 * @link http://php.net/sprintf Description of syntax.
  1212 	 *
       
  1213 	 * @link https://secure.php.net/sprintf Description of syntax.
  1199 	 * @since 2.3.0
  1214 	 * @since 2.3.0
  1200 	 *
  1215 	 *
  1201 	 * @param string $query Query statement with sprintf()-like placeholders
  1216 	 * @param string      $query    Query statement with sprintf()-like placeholders
  1202 	 * @param array|mixed $args The array of variables to substitute into the query's placeholders if being called like
  1217 	 * @param array|mixed $args     The array of variables to substitute into the query's placeholders if being called with an array of arguments,
  1203 	 * 	{@link http://php.net/vsprintf vsprintf()}, or the first variable to substitute into the query's placeholders if
  1218 	 *                              or the first variable to substitute into the query's placeholders if being called with individual arguments.
  1204 	 * 	being called like {@link http://php.net/sprintf sprintf()}.
  1219 	 * @param mixed       $args,... further variables to substitute into the query's placeholders if being called wih individual arguments.
  1205 	 * @param mixed $args,... further variables to substitute into the query's placeholders if being called like
  1220 	 * @return string|void Sanitized query string, if there is a query to prepare.
  1206 	 * 	{@link http://php.net/sprintf sprintf()}.
       
  1207 	 * @return null|false|string Sanitized query string, null if there is no query, false if there is an error and string
       
  1208 	 * 	if there was something to prepare
       
  1209 	 */
  1221 	 */
  1210 	public function prepare( $query, $args ) {
  1222 	public function prepare( $query, $args ) {
  1211 		if ( is_null( $query ) )
  1223 		if ( is_null( $query ) ) {
  1212 			return;
  1224 			return;
       
  1225 		}
  1213 
  1226 
  1214 		// This is not meant to be foolproof -- but it will catch obviously incorrect usage.
  1227 		// This is not meant to be foolproof -- but it will catch obviously incorrect usage.
  1215 		if ( strpos( $query, '%' ) === false ) {
  1228 		if ( strpos( $query, '%' ) === false ) {
  1216 			_doing_it_wrong( 'wpdb::prepare', sprintf( __( 'The query argument of %s must have a placeholder.' ), 'wpdb::prepare()' ), '3.9' );
  1229 			wp_load_translations_early();
       
  1230 			_doing_it_wrong( 'wpdb::prepare', sprintf( __( 'The query argument of %s must have a placeholder.' ), 'wpdb::prepare()' ), '3.9.0' );
  1217 		}
  1231 		}
  1218 
  1232 
  1219 		$args = func_get_args();
  1233 		$args = func_get_args();
  1220 		array_shift( $args );
  1234 		array_shift( $args );
  1221 		// If args were passed as an array (as in vsprintf), move them up
  1235 
  1222 		if ( isset( $args[0] ) && is_array($args[0]) )
  1236 		// If args were passed as an array (as in vsprintf), move them up.
       
  1237 		$passed_as_array = false;
       
  1238 		if ( is_array( $args[0] ) && count( $args ) == 1 ) {
       
  1239 			$passed_as_array = true;
  1223 			$args = $args[0];
  1240 			$args = $args[0];
  1224 		$query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it
  1241 		}
  1225 		$query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
  1242 
  1226 		$query = preg_replace( '|(?<!%)%f|' , '%F', $query ); // Force floats to be locale unaware
  1243 		foreach ( $args as $arg ) {
  1227 		$query = preg_replace( '|(?<!%)%s|', "'%s'", $query ); // quote the strings, avoiding escaped strings like %%s
  1244 			if ( ! is_scalar( $arg ) && ! is_null( $arg ) ) {
       
  1245 				wp_load_translations_early();
       
  1246 				_doing_it_wrong( 'wpdb::prepare', sprintf( __( 'Unsupported value type (%s).' ), gettype( $arg ) ), '4.8.2' );
       
  1247 			}
       
  1248 		}
       
  1249 
       
  1250 		/*
       
  1251 		 * Specify the formatting allowed in a placeholder. The following are allowed:
       
  1252 		 *
       
  1253 		 * - Sign specifier. eg, $+d
       
  1254 		 * - Numbered placeholders. eg, %1$s
       
  1255 		 * - Padding specifier, including custom padding characters. eg, %05s, %'#5s
       
  1256 		 * - Alignment specifier. eg, %05-s
       
  1257 		 * - Precision specifier. eg, %.2f
       
  1258 		 */
       
  1259 		$allowed_format = '(?:[1-9][0-9]*[$])?[-+0-9]*(?: |0|\'.)?[-+0-9]*(?:\.[0-9]+)?';
       
  1260 
       
  1261 		/*
       
  1262 		 * If a %s placeholder already has quotes around it, removing the existing quotes and re-inserting them
       
  1263 		 * ensures the quotes are consistent.
       
  1264 		 *
       
  1265 		 * For backwards compatibility, this is only applied to %s, and not to placeholders like %1$s, which are frequently
       
  1266 		 * used in the middle of longer strings, or as table name placeholders.
       
  1267 		 */
       
  1268 		$query = str_replace( "'%s'", '%s', $query ); // Strip any existing single quotes.
       
  1269 		$query = str_replace( '"%s"', '%s', $query ); // Strip any existing double quotes.
       
  1270 		$query = preg_replace( '/(?<!%)%s/', "'%s'", $query ); // Quote the strings, avoiding escaped strings like %%s.
       
  1271 
       
  1272 		$query = preg_replace( "/(?<!%)(%($allowed_format)?f)/" , '%\\2F', $query ); // Force floats to be locale unaware.
       
  1273 
       
  1274 		$query = preg_replace( "/%(?:%|$|(?!($allowed_format)?[sdF]))/", '%%\\1', $query ); // Escape any unescaped percents.
       
  1275 
       
  1276 		// Count the number of valid placeholders in the query.
       
  1277 		$placeholders = preg_match_all( "/(^|[^%]|(%%)+)%($allowed_format)?[sdF]/", $query, $matches );
       
  1278 
       
  1279 		if ( count( $args ) !== $placeholders ) {
       
  1280 			if ( 1 === $placeholders && $passed_as_array ) {
       
  1281 				// If the passed query only expected one argument, but the wrong number of arguments were sent as an array, bail.
       
  1282 				wp_load_translations_early();
       
  1283 				_doing_it_wrong( 'wpdb::prepare', __( 'The query only expected one placeholder, but an array of multiple placeholders was sent.' ), '4.9.0' );
       
  1284 
       
  1285 				return;
       
  1286 			} else {
       
  1287 				/*
       
  1288 				 * If we don't have the right number of placeholders, but they were passed as individual arguments,
       
  1289 				 * or we were expecting multiple arguments in an array, throw a warning.
       
  1290 				 */
       
  1291 				wp_load_translations_early();
       
  1292 				_doing_it_wrong( 'wpdb::prepare',
       
  1293 					/* translators: 1: number of placeholders, 2: number of arguments passed */
       
  1294 					sprintf( __( 'The query does not contain the correct number of placeholders (%1$d) for the number of arguments passed (%2$d).' ),
       
  1295 						$placeholders,
       
  1296 						count( $args ) ),
       
  1297 					'4.8.3'
       
  1298 				);
       
  1299 			}
       
  1300 		}
       
  1301 
  1228 		array_walk( $args, array( $this, 'escape_by_ref' ) );
  1302 		array_walk( $args, array( $this, 'escape_by_ref' ) );
  1229 		return @vsprintf( $query, $args );
  1303 		$query = @vsprintf( $query, $args );
       
  1304 
       
  1305 		return $this->add_placeholder_escape( $query );
  1230 	}
  1306 	}
  1231 
  1307 
  1232 	/**
  1308 	/**
  1233 	 * First half of escaping for LIKE special characters % and _ before preparing for MySQL.
  1309 	 * First half of escaping for LIKE special characters % and _ before preparing for MySQL.
  1234 	 *
  1310 	 *
  1235 	 * Use this only before wpdb::prepare() or esc_sql().  Reversing the order is very bad for security.
  1311 	 * Use this only before wpdb::prepare() or esc_sql().  Reversing the order is very bad for security.
  1236 	 *
  1312 	 *
  1237 	 * Example Prepared Statement:
  1313 	 * Example Prepared Statement:
  1238 	 *  $wild = '%';
  1314 	 *
  1239 	 *  $find = 'only 43% of planets';
  1315 	 *     $wild = '%';
  1240 	 *  $like = $wild . $wpdb->esc_like( $find ) . $wild;
  1316 	 *     $find = 'only 43% of planets';
  1241 	 *  $sql  = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like );
  1317 	 *     $like = $wild . $wpdb->esc_like( $find ) . $wild;
       
  1318 	 *     $sql  = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE %s", $like );
  1242 	 *
  1319 	 *
  1243 	 * Example Escape Chain:
  1320 	 * Example Escape Chain:
  1244 	 *  $sql  = esc_sql( $wpdb->esc_like( $input ) );
  1321 	 *
       
  1322 	 *     $sql  = esc_sql( $wpdb->esc_like( $input ) );
  1245 	 *
  1323 	 *
  1246 	 * @since 4.0.0
  1324 	 * @since 4.0.0
  1247 	 * @access public
       
  1248 	 *
  1325 	 *
  1249 	 * @param string $text The raw text to be escaped. The input typed by the user should have no
  1326 	 * @param string $text The raw text to be escaped. The input typed by the user should have no
  1250 	 *                     extra or deleted slashes.
  1327 	 *                     extra or deleted slashes.
  1251 	 * @return string Text in the form of a LIKE phrase. The output is not SQL safe. Call $wpdb::prepare()
  1328 	 * @return string Text in the form of a LIKE phrase. The output is not SQL safe. Call $wpdb::prepare()
  1252 	 *                or real_escape next.
  1329 	 *                or real_escape next.
  1260 	 *
  1337 	 *
  1261 	 * @since 0.71
  1338 	 * @since 0.71
  1262 	 * @global array $EZSQL_ERROR Stores error information of query and error string
  1339 	 * @global array $EZSQL_ERROR Stores error information of query and error string
  1263 	 *
  1340 	 *
  1264 	 * @param string $str The error to display
  1341 	 * @param string $str The error to display
  1265 	 * @return false|null False if the showing of errors is disabled.
  1342 	 * @return false|void False if the showing of errors is disabled.
  1266 	 */
  1343 	 */
  1267 	public function print_error( $str = '' ) {
  1344 	public function print_error( $str = '' ) {
  1268 		global $EZSQL_ERROR;
  1345 		global $EZSQL_ERROR;
  1269 
  1346 
  1270 		if ( !$str ) {
  1347 		if ( !$str ) {
  1279 		if ( $this->suppress_errors )
  1356 		if ( $this->suppress_errors )
  1280 			return false;
  1357 			return false;
  1281 
  1358 
  1282 		wp_load_translations_early();
  1359 		wp_load_translations_early();
  1283 
  1360 
  1284 		if ( $caller = $this->get_caller() )
  1361 		if ( $caller = $this->get_caller() ) {
       
  1362 			/* translators: 1: Database error message, 2: SQL query, 3: Name of the calling function */
  1285 			$error_str = sprintf( __( 'WordPress database error %1$s for query %2$s made by %3$s' ), $str, $this->last_query, $caller );
  1363 			$error_str = sprintf( __( 'WordPress database error %1$s for query %2$s made by %3$s' ), $str, $this->last_query, $caller );
  1286 		else
  1364 		} else {
       
  1365 			/* translators: 1: Database error message, 2: SQL query */
  1287 			$error_str = sprintf( __( 'WordPress database error %1$s for query %2$s' ), $str, $this->last_query );
  1366 			$error_str = sprintf( __( 'WordPress database error %1$s for query %2$s' ), $str, $this->last_query );
       
  1367 		}
  1288 
  1368 
  1289 		error_log( $error_str );
  1369 		error_log( $error_str );
  1290 
  1370 
  1291 		// Are we showing errors?
  1371 		// Are we showing errors?
  1292 		if ( ! $this->show_errors )
  1372 		if ( ! $this->show_errors )
  1293 			return false;
  1373 			return false;
  1294 
  1374 
  1295 		// If there is an error then take note of it
  1375 		// If there is an error then take note of it
  1296 		if ( is_multisite() ) {
  1376 		if ( is_multisite() ) {
  1297 			$msg = "WordPress database error: [$str]\n{$this->last_query}\n";
  1377 			$msg = sprintf(
  1298 			if ( defined( 'ERRORLOGFILE' ) )
  1378 				"%s [%s]\n%s\n",
       
  1379 				__( 'WordPress database error:' ),
       
  1380 				$str,
       
  1381 				$this->last_query
       
  1382 			);
       
  1383 
       
  1384 			if ( defined( 'ERRORLOGFILE' ) ) {
  1299 				error_log( $msg, 3, ERRORLOGFILE );
  1385 				error_log( $msg, 3, ERRORLOGFILE );
  1300 			if ( defined( 'DIEONDBERROR' ) )
  1386 			}
       
  1387 			if ( defined( 'DIEONDBERROR' ) ) {
  1301 				wp_die( $msg );
  1388 				wp_die( $msg );
       
  1389 			}
  1302 		} else {
  1390 		} else {
  1303 			$str   = htmlspecialchars( $str, ENT_QUOTES );
  1391 			$str   = htmlspecialchars( $str, ENT_QUOTES );
  1304 			$query = htmlspecialchars( $this->last_query, ENT_QUOTES );
  1392 			$query = htmlspecialchars( $this->last_query, ENT_QUOTES );
  1305 
  1393 
  1306 			print "<div id='error'>
  1394 			printf(
  1307 			<p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br />
  1395 				'<div id="error"><p class="wpdberror"><strong>%s</strong> [%s]<br /><code>%s</code></p></div>',
  1308 			<code>$query</code></p>
  1396 				__( 'WordPress database error:' ),
  1309 			</div>";
  1397 				$str,
       
  1398 				$query
       
  1399 			);
  1310 		}
  1400 		}
  1311 	}
  1401 	}
  1312 
  1402 
  1313 	/**
  1403 	/**
  1314 	 * Enables showing of database errors.
  1404 	 * Enables showing of database errors.
  1365 
  1455 
  1366 	/**
  1456 	/**
  1367 	 * Kill cached query results.
  1457 	 * Kill cached query results.
  1368 	 *
  1458 	 *
  1369 	 * @since 0.71
  1459 	 * @since 0.71
  1370 	 * @return void
       
  1371 	 */
  1460 	 */
  1372 	public function flush() {
  1461 	public function flush() {
  1373 		$this->last_result = array();
  1462 		$this->last_result = array();
  1374 		$this->col_info    = null;
  1463 		$this->col_info    = null;
  1375 		$this->last_query  = null;
  1464 		$this->last_query  = null;
  1402 	 *
  1491 	 *
  1403 	 * @since 3.0.0
  1492 	 * @since 3.0.0
  1404 	 * @since 3.9.0 $allow_bail parameter added.
  1493 	 * @since 3.9.0 $allow_bail parameter added.
  1405 	 *
  1494 	 *
  1406 	 * @param bool $allow_bail Optional. Allows the function to bail. Default true.
  1495 	 * @param bool $allow_bail Optional. Allows the function to bail. Default true.
  1407 	 * @return null|bool True with a successful connection, false on failure.
  1496 	 * @return bool True with a successful connection, false on failure.
  1408 	 */
  1497 	 */
  1409 	public function db_connect( $allow_bail = true ) {
  1498 	public function db_connect( $allow_bail = true ) {
  1410 
       
  1411 		$this->is_mysql = true;
  1499 		$this->is_mysql = true;
  1412 
  1500 
  1413 		/*
  1501 		/*
  1414 		 * Deprecated in 3.9+ when using MySQLi. No equivalent
  1502 		 * Deprecated in 3.9+ when using MySQLi. No equivalent
  1415 		 * $new_link parameter exists for mysqli_* functions.
  1503 		 * $new_link parameter exists for mysqli_* functions.
  1418 		$client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0;
  1506 		$client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0;
  1419 
  1507 
  1420 		if ( $this->use_mysqli ) {
  1508 		if ( $this->use_mysqli ) {
  1421 			$this->dbh = mysqli_init();
  1509 			$this->dbh = mysqli_init();
  1422 
  1510 
  1423 			// mysqli_real_connect doesn't support the host param including a port or socket
  1511 			$host    = $this->dbhost;
  1424 			// like mysql_connect does. This duplicates how mysql_connect detects a port and/or socket file.
  1512 			$port    = null;
  1425 			$port = null;
  1513 			$socket  = null;
  1426 			$socket = null;
  1514 			$is_ipv6 = false;
  1427 			$host = $this->dbhost;
  1515 
  1428 			$port_or_socket = strstr( $host, ':' );
  1516 			if ( $host_data = $this->parse_db_host( $this->dbhost ) ) {
  1429 			if ( ! empty( $port_or_socket ) ) {
  1517 				list( $host, $port, $socket, $is_ipv6 ) = $host_data;
  1430 				$host = substr( $host, 0, strpos( $host, ':' ) );
  1518 			}
  1431 				$port_or_socket = substr( $port_or_socket, 1 );
  1519 
  1432 				if ( 0 !== strpos( $port_or_socket, '/' ) ) {
  1520 			/*
  1433 					$port = intval( $port_or_socket );
  1521 			 * If using the `mysqlnd` library, the IPv6 address needs to be
  1434 					$maybe_socket = strstr( $port_or_socket, ':' );
  1522 			 * enclosed in square brackets, whereas it doesn't while using the
  1435 					if ( ! empty( $maybe_socket ) ) {
  1523 			 * `libmysqlclient` library.
  1436 						$socket = substr( $maybe_socket, 1 );
  1524 			 * @see https://bugs.php.net/bug.php?id=67563
  1437 					}
  1525 			 */
  1438 				} else {
  1526 			if ( $is_ipv6 && extension_loaded( 'mysqlnd' ) ) {
  1439 					$socket = $port_or_socket;
  1527 				$host = "[$host]";
  1440 				}
       
  1441 			}
  1528 			}
  1442 
  1529 
  1443 			if ( WP_DEBUG ) {
  1530 			if ( WP_DEBUG ) {
  1444 				mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
  1531 				mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
  1445 			} else {
  1532 			} else {
  1447 			}
  1534 			}
  1448 
  1535 
  1449 			if ( $this->dbh->connect_errno ) {
  1536 			if ( $this->dbh->connect_errno ) {
  1450 				$this->dbh = null;
  1537 				$this->dbh = null;
  1451 
  1538 
  1452 				/* It's possible ext/mysqli is misconfigured. Fall back to ext/mysql if:
  1539 				/*
       
  1540 				 * It's possible ext/mysqli is misconfigured. Fall back to ext/mysql if:
  1453 		 		 *  - We haven't previously connected, and
  1541 		 		 *  - We haven't previously connected, and
  1454 		 		 *  - WP_USE_EXT_MYSQL isn't set to false, and
  1542 		 		 *  - WP_USE_EXT_MYSQL isn't set to false, and
  1455 		 		 *  - ext/mysql is loaded.
  1543 		 		 *  - ext/mysql is loaded.
  1456 		 		 */
  1544 		 		 */
  1457 				$attempt_fallback = true;
  1545 				$attempt_fallback = true;
  1464 					$attempt_fallback = false;
  1552 					$attempt_fallback = false;
  1465 				}
  1553 				}
  1466 
  1554 
  1467 				if ( $attempt_fallback ) {
  1555 				if ( $attempt_fallback ) {
  1468 					$this->use_mysqli = false;
  1556 					$this->use_mysqli = false;
  1469 					$this->db_connect();
  1557 					return $this->db_connect( $allow_bail );
  1470 				}
  1558 				}
  1471 			}
  1559 			}
  1472 		} else {
  1560 		} else {
  1473 			if ( WP_DEBUG ) {
  1561 			if ( WP_DEBUG ) {
  1474 				$this->dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags );
  1562 				$this->dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags );
  1484 			if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) {
  1572 			if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) {
  1485 				require_once( WP_CONTENT_DIR . '/db-error.php' );
  1573 				require_once( WP_CONTENT_DIR . '/db-error.php' );
  1486 				die();
  1574 				die();
  1487 			}
  1575 			}
  1488 
  1576 
  1489 			$this->bail( sprintf( __( "
  1577 			$message = '<h1>' . __( 'Error establishing a database connection' ) . "</h1>\n";
  1490 <h1>Error establishing a database connection</h1>
  1578 
  1491 <p>This either means that the username and password information in your <code>wp-config.php</code> file is incorrect or we can't contact the database server at <code>%s</code>. This could mean your host's database server is down.</p>
  1579 			$message .= '<p>' . sprintf(
  1492 <ul>
  1580 				/* translators: 1: wp-config.php. 2: database host */
  1493 	<li>Are you sure you have the correct username and password?</li>
  1581 				__( 'This either means that the username and password information in your %1$s file is incorrect or we can&#8217;t contact the database server at %2$s. This could mean your host&#8217;s database server is down.' ),
  1494 	<li>Are you sure that you have typed the correct hostname?</li>
  1582 				'<code>wp-config.php</code>',
  1495 	<li>Are you sure that the database server is running?</li>
  1583 				'<code>' . htmlspecialchars( $this->dbhost, ENT_QUOTES ) . '</code>'
  1496 </ul>
  1584 			) . "</p>\n";
  1497 <p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='https://wordpress.org/support/'>WordPress Support Forums</a>.</p>
  1585 
  1498 " ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' );
  1586 			$message .= "<ul>\n";
       
  1587 			$message .= '<li>' . __( 'Are you sure you have the correct username and password?' ) . "</li>\n";
       
  1588 			$message .= '<li>' . __( 'Are you sure that you have typed the correct hostname?' ) . "</li>\n";
       
  1589 			$message .= '<li>' . __( 'Are you sure that the database server is running?' ) . "</li>\n";
       
  1590 			$message .= "</ul>\n";
       
  1591 
       
  1592 			$message .= '<p>' . sprintf(
       
  1593 				/* translators: %s: support forums URL */
       
  1594 				__( 'If you&#8217;re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress Support Forums</a>.' ),
       
  1595 				__( 'https://wordpress.org/support/' )
       
  1596 			) . "</p>\n";
       
  1597 
       
  1598 			$this->bail( $message, 'db_connect_fail' );
  1499 
  1599 
  1500 			return false;
  1600 			return false;
  1501 		} elseif ( $this->dbh ) {
  1601 		} elseif ( $this->dbh ) {
  1502 			if ( ! $this->has_connected ) {
  1602 			if ( ! $this->has_connected ) {
  1503 				$this->init_charset();
  1603 				$this->init_charset();
  1516 
  1616 
  1517 		return false;
  1617 		return false;
  1518 	}
  1618 	}
  1519 
  1619 
  1520 	/**
  1620 	/**
  1521 	 * Check that the connection to the database is still up. If not, try to reconnect.
  1621 	 * Parse the DB_HOST setting to interpret it for mysqli_real_connect.
       
  1622 	 *
       
  1623 	 * mysqli_real_connect doesn't support the host param including a port or
       
  1624 	 * socket like mysql_connect does. This duplicates how mysql_connect detects
       
  1625 	 * a port and/or socket file.
       
  1626 	 *
       
  1627 	 * @since 4.9.0
       
  1628 	 *
       
  1629 	 * @param string $host The DB_HOST setting to parse.
       
  1630 	 * @return array|bool Array containing the host, the port, the socket and whether
       
  1631 	 *                    it is an IPv6 address, in that order. If $host couldn't be parsed,
       
  1632 	 *                    returns false.
       
  1633 	 */
       
  1634 	public function parse_db_host( $host ) {
       
  1635 		$port    = null;
       
  1636 		$socket  = null;
       
  1637 		$is_ipv6 = false;
       
  1638 
       
  1639 		// First peel off the socket parameter from the right, if it exists.
       
  1640 		$socket_pos = strpos( $host, ':/' );
       
  1641 		if ( $socket_pos !== false ) {
       
  1642 			$socket = substr( $host, $socket_pos + 1 );
       
  1643 			$host = substr( $host, 0, $socket_pos );
       
  1644 		}
       
  1645 
       
  1646 		// We need to check for an IPv6 address first.
       
  1647 		// An IPv6 address will always contain at least two colons.
       
  1648 		if ( substr_count( $host, ':' ) > 1 ) {
       
  1649 			$pattern = '#^(?:\[)?(?P<host>[0-9a-fA-F:]+)(?:\]:(?P<port>[\d]+))?#';
       
  1650 			$is_ipv6 = true;
       
  1651 		} else {
       
  1652 			// We seem to be dealing with an IPv4 address.
       
  1653 			$pattern = '#^(?P<host>[^:/]*)(?::(?P<port>[\d]+))?#';
       
  1654 		}
       
  1655 
       
  1656 		$matches = array();
       
  1657 		$result = preg_match( $pattern, $host, $matches );
       
  1658 
       
  1659 		if ( 1 !== $result ) {
       
  1660 			// Couldn't parse the address, bail.
       
  1661 			return false;
       
  1662 		}
       
  1663 
       
  1664 		$host = '';
       
  1665 		foreach ( array( 'host', 'port' ) as $component ) {
       
  1666 			if ( ! empty( $matches[ $component ] ) ) {
       
  1667 				$$component = $matches[ $component ];
       
  1668 			}
       
  1669 		}
       
  1670 
       
  1671 		return array( $host, $port, $socket, $is_ipv6 );
       
  1672 	}
       
  1673 
       
  1674 	/**
       
  1675 	 * Checks that the connection to the database is still up. If not, try to reconnect.
  1522 	 *
  1676 	 *
  1523 	 * If this function is unable to reconnect, it will forcibly die, or if after the
  1677 	 * If this function is unable to reconnect, it will forcibly die, or if after the
  1524 	 * the template_redirect hook has been fired, return false instead.
  1678 	 * the {@see 'template_redirect'} hook has been fired, return false instead.
  1525 	 *
  1679 	 *
  1526 	 * If $allow_bail is false, the lack of database connection will need
  1680 	 * If $allow_bail is false, the lack of database connection will need
  1527 	 * to be handled manually.
  1681 	 * to be handled manually.
  1528 	 *
  1682 	 *
  1529 	 * @since 3.9.0
  1683 	 * @since 3.9.0
  1530 	 *
  1684 	 *
  1531 	 * @param bool $allow_bail Optional. Allows the function to bail. Default true.
  1685 	 * @param bool $allow_bail Optional. Allows the function to bail. Default true.
  1532 	 * @return bool|null True if the connection is up.
  1686 	 * @return bool|void True if the connection is up.
  1533 	 */
  1687 	 */
  1534 	public function check_connection( $allow_bail = true ) {
  1688 	public function check_connection( $allow_bail = true ) {
  1535 		if ( $this->use_mysqli ) {
  1689 		if ( $this->use_mysqli ) {
  1536 			if ( @mysqli_ping( $this->dbh ) ) {
  1690 			if ( ! empty( $this->dbh ) && mysqli_ping( $this->dbh ) ) {
  1537 				return true;
  1691 				return true;
  1538 			}
  1692 			}
  1539 		} else {
  1693 		} else {
  1540 			if ( @mysql_ping( $this->dbh ) ) {
  1694 			if ( ! empty( $this->dbh ) && mysql_ping( $this->dbh ) ) {
  1541 				return true;
  1695 				return true;
  1542 			}
  1696 			}
  1543 		}
  1697 		}
  1544 
  1698 
  1545 		$error_reporting = false;
  1699 		$error_reporting = false;
  1576 
  1730 
  1577 		if ( ! $allow_bail ) {
  1731 		if ( ! $allow_bail ) {
  1578 			return false;
  1732 			return false;
  1579 		}
  1733 		}
  1580 
  1734 
       
  1735 		wp_load_translations_early();
       
  1736 
       
  1737 		$message = '<h1>' . __( 'Error reconnecting to the database' ) . "</h1>\n";
       
  1738 
       
  1739 		$message .= '<p>' . sprintf(
       
  1740 			/* translators: %s: database host */
       
  1741 			__( 'This means that we lost contact with the database server at %s. This could mean your host&#8217;s database server is down.' ),
       
  1742 			'<code>' . htmlspecialchars( $this->dbhost, ENT_QUOTES ) . '</code>'
       
  1743 		) . "</p>\n";
       
  1744 
       
  1745 		$message .= "<ul>\n";
       
  1746 		$message .= '<li>' . __( 'Are you sure that the database server is running?' ) . "</li>\n";
       
  1747 		$message .= '<li>' . __( 'Are you sure that the database server is not under particularly heavy load?' ) . "</li>\n";
       
  1748 		$message .= "</ul>\n";
       
  1749 
       
  1750 		$message .= '<p>' . sprintf(
       
  1751 			/* translators: %s: support forums URL */
       
  1752 			__( 'If you&#8217;re unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress Support Forums</a>.' ),
       
  1753 			__( 'https://wordpress.org/support/' )
       
  1754 		) . "</p>\n";
       
  1755 
  1581 		// We weren't able to reconnect, so we better bail.
  1756 		// We weren't able to reconnect, so we better bail.
  1582 		$this->bail( sprintf( ( "
  1757 		$this->bail( $message, 'db_connect_fail' );
  1583 <h1>Error reconnecting to the database</h1>
       
  1584 <p>This means that we lost contact with the database server at <code>%s</code>. This could mean your host's database server is down.</p>
       
  1585 <ul>
       
  1586 	<li>Are you sure that the database server is running?</li>
       
  1587 	<li>Are you sure that the database server is not under particularly heavy load?</li>
       
  1588 </ul>
       
  1589 <p>If you're unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href='https://wordpress.org/support/'>WordPress Support Forums</a>.</p>
       
  1590 " ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' );
       
  1591 
  1758 
  1592 		// Call dead_db() if bail didn't die, because this database is no more. It has ceased to be (at least temporarily).
  1759 		// Call dead_db() if bail didn't die, because this database is no more. It has ceased to be (at least temporarily).
  1593 		dead_db();
  1760 		dead_db();
  1594 	}
  1761 	}
  1595 
  1762 
  1608 			$this->check_current_query = true;
  1775 			$this->check_current_query = true;
  1609 			return false;
  1776 			return false;
  1610 		}
  1777 		}
  1611 
  1778 
  1612 		/**
  1779 		/**
  1613 		 * Filter the database query.
  1780 		 * Filters the database query.
  1614 		 *
  1781 		 *
  1615 		 * Some queries are made before the plugins have been loaded,
  1782 		 * Some queries are made before the plugins have been loaded,
  1616 		 * and thus cannot be filtered with this method.
  1783 		 * and thus cannot be filtered with this method.
  1617 		 *
  1784 		 *
  1618 		 * @since 2.1.0
  1785 		 * @since 2.1.0
  1638 			}
  1805 			}
  1639 		}
  1806 		}
  1640 
  1807 
  1641 		$this->check_current_query = true;
  1808 		$this->check_current_query = true;
  1642 
  1809 
  1643 		// Keep track of the last query for debug..
  1810 		// Keep track of the last query for debug.
  1644 		$this->last_query = $query;
  1811 		$this->last_query = $query;
  1645 
  1812 
  1646 		$this->_do_query( $query );
  1813 		$this->_do_query( $query );
  1647 
  1814 
  1648 		// MySQL server has gone away, try to reconnect
  1815 		// MySQL server has gone away, try to reconnect.
  1649 		$mysql_errno = 0;
  1816 		$mysql_errno = 0;
  1650 		if ( ! empty( $this->dbh ) ) {
  1817 		if ( ! empty( $this->dbh ) ) {
  1651 			if ( $this->use_mysqli ) {
  1818 			if ( $this->use_mysqli ) {
  1652 				$mysql_errno = mysqli_errno( $this->dbh );
  1819 				if ( $this->dbh instanceof mysqli ) {
       
  1820 					$mysql_errno = mysqli_errno( $this->dbh );
       
  1821 				} else {
       
  1822 					// $dbh is defined, but isn't a real connection.
       
  1823 					// Something has gone horribly wrong, let's try a reconnect.
       
  1824 					$mysql_errno = 2006;
       
  1825 				}
  1653 			} else {
  1826 			} else {
  1654 				$mysql_errno = mysql_errno( $this->dbh );
  1827 				if ( is_resource( $this->dbh ) ) {
       
  1828 					$mysql_errno = mysql_errno( $this->dbh );
       
  1829 				} else {
       
  1830 					$mysql_errno = 2006;
       
  1831 				}
  1655 			}
  1832 			}
  1656 		}
  1833 		}
  1657 
  1834 
  1658 		if ( empty( $this->dbh ) || 2006 == $mysql_errno ) {
  1835 		if ( empty( $this->dbh ) || 2006 == $mysql_errno ) {
  1659 			if ( $this->check_connection() ) {
  1836 			if ( $this->check_connection() ) {
  1662 				$this->insert_id = 0;
  1839 				$this->insert_id = 0;
  1663 				return false;
  1840 				return false;
  1664 			}
  1841 			}
  1665 		}
  1842 		}
  1666 
  1843 
  1667 		// If there is an error then take note of it..
  1844 		// If there is an error then take note of it.
  1668 		if ( $this->use_mysqli ) {
  1845 		if ( $this->use_mysqli ) {
  1669 			$this->last_error = mysqli_error( $this->dbh );
  1846 			if ( $this->dbh instanceof mysqli ) {
       
  1847 				$this->last_error = mysqli_error( $this->dbh );
       
  1848 			} else {
       
  1849 				$this->last_error = __( 'Unable to retrieve the error message from MySQL' );
       
  1850 			}
  1670 		} else {
  1851 		} else {
  1671 			$this->last_error = mysql_error( $this->dbh );
  1852 			if ( is_resource( $this->dbh ) ) {
       
  1853 				$this->last_error = mysql_error( $this->dbh );
       
  1854 			} else {
       
  1855 				$this->last_error = __( 'Unable to retrieve the error message from MySQL' );
       
  1856 			}
  1672 		}
  1857 		}
  1673 
  1858 
  1674 		if ( $this->last_error ) {
  1859 		if ( $this->last_error ) {
  1675 			// Clear insert_id on a subsequent failed insert.
  1860 			// Clear insert_id on a subsequent failed insert.
  1676 			if ( $this->insert_id && preg_match( '/^\s*(insert|replace)\s/i', $query ) )
  1861 			if ( $this->insert_id && preg_match( '/^\s*(insert|replace)\s/i', $query ) )
  1699 			// Return number of rows affected
  1884 			// Return number of rows affected
  1700 			$return_val = $this->rows_affected;
  1885 			$return_val = $this->rows_affected;
  1701 		} else {
  1886 		} else {
  1702 			$num_rows = 0;
  1887 			$num_rows = 0;
  1703 			if ( $this->use_mysqli && $this->result instanceof mysqli_result ) {
  1888 			if ( $this->use_mysqli && $this->result instanceof mysqli_result ) {
  1704 				while ( $row = @mysqli_fetch_object( $this->result ) ) {
  1889 				while ( $row = mysqli_fetch_object( $this->result ) ) {
  1705 					$this->last_result[$num_rows] = $row;
  1890 					$this->last_result[$num_rows] = $row;
  1706 					$num_rows++;
  1891 					$num_rows++;
  1707 				}
  1892 				}
  1708 			} elseif ( is_resource( $this->result ) ) {
  1893 			} elseif ( is_resource( $this->result ) ) {
  1709 				while ( $row = @mysql_fetch_object( $this->result ) ) {
  1894 				while ( $row = mysql_fetch_object( $this->result ) ) {
  1710 					$this->last_result[$num_rows] = $row;
  1895 					$this->last_result[$num_rows] = $row;
  1711 					$num_rows++;
  1896 					$num_rows++;
  1712 				}
  1897 				}
  1713 			}
  1898 			}
  1714 
  1899 
  1724 	/**
  1909 	/**
  1725 	 * Internal function to perform the mysql_query() call.
  1910 	 * Internal function to perform the mysql_query() call.
  1726 	 *
  1911 	 *
  1727 	 * @since 3.9.0
  1912 	 * @since 3.9.0
  1728 	 *
  1913 	 *
  1729 	 * @access private
       
  1730 	 * @see wpdb::query()
  1914 	 * @see wpdb::query()
  1731 	 *
  1915 	 *
  1732 	 * @param string $query The query to run.
  1916 	 * @param string $query The query to run.
  1733 	 */
  1917 	 */
  1734 	private function _do_query( $query ) {
  1918 	private function _do_query( $query ) {
  1735 		if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
  1919 		if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
  1736 			$this->timer_start();
  1920 			$this->timer_start();
  1737 		}
  1921 		}
  1738 
  1922 
  1739 		if ( $this->use_mysqli ) {
  1923 		if ( ! empty( $this->dbh ) && $this->use_mysqli ) {
  1740 			$this->result = @mysqli_query( $this->dbh, $query );
  1924 			$this->result = mysqli_query( $this->dbh, $query );
  1741 		} else {
  1925 		} elseif ( ! empty( $this->dbh ) ) {
  1742 			$this->result = @mysql_query( $query, $this->dbh );
  1926 			$this->result = mysql_query( $query, $this->dbh );
  1743 		}
  1927 		}
  1744 		$this->num_queries++;
  1928 		$this->num_queries++;
  1745 
  1929 
  1746 		if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
  1930 		if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
  1747 			$this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
  1931 			$this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
  1748 		}
  1932 		}
       
  1933 	}
       
  1934 
       
  1935 	/**
       
  1936 	 * Generates and returns a placeholder escape string for use in queries returned by ::prepare().
       
  1937 	 *
       
  1938 	 * @since 4.8.3
       
  1939 	 *
       
  1940 	 * @return string String to escape placeholders.
       
  1941 	 */
       
  1942 	public function placeholder_escape() {
       
  1943 		static $placeholder;
       
  1944 
       
  1945 		if ( ! $placeholder ) {
       
  1946 			// If ext/hash is not present, compat.php's hash_hmac() does not support sha256.
       
  1947 			$algo = function_exists( 'hash' ) ? 'sha256' : 'sha1';
       
  1948 			// Old WP installs may not have AUTH_SALT defined.
       
  1949 			$salt = defined( 'AUTH_SALT' ) && AUTH_SALT ? AUTH_SALT : (string) rand();
       
  1950 
       
  1951 			$placeholder = '{' . hash_hmac( $algo, uniqid( $salt, true ), $salt ) . '}';
       
  1952 		}
       
  1953 
       
  1954 		/*
       
  1955 		 * Add the filter to remove the placeholder escaper. Uses priority 0, so that anything
       
  1956 		 * else attached to this filter will recieve the query with the placeholder string removed.
       
  1957 		 */
       
  1958 		if ( ! has_filter( 'query', array( $this, 'remove_placeholder_escape' ) ) ) {
       
  1959 			add_filter( 'query', array( $this, 'remove_placeholder_escape' ), 0 );
       
  1960 		}
       
  1961 
       
  1962 		return $placeholder;
       
  1963 	}
       
  1964 
       
  1965 	/**
       
  1966 	 * Adds a placeholder escape string, to escape anything that resembles a printf() placeholder.
       
  1967 	 *
       
  1968 	 * @since 4.8.3
       
  1969 	 *
       
  1970 	 * @param string $query The query to escape.
       
  1971 	 * @return string The query with the placeholder escape string inserted where necessary.
       
  1972 	 */
       
  1973 	public function add_placeholder_escape( $query ) {
       
  1974 		/*
       
  1975 		 * To prevent returning anything that even vaguely resembles a placeholder,
       
  1976 		 * we clobber every % we can find.
       
  1977 		 */
       
  1978 		return str_replace( '%', $this->placeholder_escape(), $query );
       
  1979 	}
       
  1980 
       
  1981 	/**
       
  1982 	 * Removes the placeholder escape strings from a query.
       
  1983 	 *
       
  1984 	 * @since 4.8.3
       
  1985 	 *
       
  1986 	 * @param string $query The query from which the placeholder will be removed.
       
  1987 	 * @return string The query with the placeholder removed.
       
  1988 	 */
       
  1989 	public function remove_placeholder_escape( $query ) {
       
  1990 		return str_replace( $this->placeholder_escape(), '%', $query );
  1749 	}
  1991 	}
  1750 
  1992 
  1751 	/**
  1993 	/**
  1752 	 * Insert a row into a table.
  1994 	 * Insert a row into a table.
  1753 	 *
  1995 	 *
  1757 	 * @since 2.5.0
  1999 	 * @since 2.5.0
  1758 	 * @see wpdb::prepare()
  2000 	 * @see wpdb::prepare()
  1759 	 * @see wpdb::$field_types
  2001 	 * @see wpdb::$field_types
  1760 	 * @see wp_set_wpdb_vars()
  2002 	 * @see wp_set_wpdb_vars()
  1761 	 *
  2003 	 *
  1762 	 * @param string $table table name
  2004 	 * @param string       $table  Table name
  1763 	 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
  2005 	 * @param array        $data   Data to insert (in column => value pairs).
  1764 	 * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data. If string, that format will be used for all of the values in $data.
  2006 	 *                             Both $data columns and $data values should be "raw" (neither should be SQL escaped).
  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.
  2007 	 *                             Sending a null value will cause the column to be set to NULL - the corresponding format is ignored in this case.
       
  2008 	 * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data.
       
  2009 	 *                             If string, that format will be used for all of the values in $data.
       
  2010 	 *                             A format is one of '%d', '%f', '%s' (integer, float, string).
       
  2011 	 *                             If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types.
  1766 	 * @return int|false The number of rows inserted, or false on error.
  2012 	 * @return int|false The number of rows inserted, or false on error.
  1767 	 */
  2013 	 */
  1768 	public function insert( $table, $data, $format = null ) {
  2014 	public function insert( $table, $data, $format = null ) {
  1769 		return $this->_insert_replace_helper( $table, $data, $format, 'INSERT' );
  2015 		return $this->_insert_replace_helper( $table, $data, $format, 'INSERT' );
  1770 	}
  2016 	}
  1778 	 * @since 3.0.0
  2024 	 * @since 3.0.0
  1779 	 * @see wpdb::prepare()
  2025 	 * @see wpdb::prepare()
  1780 	 * @see wpdb::$field_types
  2026 	 * @see wpdb::$field_types
  1781 	 * @see wp_set_wpdb_vars()
  2027 	 * @see wp_set_wpdb_vars()
  1782 	 *
  2028 	 *
  1783 	 * @param string $table table name
  2029 	 * @param string       $table  Table name
  1784 	 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
  2030 	 * @param array        $data   Data to insert (in column => value pairs).
  1785 	 * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data. If string, that format will be used for all of the values in $data.
  2031 	 *                             Both $data columns and $data values should be "raw" (neither should be SQL escaped).
  1786 	 * 	A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types.
  2032 	 *                             Sending a null value will cause the column to be set to NULL - the corresponding format is ignored in this case.
       
  2033 	 * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data.
       
  2034 	 *                             If string, that format will be used for all of the values in $data.
       
  2035 	 *                             A format is one of '%d', '%f', '%s' (integer, float, string).
       
  2036 	 *                             If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types.
  1787 	 * @return int|false The number of rows affected, or false on error.
  2037 	 * @return int|false The number of rows affected, or false on error.
  1788 	 */
  2038 	 */
  1789 	public function replace( $table, $data, $format = null ) {
  2039 	public function replace( $table, $data, $format = null ) {
  1790 		return $this->_insert_replace_helper( $table, $data, $format, 'REPLACE' );
  2040 		return $this->_insert_replace_helper( $table, $data, $format, 'REPLACE' );
  1791 	}
  2041 	}
  1793 	/**
  2043 	/**
  1794 	 * Helper function for insert and replace.
  2044 	 * Helper function for insert and replace.
  1795 	 *
  2045 	 *
  1796 	 * Runs an insert or replace query based on $type argument.
  2046 	 * Runs an insert or replace query based on $type argument.
  1797 	 *
  2047 	 *
  1798 	 * @access private
       
  1799 	 * @since 3.0.0
  2048 	 * @since 3.0.0
  1800 	 * @see wpdb::prepare()
  2049 	 * @see wpdb::prepare()
  1801 	 * @see wpdb::$field_types
  2050 	 * @see wpdb::$field_types
  1802 	 * @see wp_set_wpdb_vars()
  2051 	 * @see wp_set_wpdb_vars()
  1803 	 *
  2052 	 *
  1804 	 * @param string $table table name
  2053 	 * @param string       $table  Table name
  1805 	 * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
  2054 	 * @param array        $data   Data to insert (in column => value pairs).
  1806 	 * @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.
  2055 	 *                             Both $data columns and $data values should be "raw" (neither should be SQL escaped).
  1807 	 * 	A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types.
  2056 	 *                             Sending a null value will cause the column to be set to NULL - the corresponding format is ignored in this case.
  1808 	 * @param string $type Optional. What type of operation is this? INSERT or REPLACE. Defaults to INSERT.
  2057 	 * @param array|string $format Optional. An array of formats to be mapped to each of the value in $data.
       
  2058 	 *                             If string, that format will be used for all of the values in $data.
       
  2059 	 *                             A format is one of '%d', '%f', '%s' (integer, float, string).
       
  2060 	 *                             If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types.
       
  2061 	 * @param string $type         Optional. What type of operation is this? INSERT or REPLACE. Defaults to INSERT.
  1809 	 * @return int|false The number of rows affected, or false on error.
  2062 	 * @return int|false The number of rows affected, or false on error.
  1810 	 */
  2063 	 */
  1811 	function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) {
  2064 	function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) {
  1812 		$this->insert_id = 0;
  2065 		$this->insert_id = 0;
  1813 
  2066 
  1820 			return false;
  2073 			return false;
  1821 		}
  2074 		}
  1822 
  2075 
  1823 		$formats = $values = array();
  2076 		$formats = $values = array();
  1824 		foreach ( $data as $value ) {
  2077 		foreach ( $data as $value ) {
       
  2078 			if ( is_null( $value['value'] ) ) {
       
  2079 				$formats[] = 'NULL';
       
  2080 				continue;
       
  2081 			}
       
  2082 
  1825 			$formats[] = $value['format'];
  2083 			$formats[] = $value['format'];
  1826 			$values[]  = $value['value'];
  2084 			$values[]  = $value['value'];
  1827 		}
  2085 		}
  1828 
  2086 
  1829 		$fields  = '`' . implode( '`, `', array_keys( $data ) ) . '`';
  2087 		$fields  = '`' . implode( '`, `', array_keys( $data ) ) . '`';
  1844 	 * @since 2.5.0
  2102 	 * @since 2.5.0
  1845 	 * @see wpdb::prepare()
  2103 	 * @see wpdb::prepare()
  1846 	 * @see wpdb::$field_types
  2104 	 * @see wpdb::$field_types
  1847 	 * @see wp_set_wpdb_vars()
  2105 	 * @see wp_set_wpdb_vars()
  1848 	 *
  2106 	 *
  1849 	 * @param string $table table name
  2107 	 * @param string       $table        Table name
  1850 	 * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped).
  2108 	 * @param array        $data         Data to update (in column => value pairs).
  1851 	 * @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".
  2109 	 *                                   Both $data columns and $data values should be "raw" (neither should be SQL escaped).
  1852 	 * @param array|string $format Optional. An array of formats to be mapped to each of the values in $data. If string, that format will be used for all of the values in $data.
  2110 	 *                                   Sending a null value will cause the column to be set to NULL - the corresponding
  1853 	 * 	A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types.
  2111 	 *                                   format is ignored in this case.
  1854 	 * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where. If string, that format will be used for all of the items in $where. A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $where will be treated as strings.
  2112 	 * @param array        $where        A named array of WHERE clauses (in column => value pairs).
       
  2113 	 *                                   Multiple clauses will be joined with ANDs.
       
  2114 	 *                                   Both $where columns and $where values should be "raw".
       
  2115 	 *                                   Sending a null value will create an IS NULL comparison - the corresponding format will be ignored in this case.
       
  2116 	 * @param array|string $format       Optional. An array of formats to be mapped to each of the values in $data.
       
  2117 	 *                                   If string, that format will be used for all of the values in $data.
       
  2118 	 *                                   A format is one of '%d', '%f', '%s' (integer, float, string).
       
  2119 	 *                                   If omitted, all values in $data will be treated as strings unless otherwise specified in wpdb::$field_types.
       
  2120 	 * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where.
       
  2121 	 *                                   If string, that format will be used for all of the items in $where.
       
  2122 	 *                                   A format is one of '%d', '%f', '%s' (integer, float, string).
       
  2123 	 *                                   If omitted, all values in $where will be treated as strings.
  1855 	 * @return int|false The number of rows updated, or false on error.
  2124 	 * @return int|false The number of rows updated, or false on error.
  1856 	 */
  2125 	 */
  1857 	public function update( $table, $data, $where, $format = null, $where_format = null ) {
  2126 	public function update( $table, $data, $where, $format = null, $where_format = null ) {
  1858 		if ( ! is_array( $data ) || ! is_array( $where ) ) {
  2127 		if ( ! is_array( $data ) || ! is_array( $where ) ) {
  1859 			return false;
  2128 			return false;
  1868 			return false;
  2137 			return false;
  1869 		}
  2138 		}
  1870 
  2139 
  1871 		$fields = $conditions = $values = array();
  2140 		$fields = $conditions = $values = array();
  1872 		foreach ( $data as $field => $value ) {
  2141 		foreach ( $data as $field => $value ) {
       
  2142 			if ( is_null( $value['value'] ) ) {
       
  2143 				$fields[] = "`$field` = NULL";
       
  2144 				continue;
       
  2145 			}
       
  2146 
  1873 			$fields[] = "`$field` = " . $value['format'];
  2147 			$fields[] = "`$field` = " . $value['format'];
  1874 			$values[] = $value['value'];
  2148 			$values[] = $value['value'];
  1875 		}
  2149 		}
  1876 		foreach ( $where as $field => $value ) {
  2150 		foreach ( $where as $field => $value ) {
       
  2151 			if ( is_null( $value['value'] ) ) {
       
  2152 				$conditions[] = "`$field` IS NULL";
       
  2153 				continue;
       
  2154 			}
       
  2155 
  1877 			$conditions[] = "`$field` = " . $value['format'];
  2156 			$conditions[] = "`$field` = " . $value['format'];
  1878 			$values[] = $value['value'];
  2157 			$values[] = $value['value'];
  1879 		}
  2158 		}
  1880 
  2159 
  1881 		$fields = implode( ', ', $fields );
  2160 		$fields = implode( ', ', $fields );
  1896 	 * @since 3.4.0
  2175 	 * @since 3.4.0
  1897 	 * @see wpdb::prepare()
  2176 	 * @see wpdb::prepare()
  1898 	 * @see wpdb::$field_types
  2177 	 * @see wpdb::$field_types
  1899 	 * @see wp_set_wpdb_vars()
  2178 	 * @see wp_set_wpdb_vars()
  1900 	 *
  2179 	 *
  1901 	 * @param string $table table name
  2180 	 * @param string       $table        Table name
  1902 	 * @param array $where A named array of WHERE clauses (in column => value pairs). Multiple clauses will be joined with ANDs. Both $where columns and $where values should be "raw".
  2181 	 * @param array        $where        A named array of WHERE clauses (in column => value pairs).
  1903 	 * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where. If string, that format will be used for all of the items in $where. A format is one of '%d', '%f', '%s' (integer, float, string). If omitted, all values in $where will be treated as strings unless otherwise specified in wpdb::$field_types.
  2182 	 *                                   Multiple clauses will be joined with ANDs.
       
  2183 	 *                                   Both $where columns and $where values should be "raw".
       
  2184 	 *                                   Sending a null value will create an IS NULL comparison - the corresponding format will be ignored in this case.
       
  2185 	 * @param array|string $where_format Optional. An array of formats to be mapped to each of the values in $where.
       
  2186 	 *                                   If string, that format will be used for all of the items in $where.
       
  2187 	 *                                   A format is one of '%d', '%f', '%s' (integer, float, string).
       
  2188 	 *                                   If omitted, all values in $where will be treated as strings unless otherwise specified in wpdb::$field_types.
  1904 	 * @return int|false The number of rows updated, or false on error.
  2189 	 * @return int|false The number of rows updated, or false on error.
  1905 	 */
  2190 	 */
  1906 	public function delete( $table, $where, $where_format = null ) {
  2191 	public function delete( $table, $where, $where_format = null ) {
  1907 		if ( ! is_array( $where ) ) {
  2192 		if ( ! is_array( $where ) ) {
  1908 			return false;
  2193 			return false;
  1913 			return false;
  2198 			return false;
  1914 		}
  2199 		}
  1915 
  2200 
  1916 		$conditions = $values = array();
  2201 		$conditions = $values = array();
  1917 		foreach ( $where as $field => $value ) {
  2202 		foreach ( $where as $field => $value ) {
       
  2203 			if ( is_null( $value['value'] ) ) {
       
  2204 				$conditions[] = "`$field` IS NULL";
       
  2205 				continue;
       
  2206 			}
       
  2207 
  1918 			$conditions[] = "`$field` = " . $value['format'];
  2208 			$conditions[] = "`$field` = " . $value['format'];
  1919 			$values[] = $value['value'];
  2209 			$values[] = $value['value'];
  1920 		}
  2210 		}
  1921 
  2211 
  1922 		$conditions = implode( ' AND ', $conditions );
  2212 		$conditions = implode( ' AND ', $conditions );
  1935 	 * each value with a format. Then it determines the charset of that field,
  2225 	 * each value with a format. Then it determines the charset of that field,
  1936 	 * using that to determine if any invalid text would be stripped. If text is
  2226 	 * using that to determine if any invalid text would be stripped. If text is
  1937 	 * stripped, then field processing is rejected and the query fails.
  2227 	 * stripped, then field processing is rejected and the query fails.
  1938 	 *
  2228 	 *
  1939 	 * @since 4.2.0
  2229 	 * @since 4.2.0
  1940 	 * @access protected
       
  1941 	 *
  2230 	 *
  1942 	 * @param string $table  Table name.
  2231 	 * @param string $table  Table name.
  1943 	 * @param array  $data   Field/value pair.
  2232 	 * @param array  $data   Field/value pair.
  1944 	 * @param mixed  $format Format for each field.
  2233 	 * @param mixed  $format Format for each field.
  1945 	 * @return array|bool Returns an array of fields that contain paired values
  2234 	 * @return array|false Returns an array of fields that contain paired values
  1946 	 *                    and formats. Returns false for invalid values.
  2235 	 *                    and formats. Returns false for invalid values.
  1947 	 */
  2236 	 */
  1948 	protected function process_fields( $table, $data, $format ) {
  2237 	protected function process_fields( $table, $data, $format ) {
  1949 		$data = $this->process_field_formats( $data, $format );
  2238 		$data = $this->process_field_formats( $data, $format );
  1950 		if ( false === $data ) {
  2239 		if ( false === $data ) {
  1972 
  2261 
  1973 	/**
  2262 	/**
  1974 	 * Prepares arrays of value/format pairs as passed to wpdb CRUD methods.
  2263 	 * Prepares arrays of value/format pairs as passed to wpdb CRUD methods.
  1975 	 *
  2264 	 *
  1976 	 * @since 4.2.0
  2265 	 * @since 4.2.0
  1977 	 * @access protected
       
  1978 	 *
  2266 	 *
  1979 	 * @param array $data   Array of fields to values.
  2267 	 * @param array $data   Array of fields to values.
  1980 	 * @param mixed $format Formats to be mapped to the values in $data.
  2268 	 * @param mixed $format Formats to be mapped to the values in $data.
  1981 	 * @return array Array, keyed by field names with values being an array
  2269 	 * @return array Array, keyed by field names with values being an array
  1982 	 *               of 'value' and 'format' keys.
  2270 	 *               of 'value' and 'format' keys.
  2008 	/**
  2296 	/**
  2009 	 * Adds field charsets to field/value/format arrays generated by
  2297 	 * Adds field charsets to field/value/format arrays generated by
  2010 	 * the wpdb::process_field_formats() method.
  2298 	 * the wpdb::process_field_formats() method.
  2011 	 *
  2299 	 *
  2012 	 * @since 4.2.0
  2300 	 * @since 4.2.0
  2013 	 * @access protected
       
  2014 	 *
  2301 	 *
  2015 	 * @param array  $data  As it comes from the wpdb::process_field_formats() method.
  2302 	 * @param array  $data  As it comes from the wpdb::process_field_formats() method.
  2016 	 * @param string $table Table name.
  2303 	 * @param string $table Table name.
  2017 	 * @return The same array as $data with additional 'charset' keys.
  2304 	 * @return array|false The same array as $data with additional 'charset' keys.
  2018 	 */
  2305 	 */
  2019 	protected function process_field_charsets( $data, $table ) {
  2306 	protected function process_field_charsets( $data, $table ) {
  2020 		foreach ( $data as $field => $value ) {
  2307 		foreach ( $data as $field => $value ) {
  2021 			if ( '%d' === $value['format'] || '%f' === $value['format'] ) {
  2308 			if ( '%d' === $value['format'] || '%f' === $value['format'] ) {
  2022 				// We can skip this field if we know it isn't a string.
  2309 				/*
  2023 				// This checks %d/%f versus ! %s because it's sprintf() could take more.
  2310 				 * We can skip this field if we know it isn't a string.
       
  2311 				 * This checks %d/%f versus ! %s because its sprintf() could take more.
       
  2312 				 */
  2024 				$value['charset'] = false;
  2313 				$value['charset'] = false;
  2025 			} else {
  2314 			} else {
  2026 				$value['charset'] = $this->get_col_charset( $table, $field );
  2315 				$value['charset'] = $this->get_col_charset( $table, $field );
  2027 				if ( is_wp_error( $value['charset'] ) ) {
  2316 				if ( is_wp_error( $value['charset'] ) ) {
  2028 					return false;
  2317 					return false;
  2037 
  2326 
  2038 	/**
  2327 	/**
  2039 	 * For string fields, record the maximum string length that field can safely save.
  2328 	 * For string fields, record the maximum string length that field can safely save.
  2040 	 *
  2329 	 *
  2041 	 * @since 4.2.1
  2330 	 * @since 4.2.1
  2042 	 * @access protected
       
  2043 	 *
  2331 	 *
  2044 	 * @param array  $data  As it comes from the wpdb::process_field_charsets() method.
  2332 	 * @param array  $data  As it comes from the wpdb::process_field_charsets() method.
  2045 	 * @param string $table Table name.
  2333 	 * @param string $table Table name.
  2046 	 * @return array|False The same array as $data with additional 'length' keys, or false if
  2334 	 * @return array|false The same array as $data with additional 'length' keys, or false if
  2047 	 *                     any of the values were too long for their corresponding field.
  2335 	 *                     any of the values were too long for their corresponding field.
  2048 	 */
  2336 	 */
  2049 	protected function process_field_lengths( $data, $table ) {
  2337 	protected function process_field_lengths( $data, $table ) {
  2050 		foreach ( $data as $field => $value ) {
  2338 		foreach ( $data as $field => $value ) {
  2051 			if ( '%d' === $value['format'] || '%f' === $value['format'] ) {
  2339 			if ( '%d' === $value['format'] || '%f' === $value['format'] ) {
  2052 				// We can skip this field if we know it isn't a string.
  2340 				/*
  2053 				// This checks %d/%f versus ! %s because it's sprintf() could take more.
  2341 				 * We can skip this field if we know it isn't a string.
       
  2342 				 * This checks %d/%f versus ! %s because its sprintf() could take more.
       
  2343 				 */
  2054 				$value['length'] = false;
  2344 				$value['length'] = false;
  2055 			} else {
  2345 			} else {
  2056 				$value['length'] = $this->get_col_length( $table, $field );
  2346 				$value['length'] = $this->get_col_length( $table, $field );
  2057 				if ( is_wp_error( $value['length'] ) ) {
  2347 				if ( is_wp_error( $value['length'] ) ) {
  2058 					return false;
  2348 					return false;
  2073 	 * If $query is null, this function returns the value in the specified column and row from the previous SQL result.
  2363 	 * If $query is null, this function returns the value in the specified column and row from the previous SQL result.
  2074 	 *
  2364 	 *
  2075 	 * @since 0.71
  2365 	 * @since 0.71
  2076 	 *
  2366 	 *
  2077 	 * @param string|null $query Optional. SQL query. Defaults to null, use the result from the previous query.
  2367 	 * @param string|null $query Optional. SQL query. Defaults to null, use the result from the previous query.
  2078 	 * @param int $x Optional. Column of value to return. Indexed from 0.
  2368 	 * @param int         $x     Optional. Column of value to return. Indexed from 0.
  2079 	 * @param int $y Optional. Row of value to return. Indexed from 0.
  2369 	 * @param int         $y     Optional. Row of value to return. Indexed from 0.
  2080 	 * @return string|null Database query result (as string), or null on failure
  2370 	 * @return string|null Database query result (as string), or null on failure
  2081 	 */
  2371 	 */
  2082 	public function get_var( $query = null, $x = 0, $y = 0 ) {
  2372 	public function get_var( $query = null, $x = 0, $y = 0 ) {
  2083 		$this->func_call = "\$db->get_var(\"$query\", $x, $y)";
  2373 		$this->func_call = "\$db->get_var(\"$query\", $x, $y)";
  2084 
  2374 
  2085 		if ( $this->check_safe_collation( $query ) ) {
  2375 		if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
  2086 			$this->check_current_query = false;
  2376 			$this->check_current_query = false;
  2087 		}
  2377 		}
  2088 
  2378 
  2089 		if ( $query ) {
  2379 		if ( $query ) {
  2090 			$this->query( $query );
  2380 			$this->query( $query );
  2104 	 *
  2394 	 *
  2105 	 * Executes a SQL query and returns the row from the SQL result.
  2395 	 * Executes a SQL query and returns the row from the SQL result.
  2106 	 *
  2396 	 *
  2107 	 * @since 0.71
  2397 	 * @since 0.71
  2108 	 *
  2398 	 *
  2109 	 * @param string|null $query SQL query.
  2399 	 * @param string|null $query  SQL query.
  2110 	 * @param string $output Optional. one of ARRAY_A | ARRAY_N | OBJECT constants. Return an associative array (column => value, ...),
  2400 	 * @param string      $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
  2111 	 * 	a numerically indexed array (0 => value, ...) or an object ( ->column = value ), respectively.
  2401 	 *                            an stdClass object, an associative array, or a numeric array, respectively. Default OBJECT.
  2112 	 * @param int $y Optional. Row to return. Indexed from 0.
  2402 	 * @param int         $y      Optional. Row to return. Indexed from 0.
  2113 	 * @return mixed Database query result in format specified by $output or null on failure
  2403 	 * @return array|object|null|void Database query result in format specified by $output or null on failure
  2114 	 */
  2404 	 */
  2115 	public function get_row( $query = null, $output = OBJECT, $y = 0 ) {
  2405 	public function get_row( $query = null, $output = OBJECT, $y = 0 ) {
  2116 		$this->func_call = "\$db->get_row(\"$query\",$output,$y)";
  2406 		$this->func_call = "\$db->get_row(\"$query\",$output,$y)";
  2117 
  2407 
  2118 		if ( $this->check_safe_collation( $query ) ) {
  2408 		if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
  2119 			$this->check_current_query = false;
  2409 			$this->check_current_query = false;
  2120 		}
  2410 		}
  2121 
  2411 
  2122 		if ( $query ) {
  2412 		if ( $query ) {
  2123 			$this->query( $query );
  2413 			$this->query( $query );
  2150 	 * If $query is null, this function returns the specified column from the previous SQL result.
  2440 	 * If $query is null, this function returns the specified column from the previous SQL result.
  2151 	 *
  2441 	 *
  2152 	 * @since 0.71
  2442 	 * @since 0.71
  2153 	 *
  2443 	 *
  2154 	 * @param string|null $query Optional. SQL query. Defaults to previous query.
  2444 	 * @param string|null $query Optional. SQL query. Defaults to previous query.
  2155 	 * @param int $x Optional. Column to return. Indexed from 0.
  2445 	 * @param int         $x     Optional. Column to return. Indexed from 0.
  2156 	 * @return array Database query result. Array indexed from 0 by SQL result row number.
  2446 	 * @return array Database query result. Array indexed from 0 by SQL result row number.
  2157 	 */
  2447 	 */
  2158 	public function get_col( $query = null , $x = 0 ) {
  2448 	public function get_col( $query = null , $x = 0 ) {
  2159 		if ( $this->check_safe_collation( $query ) ) {
  2449 		if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
  2160 			$this->check_current_query = false;
  2450 			$this->check_current_query = false;
  2161 		}
  2451 		}
  2162 
  2452 
  2163 		if ( $query ) {
  2453 		if ( $query ) {
  2164 			$this->query( $query );
  2454 			$this->query( $query );
  2177 	 *
  2467 	 *
  2178 	 * Executes a SQL query and returns the entire SQL result.
  2468 	 * Executes a SQL query and returns the entire SQL result.
  2179 	 *
  2469 	 *
  2180 	 * @since 0.71
  2470 	 * @since 0.71
  2181 	 *
  2471 	 *
  2182 	 * @param string $query SQL query.
  2472 	 * @param string $query  SQL query.
  2183 	 * @param string $output Optional. Any of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants. With one of the first three, return an array of rows indexed from 0 by SQL result row number.
  2473 	 * @param string $output Optional. Any of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants.
  2184 	 * 	Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively.
  2474 	 *                       With one of the first three, return an array of rows indexed from 0 by SQL result row number.
  2185 	 * 	With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value. Duplicate keys are discarded.
  2475 	 *                       Each row is an associative array (column => value, ...), a numerically indexed array (0 => value, ...), or an object. ( ->column = value ), respectively.
  2186 	 * @return mixed Database query results
  2476 	 *                       With OBJECT_K, return an associative array of row objects keyed by the value of each row's first column's value.
       
  2477 	 *                       Duplicate keys are discarded.
       
  2478 	 * @return array|object|null Database query results
  2187 	 */
  2479 	 */
  2188 	public function get_results( $query = null, $output = OBJECT ) {
  2480 	public function get_results( $query = null, $output = OBJECT ) {
  2189 		$this->func_call = "\$db->get_results(\"$query\", $output)";
  2481 		$this->func_call = "\$db->get_results(\"$query\", $output)";
  2190 
  2482 
  2191 		if ( $this->check_safe_collation( $query ) ) {
  2483 		if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
  2192 			$this->check_current_query = false;
  2484 			$this->check_current_query = false;
  2193 		}
  2485 		}
  2194 
  2486 
  2195 		if ( $query ) {
  2487 		if ( $query ) {
  2196 			$this->query( $query );
  2488 			$this->query( $query );
  2213 			}
  2505 			}
  2214 			return $new_array;
  2506 			return $new_array;
  2215 		} elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
  2507 		} elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
  2216 			// Return an integer-keyed array of...
  2508 			// Return an integer-keyed array of...
  2217 			if ( $this->last_result ) {
  2509 			if ( $this->last_result ) {
  2218 				foreach( (array) $this->last_result as $row ) {
  2510 				foreach ( (array) $this->last_result as $row ) {
  2219 					if ( $output == ARRAY_N ) {
  2511 					if ( $output == ARRAY_N ) {
  2220 						// ...integer-keyed row arrays
  2512 						// ...integer-keyed row arrays
  2221 						$new_array[] = array_values( get_object_vars( $row ) );
  2513 						$new_array[] = array_values( get_object_vars( $row ) );
  2222 					} else {
  2514 					} else {
  2223 						// ...column name-keyed row arrays
  2515 						// ...column name-keyed row arrays
  2235 
  2527 
  2236 	/**
  2528 	/**
  2237 	 * Retrieves the character set for the given table.
  2529 	 * Retrieves the character set for the given table.
  2238 	 *
  2530 	 *
  2239 	 * @since 4.2.0
  2531 	 * @since 4.2.0
  2240 	 * @access protected
       
  2241 	 *
  2532 	 *
  2242 	 * @param string $table Table name.
  2533 	 * @param string $table Table name.
  2243 	 * @return string|WP_Error Table character set, WP_Error object if it couldn't be found.
  2534 	 * @return string|WP_Error Table character set, WP_Error object if it couldn't be found.
  2244 	 */
  2535 	 */
  2245 	protected function get_table_charset( $table ) {
  2536 	protected function get_table_charset( $table ) {
  2246 		$tablekey = strtolower( $table );
  2537 		$tablekey = strtolower( $table );
  2247 
  2538 
  2248 		/**
  2539 		/**
  2249 		 * Filter the table charset value before the DB is checked.
  2540 		 * Filters the table charset value before the DB is checked.
  2250 		 *
  2541 		 *
  2251 		 * Passing a non-null value to the filter will effectively short-circuit
  2542 		 * Passing a non-null value to the filter will effectively short-circuit
  2252 		 * checking the DB for the charset, returning that value instead.
  2543 		 * checking the DB for the charset, returning that value instead.
  2253 		 *
  2544 		 *
  2254 		 * @since 4.2.0
  2545 		 * @since 4.2.0
  2336 
  2627 
  2337 	/**
  2628 	/**
  2338 	 * Retrieves the character set for the given column.
  2629 	 * Retrieves the character set for the given column.
  2339 	 *
  2630 	 *
  2340 	 * @since 4.2.0
  2631 	 * @since 4.2.0
  2341 	 * @access public
       
  2342 	 *
  2632 	 *
  2343 	 * @param string $table  Table name.
  2633 	 * @param string $table  Table name.
  2344 	 * @param string $column Column name.
  2634 	 * @param string $column Column name.
  2345 	 * @return mixed Column character set as a string. False if the column has no
  2635 	 * @return string|false|WP_Error Column character set as a string. False if the column has no
  2346 	 *               character set. WP_Error object if there was an error.
  2636 	 *                               character set. WP_Error object if there was an error.
  2347 	 */
  2637 	 */
  2348 	public function get_col_charset( $table, $column ) {
  2638 	public function get_col_charset( $table, $column ) {
  2349 		$tablekey = strtolower( $table );
  2639 		$tablekey = strtolower( $table );
  2350 		$columnkey = strtolower( $column );
  2640 		$columnkey = strtolower( $column );
  2351 
  2641 
  2352 		/**
  2642 		/**
  2353 		 * Filter the column charset value before the DB is checked.
  2643 		 * Filters the column charset value before the DB is checked.
  2354 		 *
  2644 		 *
  2355 		 * Passing a non-null value to the filter will short-circuit
  2645 		 * Passing a non-null value to the filter will short-circuit
  2356 		 * checking the DB for the charset, returning that value instead.
  2646 		 * checking the DB for the charset, returning that value instead.
  2357 		 *
  2647 		 *
  2358 		 * @since 4.2.0
  2648 		 * @since 4.2.0
  2365 		if ( null !== $charset ) {
  2655 		if ( null !== $charset ) {
  2366 			return $charset;
  2656 			return $charset;
  2367 		}
  2657 		}
  2368 
  2658 
  2369 		// Skip this entirely if this isn't a MySQL database.
  2659 		// Skip this entirely if this isn't a MySQL database.
  2370 		if ( false === $this->is_mysql ) {
  2660 		if ( empty( $this->is_mysql ) ) {
  2371 			return false;
  2661 			return false;
  2372 		}
  2662 		}
  2373 
  2663 
  2374 		if ( empty( $this->table_charset[ $tablekey ] ) ) {
  2664 		if ( empty( $this->table_charset[ $tablekey ] ) ) {
  2375 			// This primes column information for us.
  2665 			// This primes column information for us.
  2401 	/**
  2691 	/**
  2402 	 * Retrieve the maximum string length allowed in a given column.
  2692 	 * Retrieve the maximum string length allowed in a given column.
  2403 	 * The length may either be specified as a byte length or a character length.
  2693 	 * The length may either be specified as a byte length or a character length.
  2404 	 *
  2694 	 *
  2405 	 * @since 4.2.1
  2695 	 * @since 4.2.1
  2406 	 * @access public
       
  2407 	 *
  2696 	 *
  2408 	 * @param string $table  Table name.
  2697 	 * @param string $table  Table name.
  2409 	 * @param string $column Column name.
  2698 	 * @param string $column Column name.
  2410 	 * @return mixed array( 'length' => (int), 'type' => 'byte' | 'char' )
  2699 	 * @return array|false|WP_Error array( 'length' => (int), 'type' => 'byte' | 'char' )
  2411 	 *               false if the column has no length (for example, numeric column)
  2700 	 *                              false if the column has no length (for example, numeric column)
  2412 	 *               WP_Error object if there was an error.
  2701 	 *                              WP_Error object if there was an error.
  2413 	 */
  2702 	 */
  2414 	public function get_col_length( $table, $column ) {
  2703 	public function get_col_length( $table, $column ) {
  2415 		$tablekey = strtolower( $table );
  2704 		$tablekey = strtolower( $table );
  2416 		$columnkey = strtolower( $column );
  2705 		$columnkey = strtolower( $column );
  2417 
  2706 
  2418 		// Skip this entirely if this isn't a MySQL database.
  2707 		// Skip this entirely if this isn't a MySQL database.
  2419 		if ( false === $this->is_mysql ) {
  2708 		if ( empty( $this->is_mysql ) ) {
  2420 			return false;
  2709 			return false;
  2421 		}
  2710 		}
  2422 
  2711 
  2423 		if ( empty( $this->col_meta[ $tablekey ] ) ) {
  2712 		if ( empty( $this->col_meta[ $tablekey ] ) ) {
  2424 			// This primes column information for us.
  2713 			// This primes column information for us.
  2446 			case 'varchar':
  2735 			case 'varchar':
  2447 				return array(
  2736 				return array(
  2448 					'type'   => 'char',
  2737 					'type'   => 'char',
  2449 					'length' => (int) $length,
  2738 					'length' => (int) $length,
  2450 				);
  2739 				);
  2451 				break;
  2740 
  2452 			case 'binary':
  2741 			case 'binary':
  2453 			case 'varbinary':
  2742 			case 'varbinary':
  2454 				return array(
  2743 				return array(
  2455 					'type'   => 'byte',
  2744 					'type'   => 'byte',
  2456 					'length' => (int) $length,
  2745 					'length' => (int) $length,
  2457 				);
  2746 				);
  2458 				break;
  2747 
  2459 			case 'tinyblob':
  2748 			case 'tinyblob':
  2460 			case 'tinytext':
  2749 			case 'tinytext':
  2461 				return array(
  2750 				return array(
  2462 					'type'   => 'byte',
  2751 					'type'   => 'byte',
  2463 					'length' => 255,        // 2^8 - 1
  2752 					'length' => 255,        // 2^8 - 1
  2464 				);
  2753 				);
  2465 				break;
  2754 
  2466 			case 'blob':
  2755 			case 'blob':
  2467 			case 'text':
  2756 			case 'text':
  2468 				return array(
  2757 				return array(
  2469 					'type'   => 'byte',
  2758 					'type'   => 'byte',
  2470 					'length' => 65535,      // 2^16 - 1
  2759 					'length' => 65535,      // 2^16 - 1
  2471 				);
  2760 				);
  2472 				break;
  2761 
  2473 			case 'mediumblob':
  2762 			case 'mediumblob':
  2474 			case 'mediumtext':
  2763 			case 'mediumtext':
  2475 				return array(
  2764 				return array(
  2476 					'type'   => 'byte',
  2765 					'type'   => 'byte',
  2477 					'length' => 16777215,   // 2^24 - 1
  2766 					'length' => 16777215,   // 2^24 - 1
  2478 				);
  2767 				);
  2479 				break;
  2768 
  2480 			case 'longblob':
  2769 			case 'longblob':
  2481 			case 'longtext':
  2770 			case 'longtext':
  2482 				return array(
  2771 				return array(
  2483 					'type'   => 'byte',
  2772 					'type'   => 'byte',
  2484 					'length' => 4294967295, // 2^32 - 1
  2773 					'length' => 4294967295, // 2^32 - 1
  2485 				);
  2774 				);
  2486 				break;
  2775 
  2487 			default:
  2776 			default:
  2488 				return false;
  2777 				return false;
  2489 		}
  2778 		}
  2490 
       
  2491 		return false;
       
  2492 	}
  2779 	}
  2493 
  2780 
  2494 	/**
  2781 	/**
  2495 	 * Check if a string is ASCII.
  2782 	 * Check if a string is ASCII.
  2496 	 *
  2783 	 *
  2497 	 * The negative regex is faster for non-ASCII strings, as it allows
  2784 	 * The negative regex is faster for non-ASCII strings, as it allows
  2498 	 * the search to finish as soon as it encounters a non-ASCII character.
  2785 	 * the search to finish as soon as it encounters a non-ASCII character.
  2499 	 *
  2786 	 *
  2500 	 * @since 4.2.0
  2787 	 * @since 4.2.0
  2501 	 * @access protected
       
  2502 	 *
  2788 	 *
  2503 	 * @param string $string String to check.
  2789 	 * @param string $string String to check.
  2504 	 * @return bool True if ASCII, false if not.
  2790 	 * @return bool True if ASCII, false if not.
  2505 	 */
  2791 	 */
  2506 	protected function check_ascii( $string ) {
  2792 	protected function check_ascii( $string ) {
  2517 
  2803 
  2518 	/**
  2804 	/**
  2519 	 * Check if the query is accessing a collation considered safe on the current version of MySQL.
  2805 	 * Check if the query is accessing a collation considered safe on the current version of MySQL.
  2520 	 *
  2806 	 *
  2521 	 * @since 4.2.0
  2807 	 * @since 4.2.0
  2522 	 * @access protected
       
  2523 	 *
  2808 	 *
  2524 	 * @param string $query The query to check.
  2809 	 * @param string $query The query to check.
  2525 	 * @return bool True if the collation is safe, false if it isn't.
  2810 	 * @return bool True if the collation is safe, false if it isn't.
  2526 	 */
  2811 	 */
  2527 	protected function check_safe_collation( $query ) {
  2812 	protected function check_safe_collation( $query ) {
  2558 		if ( empty( $this->col_meta[ $table ] ) ) {
  2843 		if ( empty( $this->col_meta[ $table ] ) ) {
  2559 			return false;
  2844 			return false;
  2560 		}
  2845 		}
  2561 
  2846 
  2562 		// If any of the columns don't have one of these collations, it needs more sanity checking.
  2847 		// If any of the columns don't have one of these collations, it needs more sanity checking.
  2563 		foreach( $this->col_meta[ $table ] as $col ) {
  2848 		foreach ( $this->col_meta[ $table ] as $col ) {
  2564 			if ( empty( $col->Collation ) ) {
  2849 			if ( empty( $col->Collation ) ) {
  2565 				continue;
  2850 				continue;
  2566 			}
  2851 			}
  2567 
  2852 
  2568 			if ( ! in_array( $col->Collation, array( 'utf8_general_ci', 'utf8_bin', 'utf8mb4_general_ci', 'utf8mb4_bin' ), true ) ) {
  2853 			if ( ! in_array( $col->Collation, array( 'utf8_general_ci', 'utf8_bin', 'utf8mb4_general_ci', 'utf8mb4_bin' ), true ) ) {
  2575 
  2860 
  2576 	/**
  2861 	/**
  2577 	 * Strips any invalid characters based on value/charset pairs.
  2862 	 * Strips any invalid characters based on value/charset pairs.
  2578 	 *
  2863 	 *
  2579 	 * @since 4.2.0
  2864 	 * @since 4.2.0
  2580 	 * @access protected
       
  2581 	 *
  2865 	 *
  2582 	 * @param array $data Array of value arrays. Each value array has the keys
  2866 	 * @param array $data Array of value arrays. Each value array has the keys
  2583 	 *                    'value' and 'charset'. An optional 'ascii' key can be
  2867 	 *                    'value' and 'charset'. An optional 'ascii' key can be
  2584 	 *                    set to false to avoid redundant ASCII checks.
  2868 	 *                    set to false to avoid redundant ASCII checks.
  2585 	 * @return array|WP_Error The $data parameter, with invalid characters removed from
  2869 	 * @return array|WP_Error The $data parameter, with invalid characters removed from
  2593 		foreach ( $data as &$value ) {
  2877 		foreach ( $data as &$value ) {
  2594 			$charset = $value['charset'];
  2878 			$charset = $value['charset'];
  2595 
  2879 
  2596 			if ( is_array( $value['length'] ) ) {
  2880 			if ( is_array( $value['length'] ) ) {
  2597 				$length = $value['length']['length'];
  2881 				$length = $value['length']['length'];
       
  2882 				$truncate_by_byte_length = 'byte' === $value['length']['type'];
  2598 			} else {
  2883 			} else {
  2599 				$length = false;
  2884 				$length = false;
       
  2885 				// Since we have no length, we'll never truncate.
       
  2886 				// Initialize the variable to false. true would take us
       
  2887 				// through an unnecessary (for this case) codepath below.
       
  2888 				$truncate_by_byte_length = false;
  2600 			}
  2889 			}
  2601 
  2890 
  2602 			// There's no charset to work with.
  2891 			// There's no charset to work with.
  2603 			if ( false === $charset ) {
  2892 			if ( false === $charset ) {
  2604 				continue;
  2893 				continue;
  2606 
  2895 
  2607 			// Column isn't a string.
  2896 			// Column isn't a string.
  2608 			if ( ! is_string( $value['value'] ) ) {
  2897 			if ( ! is_string( $value['value'] ) ) {
  2609 				continue;
  2898 				continue;
  2610 			}
  2899 			}
  2611 
       
  2612 			$truncate_by_byte_length = 'byte' === $value['length']['type'];
       
  2613 
  2900 
  2614 			$needs_validation = true;
  2901 			$needs_validation = true;
  2615 			if (
  2902 			if (
  2616 				// latin1 can store any byte sequence
  2903 				// latin1 can store any byte sequence
  2617 				'latin1' === $charset
  2904 				'latin1' === $charset
  2674 
  2961 
  2675 		if ( $db_check_string ) {
  2962 		if ( $db_check_string ) {
  2676 			$queries = array();
  2963 			$queries = array();
  2677 			foreach ( $data as $col => $value ) {
  2964 			foreach ( $data as $col => $value ) {
  2678 				if ( ! empty( $value['db'] ) ) {
  2965 				if ( ! empty( $value['db'] ) ) {
  2679 					if ( ! isset( $queries[ $value['charset'] ] ) ) {
       
  2680 						$queries[ $value['charset'] ] = array();
       
  2681 					}
       
  2682 
       
  2683 					// We're going to need to truncate by characters or bytes, depending on the length value we have.
  2966 					// We're going to need to truncate by characters or bytes, depending on the length value we have.
  2684 					if ( 'byte' === $value['length']['type'] ) {
  2967 					if ( 'byte' === $value['length']['type'] ) {
  2685 						// Split the CONVERT() calls by charset, so we can make sure the connection is right
  2968 						// Using binary causes LEFT() to truncate by bytes.
  2686 						$queries[ $value['charset'] ][ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING binary ), %d ) USING {$value['charset']} )", $value['value'], $value['length']['length'] );
  2969 						$charset = 'binary';
  2687 					} else {
  2970 					} else {
  2688 						$queries[ $value['charset'] ][ $col ] = $this->prepare( "LEFT( CONVERT( %s USING {$value['charset']} ), %d )", $value['value'], $value['length']['length'] );
  2971 						$charset = $value['charset'];
       
  2972 					}
       
  2973 
       
  2974 					if ( $this->charset ) {
       
  2975 						$connection_charset = $this->charset;
       
  2976 					} else {
       
  2977 						if ( $this->use_mysqli ) {
       
  2978 							$connection_charset = mysqli_character_set_name( $this->dbh );
       
  2979 						} else {
       
  2980 							$connection_charset = mysql_client_encoding();
       
  2981 						}
       
  2982 					}
       
  2983 
       
  2984 					if ( is_array( $value['length'] ) ) {
       
  2985 						$length = sprintf( '%.0f', $value['length']['length'] );
       
  2986 						$queries[ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING $charset ), $length ) USING $connection_charset )", $value['value'] );
       
  2987 					} else if ( 'binary' !== $charset ) {
       
  2988 						// If we don't have a length, there's no need to convert binary - it will always return the same result.
       
  2989 						$queries[ $col ] = $this->prepare( "CONVERT( CONVERT( %s USING $charset ) USING $connection_charset )", $value['value'] );
  2689 					}
  2990 					}
  2690 
  2991 
  2691 					unset( $data[ $col ]['db'] );
  2992 					unset( $data[ $col ]['db'] );
  2692 				}
  2993 				}
  2693 			}
  2994 			}
  2694 
  2995 
  2695 			$connection_charset = $this->charset;
  2996 			$sql = array();
  2696 			foreach ( $queries as $charset => $query ) {
  2997 			foreach ( $queries as $column => $query ) {
  2697 				if ( ! $query ) {
  2998 				if ( ! $query ) {
  2698 					continue;
  2999 					continue;
  2699 				}
  3000 				}
  2700 
  3001 
  2701 				// Change the charset to match the string(s) we're converting
  3002 				$sql[] = $query . " AS x_$column";
  2702 				if ( $charset !== $connection_charset ) {
  3003 			}
  2703 					$connection_charset = $charset;
  3004 
  2704 					$this->set_charset( $this->dbh, $charset );
  3005 			$this->check_current_query = false;
  2705 				}
  3006 			$row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A );
  2706 
  3007 			if ( ! $row ) {
  2707 				$this->check_current_query = false;
  3008 				return new WP_Error( 'wpdb_strip_invalid_text_failure' );
  2708 
  3009 			}
  2709 				$sql = array();
  3010 
  2710 				foreach ( $query as $column => $column_query ) {
  3011 			foreach ( array_keys( $data ) as $column ) {
  2711 					$sql[] = $column_query . " AS x_$column";
  3012 				if ( isset( $row["x_$column"] ) ) {
  2712 				}
       
  2713 
       
  2714 				$row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A );
       
  2715 				if ( ! $row ) {
       
  2716 					$this->set_charset( $this->dbh, $connection_charset );
       
  2717 					return new WP_Error( 'wpdb_strip_invalid_text_failure' );
       
  2718 				}
       
  2719 
       
  2720 				foreach ( array_keys( $query ) as $column ) {
       
  2721 					$data[ $column ]['value'] = $row["x_$column"];
  3013 					$data[ $column ]['value'] = $row["x_$column"];
  2722 				}
  3014 				}
  2723 			}
  3015 			}
  2724 
       
  2725 			// Don't forget to change the charset back!
       
  2726 			if ( $connection_charset !== $this->charset ) {
       
  2727 				$this->set_charset( $this->dbh );
       
  2728 			}
       
  2729 		}
  3016 		}
  2730 
  3017 
  2731 		return $data;
  3018 		return $data;
  2732 	}
  3019 	}
  2733 
  3020 
  2734 	/**
  3021 	/**
  2735 	 * Strips any invalid characters from the query.
  3022 	 * Strips any invalid characters from the query.
  2736 	 *
  3023 	 *
  2737 	 * @since 4.2.0
  3024 	 * @since 4.2.0
  2738 	 * @access protected
       
  2739 	 *
  3025 	 *
  2740 	 * @param string $query Query to convert.
  3026 	 * @param string $query Query to convert.
  2741 	 * @return string|WP_Error The converted query, or a WP_Error object if the conversion fails.
  3027 	 * @return string|WP_Error The converted query, or a WP_Error object if the conversion fails.
  2742 	 */
  3028 	 */
  2743 	protected function strip_invalid_text_from_query( $query ) {
  3029 	protected function strip_invalid_text_from_query( $query ) {
  2779 
  3065 
  2780 	/**
  3066 	/**
  2781 	 * Strips any invalid characters from the string for a given table and column.
  3067 	 * Strips any invalid characters from the string for a given table and column.
  2782 	 *
  3068 	 *
  2783 	 * @since 4.2.0
  3069 	 * @since 4.2.0
  2784 	 * @access public
       
  2785 	 *
  3070 	 *
  2786 	 * @param string $table  Table name.
  3071 	 * @param string $table  Table name.
  2787 	 * @param string $column Column name.
  3072 	 * @param string $column Column name.
  2788 	 * @param string $value  The text to check.
  3073 	 * @param string $value  The text to check.
  2789 	 * @return string|WP_Error The converted string, or a WP_Error object if the conversion fails.
  3074 	 * @return string|WP_Error The converted string, or a WP_Error object if the conversion fails.
  2820 
  3105 
  2821 	/**
  3106 	/**
  2822 	 * Find the first table name referenced in a query.
  3107 	 * Find the first table name referenced in a query.
  2823 	 *
  3108 	 *
  2824 	 * @since 4.2.0
  3109 	 * @since 4.2.0
  2825 	 * @access protected
       
  2826 	 *
  3110 	 *
  2827 	 * @param string $query The query to search.
  3111 	 * @param string $query The query to search.
  2828 	 * @return string|false $table The table name found, or false if a table couldn't be found.
  3112 	 * @return string|false $table The table name found, or false if a table couldn't be found.
  2829 	 */
  3113 	 */
  2830 	protected function get_table_from_query( $query ) {
  3114 	protected function get_table_from_query( $query ) {
  2832 		$query = rtrim( $query, ';/-#' );
  3116 		$query = rtrim( $query, ';/-#' );
  2833 
  3117 
  2834 		// Allow (select...) union [...] style queries. Use the first query's table name.
  3118 		// Allow (select...) union [...] style queries. Use the first query's table name.
  2835 		$query = ltrim( $query, "\r\n\t (" );
  3119 		$query = ltrim( $query, "\r\n\t (" );
  2836 
  3120 
  2837 		/*
  3121 		// Strip everything between parentheses except nested selects.
  2838 		 * Strip everything between parentheses except nested selects and use only 1,000
  3122 		$query = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', $query );
  2839 		 * chars of the query.
       
  2840 		 */
       
  2841 		$query = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', substr( $query, 0, 1000 ) );
       
  2842 
  3123 
  2843 		// Quickly match most common queries.
  3124 		// Quickly match most common queries.
  2844 		if ( preg_match( '/^\s*(?:'
  3125 		if ( preg_match( '/^\s*(?:'
  2845 				. 'SELECT.*?\s+FROM'
  3126 				. 'SELECT.*?\s+FROM'
  2846 				. '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?'
  3127 				. '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?'
  2847 				. '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?'
  3128 				. '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?'
  2848 				. '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?'
  3129 				. '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?'
  2849 				. '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:\s+FROM)?'
  3130 				. '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:.+?FROM)?'
  2850 				. ')\s+((?:[0-9a-zA-Z$_.`]|[\xC2-\xDF][\x80-\xBF])+)/is', $query, $maybe ) ) {
  3131 				. ')\s+((?:[0-9a-zA-Z$_.`-]|[\xC2-\xDF][\x80-\xBF])+)/is', $query, $maybe ) ) {
  2851 			return str_replace( '`', '', $maybe[1] );
  3132 			return str_replace( '`', '', $maybe[1] );
  2852 		}
  3133 		}
  2853 
  3134 
  2854 		// SHOW TABLE STATUS and SHOW TABLES
  3135 		// SHOW TABLE STATUS and SHOW TABLES WHERE Name = 'wp_posts'
  2855 		if ( preg_match( '/^\s*(?:'
  3136 		if ( preg_match( '/^\s*SHOW\s+(?:TABLE\s+STATUS|(?:FULL\s+)?TABLES).+WHERE\s+Name\s*=\s*("|\')((?:[0-9a-zA-Z$_.-]|[\xC2-\xDF][\x80-\xBF])+)\\1/is', $query, $maybe ) ) {
  2856 				. 'SHOW\s+TABLE\s+STATUS.+(?:LIKE\s+|WHERE\s+Name\s*=\s*)'
  3137 			return $maybe[2];
  2857 				. '|SHOW\s+(?:FULL\s+)?TABLES.+(?:LIKE\s+|WHERE\s+Name\s*=\s*)'
  3138 		}
  2858 				. ')\W((?:[0-9a-zA-Z$_.`]|[\xC2-\xDF][\x80-\xBF])+)\W/is', $query, $maybe ) ) {
  3139 
  2859 			return str_replace( '`', '', $maybe[1] );
  3140 		// SHOW TABLE STATUS LIKE and SHOW TABLES LIKE 'wp\_123\_%'
       
  3141 		// This quoted LIKE operand seldom holds a full table name.
       
  3142 		// It is usually a pattern for matching a prefix so we just
       
  3143 		// strip the trailing % and unescape the _ to get 'wp_123_'
       
  3144 		// which drop-ins can use for routing these SQL statements.
       
  3145 		if ( preg_match( '/^\s*SHOW\s+(?:TABLE\s+STATUS|(?:FULL\s+)?TABLES)\s+(?:WHERE\s+Name\s+)?LIKE\s*("|\')((?:[\\\\0-9a-zA-Z$_.-]|[\xC2-\xDF][\x80-\xBF])+)%?\\1/is', $query, $maybe ) ) {
       
  3146 			return str_replace( '\\_', '_', $maybe[2] );
  2860 		}
  3147 		}
  2861 
  3148 
  2862 		// Big pattern for the rest of the table-related queries.
  3149 		// Big pattern for the rest of the table-related queries.
  2863 		if ( preg_match( '/^\s*(?:'
  3150 		if ( preg_match( '/^\s*(?:'
  2864 				. '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM'
  3151 				. '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM'
  2872 				. '|CREATE(?:\s+\w+)?\s+INDEX.*\s+ON'
  3159 				. '|CREATE(?:\s+\w+)?\s+INDEX.*\s+ON'
  2873 				. '|DROP\s+INDEX.*\s+ON'
  3160 				. '|DROP\s+INDEX.*\s+ON'
  2874 				. '|LOAD\s+DATA.*INFILE.*INTO\s+TABLE'
  3161 				. '|LOAD\s+DATA.*INFILE.*INTO\s+TABLE'
  2875 				. '|(?:GRANT|REVOKE).*ON\s+TABLE'
  3162 				. '|(?:GRANT|REVOKE).*ON\s+TABLE'
  2876 				. '|SHOW\s+(?:.*FROM|.*TABLE)'
  3163 				. '|SHOW\s+(?:.*FROM|.*TABLE)'
  2877 				. ')\s+\(*\s*((?:[0-9a-zA-Z$_.`]|[\xC2-\xDF][\x80-\xBF])+)\s*\)*/is', $query, $maybe ) ) {
  3164 				. ')\s+\(*\s*((?:[0-9a-zA-Z$_.`-]|[\xC2-\xDF][\x80-\xBF])+)\s*\)*/is', $query, $maybe ) ) {
  2878 			return str_replace( '`', '', $maybe[1] );
  3165 			return str_replace( '`', '', $maybe[1] );
  2879 		}
  3166 		}
  2880 
  3167 
  2881 		return false;
  3168 		return false;
  2882 	}
  3169 	}
  2884 	/**
  3171 	/**
  2885 	 * Load the column metadata from the last query.
  3172 	 * Load the column metadata from the last query.
  2886 	 *
  3173 	 *
  2887 	 * @since 3.5.0
  3174 	 * @since 3.5.0
  2888 	 *
  3175 	 *
  2889 	 * @access protected
       
  2890 	 */
  3176 	 */
  2891 	protected function load_col_info() {
  3177 	protected function load_col_info() {
  2892 		if ( $this->col_info )
  3178 		if ( $this->col_info )
  2893 			return;
  3179 			return;
  2894 
  3180 
  2895 		if ( $this->use_mysqli ) {
  3181 		if ( $this->use_mysqli ) {
  2896 			for ( $i = 0; $i < @mysqli_num_fields( $this->result ); $i++ ) {
  3182 			$num_fields = mysqli_num_fields( $this->result );
  2897 				$this->col_info[ $i ] = @mysqli_fetch_field( $this->result );
  3183 			for ( $i = 0; $i < $num_fields; $i++ ) {
       
  3184 				$this->col_info[ $i ] = mysqli_fetch_field( $this->result );
  2898 			}
  3185 			}
  2899 		} else {
  3186 		} else {
  2900 			for ( $i = 0; $i < @mysql_num_fields( $this->result ); $i++ ) {
  3187 			$num_fields = mysql_num_fields( $this->result );
  2901 				$this->col_info[ $i ] = @mysql_fetch_field( $this->result, $i );
  3188 			for ( $i = 0; $i < $num_fields; $i++ ) {
       
  3189 				$this->col_info[ $i ] = mysql_fetch_field( $this->result, $i );
  2902 			}
  3190 			}
  2903 		}
  3191 		}
  2904 	}
  3192 	}
  2905 
  3193 
  2906 	/**
  3194 	/**
  2907 	 * Retrieve column metadata from the last query.
  3195 	 * Retrieve column metadata from the last query.
  2908 	 *
  3196 	 *
  2909 	 * @since 0.71
  3197 	 * @since 0.71
  2910 	 *
  3198 	 *
  2911 	 * @param string $info_type Optional. Type one of name, table, def, max_length, not_null, primary_key, multiple_key, unique_key, numeric, blob, type, unsigned, zerofill
  3199 	 * @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
  2912 	 * @param int $col_offset Optional. 0: col name. 1: which table the col's in. 2: col's max length. 3: if the col is numeric. 4: col's type
  3200 	 * @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
  2913 	 * @return mixed Column Results
  3201 	 * @return mixed Column Results
  2914 	 */
  3202 	 */
  2915 	public function get_col_info( $info_type = 'name', $col_offset = -1 ) {
  3203 	public function get_col_info( $info_type = 'name', $col_offset = -1 ) {
  2916 		$this->load_col_info();
  3204 		$this->load_col_info();
  2917 
  3205 
  2918 		if ( $this->col_info ) {
  3206 		if ( $this->col_info ) {
  2919 			if ( $col_offset == -1 ) {
  3207 			if ( $col_offset == -1 ) {
  2920 				$i = 0;
  3208 				$i = 0;
  2921 				$new_array = array();
  3209 				$new_array = array();
  2922 				foreach( (array) $this->col_info as $col ) {
  3210 				foreach ( (array) $this->col_info as $col ) {
  2923 					$new_array[$i] = $col->{$info_type};
  3211 					$new_array[$i] = $col->{$info_type};
  2924 					$i++;
  3212 					$i++;
  2925 				}
  3213 				}
  2926 				return $new_array;
  3214 				return $new_array;
  2927 			} else {
  3215 			} else {
  2933 	/**
  3221 	/**
  2934 	 * Starts the timer, for debugging purposes.
  3222 	 * Starts the timer, for debugging purposes.
  2935 	 *
  3223 	 *
  2936 	 * @since 1.5.0
  3224 	 * @since 1.5.0
  2937 	 *
  3225 	 *
  2938 	 * @return bool
  3226 	 * @return true
  2939 	 */
  3227 	 */
  2940 	public function timer_start() {
  3228 	public function timer_start() {
  2941 		$this->time_start = microtime( true );
  3229 		$this->time_start = microtime( true );
  2942 		return true;
  3230 		return true;
  2943 	}
  3231 	}
  2958 	 *
  3246 	 *
  2959 	 * Will not die if wpdb::$show_errors is false.
  3247 	 * Will not die if wpdb::$show_errors is false.
  2960 	 *
  3248 	 *
  2961 	 * @since 1.5.0
  3249 	 * @since 1.5.0
  2962 	 *
  3250 	 *
  2963 	 * @param string $message The Error message
  3251 	 * @param string $message    The Error message
  2964 	 * @param string $error_code Optional. A Computer readable string to identify the error.
  3252 	 * @param string $error_code Optional. A Computer readable string to identify the error.
  2965 	 * @return false|void
  3253 	 * @return false|void
  2966 	 */
  3254 	 */
  2967 	public function bail( $message, $error_code = '500' ) {
  3255 	public function bail( $message, $error_code = '500' ) {
  2968 		if ( !$this->show_errors ) {
  3256 		if ( !$this->show_errors ) {
  2969 			if ( class_exists( 'WP_Error' ) )
  3257 			if ( class_exists( 'WP_Error', false ) ) {
  2970 				$this->error = new WP_Error($error_code, $message);
  3258 				$this->error = new WP_Error($error_code, $message);
  2971 			else
  3259 			} else {
  2972 				$this->error = $message;
  3260 				$this->error = $message;
       
  3261 			}
  2973 			return false;
  3262 			return false;
  2974 		}
  3263 		}
  2975 		wp_die($message);
  3264 		wp_die($message);
  2976 	}
  3265 	}
  2977 
  3266 
       
  3267 
       
  3268 	/**
       
  3269 	 * Closes the current database connection.
       
  3270 	 *
       
  3271 	 * @since 4.5.0
       
  3272 	 *
       
  3273 	 * @return bool True if the connection was successfully closed, false if it wasn't,
       
  3274 	 *              or the connection doesn't exist.
       
  3275 	 */
       
  3276 	public function close() {
       
  3277 		if ( ! $this->dbh ) {
       
  3278 			return false;
       
  3279 		}
       
  3280 
       
  3281 		if ( $this->use_mysqli ) {
       
  3282 			$closed = mysqli_close( $this->dbh );
       
  3283 		} else {
       
  3284 			$closed = mysql_close( $this->dbh );
       
  3285 		}
       
  3286 
       
  3287 		if ( $closed ) {
       
  3288 			$this->dbh = null;
       
  3289 			$this->ready = false;
       
  3290 			$this->has_connected = false;
       
  3291 		}
       
  3292 
       
  3293 		return $closed;
       
  3294 	}
       
  3295 
  2978 	/**
  3296 	/**
  2979 	 * Whether MySQL database is at least the required minimum version.
  3297 	 * Whether MySQL database is at least the required minimum version.
  2980 	 *
  3298 	 *
  2981 	 * @since 2.5.0
  3299 	 * @since 2.5.0
  2982 	 * @uses $wp_version
  3300 	 *
  2983 	 * @uses $required_mysql_version
  3301 	 * @global string $wp_version
  2984 	 *
  3302 	 * @global string $required_mysql_version
  2985 	 * @return WP_Error
  3303 	 *
       
  3304 	 * @return WP_Error|void
  2986 	 */
  3305 	 */
  2987 	public function check_database_version() {
  3306 	public function check_database_version() {
  2988 		global $wp_version, $required_mysql_version;
  3307 		global $wp_version, $required_mysql_version;
  2989 		// Make sure the server has the required MySQL version
  3308 		// Make sure the server has the required MySQL version
  2990 		if ( version_compare($this->db_version(), $required_mysql_version, '<') )
  3309 		if ( version_compare($this->db_version(), $required_mysql_version, '<') ) {
       
  3310 			/* translators: 1: WordPress version number, 2: Minimum required MySQL version number */
  2991 			return new WP_Error('database_version', sprintf( __( '<strong>ERROR</strong>: WordPress %1$s requires MySQL %2$s or higher' ), $wp_version, $required_mysql_version ));
  3311 			return new WP_Error('database_version', sprintf( __( '<strong>ERROR</strong>: WordPress %1$s requires MySQL %2$s or higher' ), $wp_version, $required_mysql_version ));
       
  3312 		}
  2992 	}
  3313 	}
  2993 
  3314 
  2994 	/**
  3315 	/**
  2995 	 * Whether the database supports collation.
  3316 	 * Whether the database supports collation.
  2996 	 *
  3317 	 *
  2997 	 * Called when WordPress is generating the table scheme.
  3318 	 * Called when WordPress is generating the table scheme.
  2998 	 *
  3319 	 *
       
  3320 	 * Use `wpdb::has_cap( 'collation' )`.
       
  3321 	 *
  2999 	 * @since 2.5.0
  3322 	 * @since 2.5.0
  3000 	 * @deprecated 3.5.0
  3323 	 * @deprecated 3.5.0 Use wpdb::has_cap()
  3001 	 * @deprecated Use wpdb::has_cap( 'collation' )
       
  3002 	 *
  3324 	 *
  3003 	 * @return bool True if collation is supported, false if version does not
  3325 	 * @return bool True if collation is supported, false if version does not
  3004 	 */
  3326 	 */
  3005 	public function supports_collation() {
  3327 	public function supports_collation() {
  3006 		_deprecated_function( __FUNCTION__, '3.5', 'wpdb::has_cap( \'collation\' )' );
  3328 		_deprecated_function( __FUNCTION__, '3.5.0', 'wpdb::has_cap( \'collation\' )' );
  3007 		return $this->has_cap( 'collation' );
  3329 		return $this->has_cap( 'collation' );
  3008 	}
  3330 	}
  3009 
  3331 
  3010 	/**
  3332 	/**
  3011 	 * The database character collate.
  3333 	 * The database character collate.
  3027 
  3349 
  3028 	/**
  3350 	/**
  3029 	 * Determine if a database supports a particular feature.
  3351 	 * Determine if a database supports a particular feature.
  3030 	 *
  3352 	 *
  3031 	 * @since 2.7.0
  3353 	 * @since 2.7.0
  3032 	 * @since 4.1.0 Support was added for the 'utf8mb4' feature.
  3354 	 * @since 4.1.0 Added support for the 'utf8mb4' feature.
       
  3355 	 * @since 4.6.0 Added support for the 'utf8mb4_520' feature.
  3033 	 *
  3356 	 *
  3034 	 * @see wpdb::db_version()
  3357 	 * @see wpdb::db_version()
  3035 	 *
  3358 	 *
  3036 	 * @param string $db_cap The feature to check for. Accepts 'collation',
  3359 	 * @param string $db_cap The feature to check for. Accepts 'collation',
  3037 	 *                       'group_concat', 'subqueries', 'set_charset',
  3360 	 *                       'group_concat', 'subqueries', 'set_charset',
  3038 	 *                       or 'utf8mb4'.
  3361 	 *                       'utf8mb4', or 'utf8mb4_520'.
  3039 	 * @return bool Whether the database feature is supported, false otherwise.
  3362 	 * @return int|false Whether the database feature is supported, false otherwise.
  3040 	 */
  3363 	 */
  3041 	public function has_cap( $db_cap ) {
  3364 	public function has_cap( $db_cap ) {
  3042 		$version = $this->db_version();
  3365 		$version = $this->db_version();
  3043 
  3366 
  3044 		switch ( strtolower( $db_cap ) ) {
  3367 		switch ( strtolower( $db_cap ) ) {
  3066 					$client_version = preg_replace( '/^\D+([\d.]+).*/', '$1', $client_version );
  3389 					$client_version = preg_replace( '/^\D+([\d.]+).*/', '$1', $client_version );
  3067 					return version_compare( $client_version, '5.0.9', '>=' );
  3390 					return version_compare( $client_version, '5.0.9', '>=' );
  3068 				} else {
  3391 				} else {
  3069 					return version_compare( $client_version, '5.5.3', '>=' );
  3392 					return version_compare( $client_version, '5.5.3', '>=' );
  3070 				}
  3393 				}
       
  3394 			case 'utf8mb4_520' : // @since 4.6.0
       
  3395 				return version_compare( $version, '5.6', '>=' );
  3071 		}
  3396 		}
  3072 
  3397 
  3073 		return false;
  3398 		return false;
  3074 	}
  3399 	}
  3075 
  3400 
  3079 	 * Searches up the list of functions until it reaches
  3404 	 * Searches up the list of functions until it reaches
  3080 	 * the one that would most logically had called this method.
  3405 	 * the one that would most logically had called this method.
  3081 	 *
  3406 	 *
  3082 	 * @since 2.5.0
  3407 	 * @since 2.5.0
  3083 	 *
  3408 	 *
  3084 	 * @return string The name of the calling function
  3409 	 * @return string|array The name of the calling function
  3085 	 */
  3410 	 */
  3086 	public function get_caller() {
  3411 	public function get_caller() {
  3087 		return wp_debug_backtrace_summary( __CLASS__ );
  3412 		return wp_debug_backtrace_summary( __CLASS__ );
  3088 	}
  3413 	}
  3089 
  3414 
  3090 	/**
  3415 	/**
  3091 	 * The database version number.
  3416 	 * Retrieves the MySQL server version.
  3092 	 *
  3417 	 *
  3093 	 * @since 2.7.0
  3418 	 * @since 2.7.0
  3094 	 *
  3419 	 *
  3095 	 * @return null|string Null on failure, version number on success.
  3420 	 * @return null|string Null on failure, version number on success.
  3096 	 */
  3421 	 */