wp/wp-includes/wp-db.php
changeset 9 177826044cd9
parent 7 cf61fcea0001
child 16 a86126ab1dd4
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
    16 
    16 
    17 /**
    17 /**
    18  * @since 0.71
    18  * @since 0.71
    19  */
    19  */
    20 define( 'OBJECT', 'OBJECT' );
    20 define( 'OBJECT', 'OBJECT' );
       
    21 // phpcs:ignore Generic.NamingConventions.UpperCaseConstantName.ConstantNotUpperCase
    21 define( 'object', 'OBJECT' ); // Back compat.
    22 define( 'object', 'OBJECT' ); // Back compat.
    22 
    23 
    23 /**
    24 /**
    24  * @since 2.5.0
    25  * @since 2.5.0
    25  */
    26  */
   172 	 * @var array
   173 	 * @var array
   173 	 */
   174 	 */
   174 	protected $col_info;
   175 	protected $col_info;
   175 
   176 
   176 	/**
   177 	/**
   177 	 * Saved queries that were executed
   178 	 * Log of queries that were executed, for debugging purposes.
   178 	 *
   179 	 *
   179 	 * @since 1.5.0
   180 	 * @since 1.5.0
   180 	 * @var array
   181 	 * @since 2.5.0 The third element in each query log was added to record the calling functions.
       
   182 	 * @since 5.1.0 The fourth element in each query log was added to record the start time.
       
   183 	 *
       
   184 	 * @var array[] {
       
   185 	 *     Array of queries that were executed.
       
   186 	 *
       
   187 	 *     @type array ...$0 {
       
   188 	 *         Data for each query.
       
   189 	 *
       
   190 	 *         @type string $0 The query's SQL.
       
   191 	 *         @type float  $1 Total time spent on the query, in seconds.
       
   192 	 *         @type string $2 Comma separated list of the calling functions.
       
   193 	 *         @type float  $3 Unix timestamp of the time at the start of the query.
       
   194 	 *     }
       
   195 	 * }
   181 	 */
   196 	 */
   182 	var $queries;
   197 	var $queries;
   183 
   198 
   184 	/**
   199 	/**
   185 	 * The number of times to retry reconnecting before dying.
   200 	 * The number of times to retry reconnecting before dying.
   206 	 * WordPress base table prefix.
   221 	 * WordPress base table prefix.
   207 	 *
   222 	 *
   208 	 * @since 3.0.0
   223 	 * @since 3.0.0
   209 	 * @var string
   224 	 * @var string
   210 	 */
   225 	 */
   211 	 public $base_prefix;
   226 	public $base_prefix;
   212 
   227 
   213 	/**
   228 	/**
   214 	 * Whether the database queries are ready to start executing.
   229 	 * Whether the database queries are ready to start executing.
   215 	 *
   230 	 *
   216 	 * @since 2.3.2
   231 	 * @since 2.3.2
   239 	 *
   254 	 *
   240 	 * @since 2.5.0
   255 	 * @since 2.5.0
   241 	 * @see wpdb::tables()
   256 	 * @see wpdb::tables()
   242 	 * @var array
   257 	 * @var array
   243 	 */
   258 	 */
   244 	var $tables = array( 'posts', 'comments', 'links', 'options', 'postmeta',
   259 	var $tables = array(
   245 		'terms', 'term_taxonomy', 'term_relationships', 'termmeta', 'commentmeta' );
   260 		'posts',
       
   261 		'comments',
       
   262 		'links',
       
   263 		'options',
       
   264 		'postmeta',
       
   265 		'terms',
       
   266 		'term_taxonomy',
       
   267 		'term_relationships',
       
   268 		'termmeta',
       
   269 		'commentmeta',
       
   270 	);
   246 
   271 
   247 	/**
   272 	/**
   248 	 * List of deprecated WordPress tables
   273 	 * List of deprecated WordPress tables
   249 	 *
   274 	 *
   250 	 * categories, post2cat, and link2cat were deprecated in 2.3.0, db version 5539
   275 	 * categories, post2cat, and link2cat were deprecated in 2.3.0, db version 5539
   269 	 *
   294 	 *
   270 	 * @since 3.0.0
   295 	 * @since 3.0.0
   271 	 * @see wpdb::tables()
   296 	 * @see wpdb::tables()
   272 	 * @var array
   297 	 * @var array
   273 	 */
   298 	 */
   274 	var $ms_global_tables = array( 'blogs', 'signups', 'site', 'sitemeta',
   299 	var $ms_global_tables = array(
   275 		'sitecategories', 'registration_log', 'blog_versions' );
   300 		'blogs',
       
   301 		'blogmeta',
       
   302 		'signups',
       
   303 		'site',
       
   304 		'sitemeta',
       
   305 		'sitecategories',
       
   306 		'registration_log',
       
   307 		'blog_versions',
       
   308 	);
   276 
   309 
   277 	/**
   310 	/**
   278 	 * WordPress Comments table
   311 	 * WordPress Comments table
   279 	 *
   312 	 *
   280 	 * @since 1.5.0
   313 	 * @since 1.5.0
   379 	 *
   412 	 *
   380 	 * @since 3.0.0
   413 	 * @since 3.0.0
   381 	 * @var string
   414 	 * @var string
   382 	 */
   415 	 */
   383 	public $blogs;
   416 	public $blogs;
       
   417 
       
   418 	/**
       
   419 	 * Multisite Blog Metadata table
       
   420 	 *
       
   421 	 * @since 5.1.0
       
   422 	 * @var string
       
   423 	 */
       
   424 	public $blogmeta;
   384 
   425 
   385 	/**
   426 	/**
   386 	 * Multisite Blog Versions table
   427 	 * Multisite Blog Versions table
   387 	 *
   428 	 *
   388 	 * @since 3.0.0
   429 	 * @since 3.0.0
   526 	 * A list of incompatible SQL modes.
   567 	 * A list of incompatible SQL modes.
   527 	 *
   568 	 *
   528 	 * @since 3.9.0
   569 	 * @since 3.9.0
   529 	 * @var array
   570 	 * @var array
   530 	 */
   571 	 */
   531 	protected $incompatible_modes = array( 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY',
   572 	protected $incompatible_modes = array(
   532 		'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL' );
   573 		'NO_ZERO_DATE',
       
   574 		'ONLY_FULL_GROUP_BY',
       
   575 		'STRICT_TRANS_TABLES',
       
   576 		'STRICT_ALL_TABLES',
       
   577 		'TRADITIONAL',
       
   578 	);
   533 
   579 
   534 	/**
   580 	/**
   535 	 * Whether to use mysqli over mysql.
   581 	 * Whether to use mysqli over mysql.
   536 	 *
   582 	 *
   537 	 * @since 3.9.0
   583 	 * @since 3.9.0
   565 	 * @param string $dbhost     MySQL database host
   611 	 * @param string $dbhost     MySQL database host
   566 	 */
   612 	 */
   567 	public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) {
   613 	public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) {
   568 		register_shutdown_function( array( $this, '__destruct' ) );
   614 		register_shutdown_function( array( $this, '__destruct' ) );
   569 
   615 
   570 		if ( WP_DEBUG && WP_DEBUG_DISPLAY )
   616 		if ( WP_DEBUG && WP_DEBUG_DISPLAY ) {
   571 			$this->show_errors();
   617 			$this->show_errors();
       
   618 		}
   572 
   619 
   573 		// Use ext/mysqli if it exists unless WP_USE_EXT_MYSQL is defined as true
   620 		// Use ext/mysqli if it exists unless WP_USE_EXT_MYSQL is defined as true
   574 		if ( function_exists( 'mysqli_connect' ) ) {
   621 		if ( function_exists( 'mysqli_connect' ) ) {
   575 			$this->use_mysqli = true;
   622 			$this->use_mysqli = true;
   576 
   623 
   577 			if ( defined( 'WP_USE_EXT_MYSQL' ) ) {
   624 			if ( defined( 'WP_USE_EXT_MYSQL' ) ) {
   578 				$this->use_mysqli = ! WP_USE_EXT_MYSQL;
   625 				$this->use_mysqli = ! WP_USE_EXT_MYSQL;
   579 			}
   626 			}
   580 		}
   627 		}
   581 
   628 
   582 		$this->dbuser = $dbuser;
   629 		$this->dbuser     = $dbuser;
   583 		$this->dbpassword = $dbpassword;
   630 		$this->dbpassword = $dbpassword;
   584 		$this->dbname = $dbname;
   631 		$this->dbname     = $dbname;
   585 		$this->dbhost = $dbhost;
   632 		$this->dbhost     = $dbhost;
   586 
   633 
   587 		// wp-config.php creation will manually connect when ready.
   634 		// wp-config.php creation will manually connect when ready.
   588 		if ( defined( 'WP_SETUP_CONFIG' ) ) {
   635 		if ( defined( 'WP_SETUP_CONFIG' ) ) {
   589 			return;
   636 			return;
   590 		}
   637 		}
   610 	 *
   657 	 *
   611 	 * @param string $name The private member to get, and optionally process
   658 	 * @param string $name The private member to get, and optionally process
   612 	 * @return mixed The private member
   659 	 * @return mixed The private member
   613 	 */
   660 	 */
   614 	public function __get( $name ) {
   661 	public function __get( $name ) {
   615 		if ( 'col_info' === $name )
   662 		if ( 'col_info' === $name ) {
   616 			$this->load_col_info();
   663 			$this->load_col_info();
       
   664 		}
   617 
   665 
   618 		return $this->$name;
   666 		return $this->$name;
   619 	}
   667 	}
   620 
   668 
   621 	/**
   669 	/**
   630 		$protected_members = array(
   678 		$protected_members = array(
   631 			'col_meta',
   679 			'col_meta',
   632 			'table_charset',
   680 			'table_charset',
   633 			'check_current_query',
   681 			'check_current_query',
   634 		);
   682 		);
   635 		if (  in_array( $name, $protected_members, true ) ) {
   683 		if ( in_array( $name, $protected_members, true ) ) {
   636 			return;
   684 			return;
   637 		}
   685 		}
   638 		$this->$name = $value;
   686 		$this->$name = $value;
   639 	}
   687 	}
   640 
   688 
   669 	 */
   717 	 */
   670 	public function init_charset() {
   718 	public function init_charset() {
   671 		$charset = '';
   719 		$charset = '';
   672 		$collate = '';
   720 		$collate = '';
   673 
   721 
   674 		if ( function_exists('is_multisite') && is_multisite() ) {
   722 		if ( function_exists( 'is_multisite' ) && is_multisite() ) {
   675 			$charset = 'utf8';
   723 			$charset = 'utf8';
   676 			if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) {
   724 			if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) {
   677 				$collate = DB_COLLATE;
   725 				$collate = DB_COLLATE;
   678 			} else {
   726 			} else {
   679 				$collate = 'utf8_general_ci';
   727 				$collate = 'utf8_general_ci';
   742 	 * @param resource $dbh     The resource given by mysql_connect
   790 	 * @param resource $dbh     The resource given by mysql_connect
   743 	 * @param string   $charset Optional. The character set. Default null.
   791 	 * @param string   $charset Optional. The character set. Default null.
   744 	 * @param string   $collate Optional. The collation. Default null.
   792 	 * @param string   $collate Optional. The collation. Default null.
   745 	 */
   793 	 */
   746 	public function set_charset( $dbh, $charset = null, $collate = null ) {
   794 	public function set_charset( $dbh, $charset = null, $collate = null ) {
   747 		if ( ! isset( $charset ) )
   795 		if ( ! isset( $charset ) ) {
   748 			$charset = $this->charset;
   796 			$charset = $this->charset;
   749 		if ( ! isset( $collate ) )
   797 		}
       
   798 		if ( ! isset( $collate ) ) {
   750 			$collate = $this->collate;
   799 			$collate = $this->collate;
       
   800 		}
   751 		if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) {
   801 		if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) {
   752 			$set_charset_succeeded = true;
   802 			$set_charset_succeeded = true;
   753 
   803 
   754 			if ( $this->use_mysqli ) {
   804 			if ( $this->use_mysqli ) {
   755 				if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) {
   805 				if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) {
   756 					$set_charset_succeeded = mysqli_set_charset( $dbh, $charset );
   806 					$set_charset_succeeded = mysqli_set_charset( $dbh, $charset );
   757 				}
   807 				}
   758 
   808 
   759 				if ( $set_charset_succeeded ) {
   809 				if ( $set_charset_succeeded ) {
   760 					$query = $this->prepare( 'SET NAMES %s', $charset );
   810 					$query = $this->prepare( 'SET NAMES %s', $charset );
   761 					if ( ! empty( $collate ) )
   811 					if ( ! empty( $collate ) ) {
   762 						$query .= $this->prepare( ' COLLATE %s', $collate );
   812 						$query .= $this->prepare( ' COLLATE %s', $collate );
       
   813 					}
   763 					mysqli_query( $dbh, $query );
   814 					mysqli_query( $dbh, $query );
   764 				}
   815 				}
   765 			} else {
   816 			} else {
   766 				if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) {
   817 				if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) {
   767 					$set_charset_succeeded = mysql_set_charset( $charset, $dbh );
   818 					$set_charset_succeeded = mysql_set_charset( $charset, $dbh );
   768 				}
   819 				}
   769 				if ( $set_charset_succeeded ) {
   820 				if ( $set_charset_succeeded ) {
   770 					$query = $this->prepare( 'SET NAMES %s', $charset );
   821 					$query = $this->prepare( 'SET NAMES %s', $charset );
   771 					if ( ! empty( $collate ) )
   822 					if ( ! empty( $collate ) ) {
   772 						$query .= $this->prepare( ' COLLATE %s', $collate );
   823 						$query .= $this->prepare( ' COLLATE %s', $collate );
       
   824 					}
   773 					mysql_query( $query, $dbh );
   825 					mysql_query( $query, $dbh );
   774 				}
   826 				}
   775 			}
   827 			}
   776 		}
   828 		}
   777 	}
   829 	}
   850 	 * @param bool   $set_table_names Optional. Whether the table names, e.g. wpdb::$posts, should be updated or not.
   902 	 * @param bool   $set_table_names Optional. Whether the table names, e.g. wpdb::$posts, should be updated or not.
   851 	 * @return string|WP_Error Old prefix or WP_Error on error
   903 	 * @return string|WP_Error Old prefix or WP_Error on error
   852 	 */
   904 	 */
   853 	public function set_prefix( $prefix, $set_table_names = true ) {
   905 	public function set_prefix( $prefix, $set_table_names = true ) {
   854 
   906 
   855 		if ( preg_match( '|[^a-z0-9_]|i', $prefix ) )
   907 		if ( preg_match( '|[^a-z0-9_]|i', $prefix ) ) {
   856 			return new WP_Error('invalid_db_prefix', 'Invalid database prefix' );
   908 			return new WP_Error( 'invalid_db_prefix', 'Invalid database prefix' );
       
   909 		}
   857 
   910 
   858 		$old_prefix = is_multisite() ? '' : $prefix;
   911 		$old_prefix = is_multisite() ? '' : $prefix;
   859 
   912 
   860 		if ( isset( $this->base_prefix ) )
   913 		if ( isset( $this->base_prefix ) ) {
   861 			$old_prefix = $this->base_prefix;
   914 			$old_prefix = $this->base_prefix;
       
   915 		}
   862 
   916 
   863 		$this->base_prefix = $prefix;
   917 		$this->base_prefix = $prefix;
   864 
   918 
   865 		if ( $set_table_names ) {
   919 		if ( $set_table_names ) {
   866 			foreach ( $this->tables( 'global' ) as $table => $prefixed_table )
   920 			foreach ( $this->tables( 'global' ) as $table => $prefixed_table ) {
   867 				$this->$table = $prefixed_table;
   921 				$this->$table = $prefixed_table;
   868 
   922 			}
   869 			if ( is_multisite() && empty( $this->blogid ) )
   923 
       
   924 			if ( is_multisite() && empty( $this->blogid ) ) {
   870 				return $old_prefix;
   925 				return $old_prefix;
       
   926 			}
   871 
   927 
   872 			$this->prefix = $this->get_blog_prefix();
   928 			$this->prefix = $this->get_blog_prefix();
   873 
   929 
   874 			foreach ( $this->tables( 'blog' ) as $table => $prefixed_table )
   930 			foreach ( $this->tables( 'blog' ) as $table => $prefixed_table ) {
   875 				$this->$table = $prefixed_table;
   931 				$this->$table = $prefixed_table;
   876 
   932 			}
   877 			foreach ( $this->tables( 'old' ) as $table => $prefixed_table )
   933 
       
   934 			foreach ( $this->tables( 'old' ) as $table => $prefixed_table ) {
   878 				$this->$table = $prefixed_table;
   935 				$this->$table = $prefixed_table;
       
   936 			}
   879 		}
   937 		}
   880 		return $old_prefix;
   938 		return $old_prefix;
   881 	}
   939 	}
   882 
   940 
   883 	/**
   941 	/**
   897 		$old_blog_id  = $this->blogid;
   955 		$old_blog_id  = $this->blogid;
   898 		$this->blogid = $blog_id;
   956 		$this->blogid = $blog_id;
   899 
   957 
   900 		$this->prefix = $this->get_blog_prefix();
   958 		$this->prefix = $this->get_blog_prefix();
   901 
   959 
   902 		foreach ( $this->tables( 'blog' ) as $table => $prefixed_table )
   960 		foreach ( $this->tables( 'blog' ) as $table => $prefixed_table ) {
   903 			$this->$table = $prefixed_table;
   961 			$this->$table = $prefixed_table;
   904 
   962 		}
   905 		foreach ( $this->tables( 'old' ) as $table => $prefixed_table )
   963 
       
   964 		foreach ( $this->tables( 'old' ) as $table => $prefixed_table ) {
   906 			$this->$table = $prefixed_table;
   965 			$this->$table = $prefixed_table;
       
   966 		}
   907 
   967 
   908 		return $old_blog_id;
   968 		return $old_blog_id;
   909 	}
   969 	}
   910 
   970 
   911 	/**
   971 	/**
   915 	 * @param int $blog_id Optional.
   975 	 * @param int $blog_id Optional.
   916 	 * @return string Blog prefix.
   976 	 * @return string Blog prefix.
   917 	 */
   977 	 */
   918 	public function get_blog_prefix( $blog_id = null ) {
   978 	public function get_blog_prefix( $blog_id = null ) {
   919 		if ( is_multisite() ) {
   979 		if ( is_multisite() ) {
   920 			if ( null === $blog_id )
   980 			if ( null === $blog_id ) {
   921 				$blog_id = $this->blogid;
   981 				$blog_id = $this->blogid;
       
   982 			}
   922 			$blog_id = (int) $blog_id;
   983 			$blog_id = (int) $blog_id;
   923 			if ( defined( 'MULTISITE' ) && ( 0 == $blog_id || 1 == $blog_id ) )
   984 			if ( defined( 'MULTISITE' ) && ( 0 == $blog_id || 1 == $blog_id ) ) {
   924 				return $this->base_prefix;
   985 				return $this->base_prefix;
   925 			else
   986 			} else {
   926 				return $this->base_prefix . $blog_id . '_';
   987 				return $this->base_prefix . $blog_id . '_';
       
   988 			}
   927 		} else {
   989 		} else {
   928 			return $this->base_prefix;
   990 			return $this->base_prefix;
   929 		}
   991 		}
   930 	}
   992 	}
   931 
   993 
   956 	 * @param int    $blog_id Optional. The blog_id to prefix. Defaults to wpdb::$blogid. Used only when prefix is requested.
  1018 	 * @param int    $blog_id Optional. The blog_id to prefix. Defaults to wpdb::$blogid. Used only when prefix is requested.
   957 	 * @return array Table names. When a prefix is requested, the key is the unprefixed table name.
  1019 	 * @return array Table names. When a prefix is requested, the key is the unprefixed table name.
   958 	 */
  1020 	 */
   959 	public function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) {
  1021 	public function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) {
   960 		switch ( $scope ) {
  1022 		switch ( $scope ) {
   961 			case 'all' :
  1023 			case 'all':
   962 				$tables = array_merge( $this->global_tables, $this->tables );
  1024 				$tables = array_merge( $this->global_tables, $this->tables );
   963 				if ( is_multisite() )
  1025 				if ( is_multisite() ) {
   964 					$tables = array_merge( $tables, $this->ms_global_tables );
  1026 					$tables = array_merge( $tables, $this->ms_global_tables );
       
  1027 				}
   965 				break;
  1028 				break;
   966 			case 'blog' :
  1029 			case 'blog':
   967 				$tables = $this->tables;
  1030 				$tables = $this->tables;
   968 				break;
  1031 				break;
   969 			case 'global' :
  1032 			case 'global':
   970 				$tables = $this->global_tables;
  1033 				$tables = $this->global_tables;
   971 				if ( is_multisite() )
  1034 				if ( is_multisite() ) {
   972 					$tables = array_merge( $tables, $this->ms_global_tables );
  1035 					$tables = array_merge( $tables, $this->ms_global_tables );
       
  1036 				}
   973 				break;
  1037 				break;
   974 			case 'ms_global' :
  1038 			case 'ms_global':
   975 				$tables = $this->ms_global_tables;
  1039 				$tables = $this->ms_global_tables;
   976 				break;
  1040 				break;
   977 			case 'old' :
  1041 			case 'old':
   978 				$tables = $this->old_tables;
  1042 				$tables = $this->old_tables;
   979 				break;
  1043 				break;
   980 			default :
  1044 			default:
   981 				return array();
  1045 				return array();
   982 		}
  1046 		}
   983 
  1047 
   984 		if ( $prefix ) {
  1048 		if ( $prefix ) {
   985 			if ( ! $blog_id )
  1049 			if ( ! $blog_id ) {
   986 				$blog_id = $this->blogid;
  1050 				$blog_id = $this->blogid;
   987 			$blog_prefix = $this->get_blog_prefix( $blog_id );
  1051 			}
   988 			$base_prefix = $this->base_prefix;
  1052 			$blog_prefix   = $this->get_blog_prefix( $blog_id );
       
  1053 			$base_prefix   = $this->base_prefix;
   989 			$global_tables = array_merge( $this->global_tables, $this->ms_global_tables );
  1054 			$global_tables = array_merge( $this->global_tables, $this->ms_global_tables );
   990 			foreach ( $tables as $k => $table ) {
  1055 			foreach ( $tables as $k => $table ) {
   991 				if ( in_array( $table, $global_tables ) )
  1056 				if ( in_array( $table, $global_tables ) ) {
   992 					$tables[ $table ] = $base_prefix . $table;
  1057 					$tables[ $table ] = $base_prefix . $table;
   993 				else
  1058 				} else {
   994 					$tables[ $table ] = $blog_prefix . $table;
  1059 					$tables[ $table ] = $blog_prefix . $table;
       
  1060 				}
   995 				unset( $tables[ $k ] );
  1061 				unset( $tables[ $k ] );
   996 			}
  1062 			}
   997 
  1063 
   998 			if ( isset( $tables['users'] ) && defined( 'CUSTOM_USER_TABLE' ) )
  1064 			if ( isset( $tables['users'] ) && defined( 'CUSTOM_USER_TABLE' ) ) {
   999 				$tables['users'] = CUSTOM_USER_TABLE;
  1065 				$tables['users'] = CUSTOM_USER_TABLE;
  1000 
  1066 			}
  1001 			if ( isset( $tables['usermeta'] ) && defined( 'CUSTOM_USER_META_TABLE' ) )
  1067 
       
  1068 			if ( isset( $tables['usermeta'] ) && defined( 'CUSTOM_USER_META_TABLE' ) ) {
  1002 				$tables['usermeta'] = CUSTOM_USER_META_TABLE;
  1069 				$tables['usermeta'] = CUSTOM_USER_META_TABLE;
       
  1070 			}
  1003 		}
  1071 		}
  1004 
  1072 
  1005 		return $tables;
  1073 		return $tables;
  1006 	}
  1074 	}
  1007 
  1075 
  1015 	 *
  1083 	 *
  1016 	 * @param string        $db  MySQL database name
  1084 	 * @param string        $db  MySQL database name
  1017 	 * @param resource|null $dbh Optional link identifier.
  1085 	 * @param resource|null $dbh Optional link identifier.
  1018 	 */
  1086 	 */
  1019 	public function select( $db, $dbh = null ) {
  1087 	public function select( $db, $dbh = null ) {
  1020 		if ( is_null($dbh) )
  1088 		if ( is_null( $dbh ) ) {
  1021 			$dbh = $this->dbh;
  1089 			$dbh = $this->dbh;
       
  1090 		}
  1022 
  1091 
  1023 		if ( $this->use_mysqli ) {
  1092 		if ( $this->use_mysqli ) {
  1024 			$success = mysqli_select_db( $dbh, $db );
  1093 			$success = mysqli_select_db( $dbh, $db );
  1025 		} else {
  1094 		} else {
  1026 			$success = mysql_select_db( $db, $dbh );
  1095 			$success = mysql_select_db( $db, $dbh );
  1042 				$message .= '<li>' . __( 'Are you sure it exists?' ) . "</li>\n";
  1111 				$message .= '<li>' . __( 'Are you sure it exists?' ) . "</li>\n";
  1043 
  1112 
  1044 				$message .= '<li>' . sprintf(
  1113 				$message .= '<li>' . sprintf(
  1045 					/* translators: 1: database user, 2: database name */
  1114 					/* translators: 1: database user, 2: database name */
  1046 					__( 'Does the user %1$s have permission to use the %2$s database?' ),
  1115 					__( 'Does the user %1$s have permission to use the %2$s database?' ),
  1047 					'<code>' . htmlspecialchars( $this->dbuser, ENT_QUOTES )  . '</code>',
  1116 					'<code>' . htmlspecialchars( $this->dbuser, ENT_QUOTES ) . '</code>',
  1048 					'<code>' . htmlspecialchars( $db, ENT_QUOTES ) . '</code>'
  1117 					'<code>' . htmlspecialchars( $db, ENT_QUOTES ) . '</code>'
  1049 				) . "</li>\n";
  1118 				) . "</li>\n";
  1050 
  1119 
  1051 				$message .= '<li>' . sprintf(
  1120 				$message .= '<li>' . sprintf(
  1052 					/* translators: %s: database name */
  1121 					/* 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?' ),
  1122 					__( '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 )
  1123 					htmlspecialchars( $db, ENT_QUOTES )
  1055 				). "</li>\n";
  1124 				) . "</li>\n";
  1056 
  1125 
  1057 				$message .= "</ul>\n";
  1126 				$message .= "</ul>\n";
  1058 
  1127 
  1059 				$message .= '<p>' . sprintf(
  1128 				$message .= '<p>' . sprintf(
  1060 					/* translators: %s: support forums URL */
  1129 					/* 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>.' ),
  1130 					__( '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/' )
  1131 					__( 'https://wordpress.org/support/forums/' )
  1063 				) . "</p>\n";
  1132 				) . "</p>\n";
  1064 
  1133 
  1065 				$this->bail( $message, 'db_select_fail' );
  1134 				$this->bail( $message, 'db_select_fail' );
  1066 			}
  1135 			}
  1067 		}
  1136 		}
  1079 	 *
  1148 	 *
  1080 	 * @param string $string
  1149 	 * @param string $string
  1081 	 * @return string
  1150 	 * @return string
  1082 	 */
  1151 	 */
  1083 	function _weak_escape( $string ) {
  1152 	function _weak_escape( $string ) {
  1084 		if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) )
  1153 		if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) {
  1085 			_deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' );
  1154 			_deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' );
       
  1155 		}
  1086 		return addslashes( $string );
  1156 		return addslashes( $string );
  1087 	}
  1157 	}
  1088 
  1158 
  1089 	/**
  1159 	/**
  1090 	 * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string()
  1160 	 * Real escape, using mysqli_real_escape_string() or mysql_real_escape_string()
  1128 	 */
  1198 	 */
  1129 	public function _escape( $data ) {
  1199 	public function _escape( $data ) {
  1130 		if ( is_array( $data ) ) {
  1200 		if ( is_array( $data ) ) {
  1131 			foreach ( $data as $k => $v ) {
  1201 			foreach ( $data as $k => $v ) {
  1132 				if ( is_array( $v ) ) {
  1202 				if ( is_array( $v ) ) {
  1133 					$data[$k] = $this->_escape( $v );
  1203 					$data[ $k ] = $this->_escape( $v );
  1134 				} else {
  1204 				} else {
  1135 					$data[$k] = $this->_real_escape( $v );
  1205 					$data[ $k ] = $this->_real_escape( $v );
  1136 				}
  1206 				}
  1137 			}
  1207 			}
  1138 		} else {
  1208 		} else {
  1139 			$data = $this->_real_escape( $data );
  1209 			$data = $this->_real_escape( $data );
  1140 		}
  1210 		}
  1154 	 *
  1224 	 *
  1155 	 * @param mixed $data
  1225 	 * @param mixed $data
  1156 	 * @return mixed
  1226 	 * @return mixed
  1157 	 */
  1227 	 */
  1158 	public function escape( $data ) {
  1228 	public function escape( $data ) {
  1159 		if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) )
  1229 		if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) {
  1160 			_deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' );
  1230 			_deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' );
       
  1231 		}
  1161 		if ( is_array( $data ) ) {
  1232 		if ( is_array( $data ) ) {
  1162 			foreach ( $data as $k => $v ) {
  1233 			foreach ( $data as $k => $v ) {
  1163 				if ( is_array( $v ) )
  1234 				if ( is_array( $v ) ) {
  1164 					$data[$k] = $this->escape( $v, 'recursive' );
  1235 					$data[ $k ] = $this->escape( $v, 'recursive' );
  1165 				else
  1236 				} else {
  1166 					$data[$k] = $this->_weak_escape( $v, 'internal' );
  1237 					$data[ $k ] = $this->_weak_escape( $v, 'internal' );
       
  1238 				}
  1167 			}
  1239 			}
  1168 		} else {
  1240 		} else {
  1169 			$data = $this->_weak_escape( $data, 'internal' );
  1241 			$data = $this->_weak_escape( $data, 'internal' );
  1170 		}
  1242 		}
  1171 
  1243 
  1180 	 * @since 2.3.0
  1252 	 * @since 2.3.0
  1181 	 *
  1253 	 *
  1182 	 * @param string $string to escape
  1254 	 * @param string $string to escape
  1183 	 */
  1255 	 */
  1184 	public function escape_by_ref( &$string ) {
  1256 	public function escape_by_ref( &$string ) {
  1185 		if ( ! is_float( $string ) )
  1257 		if ( ! is_float( $string ) ) {
  1186 			$string = $this->_real_escape( $string );
  1258 			$string = $this->_real_escape( $string );
       
  1259 		}
  1187 	}
  1260 	}
  1188 
  1261 
  1189 	/**
  1262 	/**
  1190 	 * Prepares a SQL query for safe execution. Uses sprintf()-like syntax.
  1263 	 * Prepares a SQL query for safe execution. Uses sprintf()-like syntax.
  1191 	 *
  1264 	 *
  1199 	 * For compatibility with old behavior, numbered or formatted string placeholders (eg, %1$s, %5s) will not have quotes
  1272 	 * For compatibility with old behavior, numbered or formatted string placeholders (eg, %1$s, %5s) will not have quotes
  1200 	 * added by this function, so should be passed with appropriate quotes around them for your usage.
  1273 	 * added by this function, so should be passed with appropriate quotes around them for your usage.
  1201 	 *
  1274 	 *
  1202 	 * Literal percentage signs (%) in the query string must be written as %%. Percentage wildcards (for example,
  1275 	 * Literal percentage signs (%) in the query string must be written as %%. Percentage wildcards (for example,
  1203 	 * to use in LIKE syntax) must be passed via a substitution argument containing the complete LIKE string, these
  1276 	 * to use in LIKE syntax) must be passed via a substitution argument containing the complete LIKE string, these
  1204 	 * cannot be inserted directly in the query string. Also see {@see esc_like()}.
  1277 	 * cannot be inserted directly in the query string. Also see wpdb::esc_like().
  1205 	 *
  1278 	 *
  1206 	 * Arguments may be passed as individual arguments to the method, or as a single array containing all arguments. A combination
  1279 	 * Arguments may be passed as individual arguments to the method, or as a single array containing all arguments. A combination
  1207 	 * of the two is not supported.
  1280 	 * of the two is not supported.
  1208 	 *
  1281 	 *
  1209 	 * Examples:
  1282 	 * Examples:
  1235 
  1308 
  1236 		// If args were passed as an array (as in vsprintf), move them up.
  1309 		// If args were passed as an array (as in vsprintf), move them up.
  1237 		$passed_as_array = false;
  1310 		$passed_as_array = false;
  1238 		if ( is_array( $args[0] ) && count( $args ) == 1 ) {
  1311 		if ( is_array( $args[0] ) && count( $args ) == 1 ) {
  1239 			$passed_as_array = true;
  1312 			$passed_as_array = true;
  1240 			$args = $args[0];
  1313 			$args            = $args[0];
  1241 		}
  1314 		}
  1242 
  1315 
  1243 		foreach ( $args as $arg ) {
  1316 		foreach ( $args as $arg ) {
  1244 			if ( ! is_scalar( $arg ) && ! is_null( $arg ) ) {
  1317 			if ( ! is_scalar( $arg ) && ! is_null( $arg ) ) {
  1245 				wp_load_translations_early();
  1318 				wp_load_translations_early();
  1260 
  1333 
  1261 		/*
  1334 		/*
  1262 		 * If a %s placeholder already has quotes around it, removing the existing quotes and re-inserting them
  1335 		 * If a %s placeholder already has quotes around it, removing the existing quotes and re-inserting them
  1263 		 * ensures the quotes are consistent.
  1336 		 * ensures the quotes are consistent.
  1264 		 *
  1337 		 *
  1265 		 * For backwards compatibility, this is only applied to %s, and not to placeholders like %1$s, which are frequently
  1338 		 * For backward 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.
  1339 		 * used in the middle of longer strings, or as table name placeholders.
  1267 		 */
  1340 		 */
  1268 		$query = str_replace( "'%s'", '%s', $query ); // Strip any existing single quotes.
  1341 		$query = str_replace( "'%s'", '%s', $query ); // Strip any existing single quotes.
  1269 		$query = str_replace( '"%s"', '%s', $query ); // Strip any existing double quotes.
  1342 		$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.
  1343 		$query = preg_replace( '/(?<!%)%s/', "'%s'", $query ); // Quote the strings, avoiding escaped strings like %%s.
  1271 
  1344 
  1272 		$query = preg_replace( "/(?<!%)(%($allowed_format)?f)/" , '%\\2F', $query ); // Force floats to be locale unaware.
  1345 		$query = preg_replace( "/(?<!%)(%($allowed_format)?f)/", '%\\2F', $query ); // Force floats to be locale unaware.
  1273 
  1346 
  1274 		$query = preg_replace( "/%(?:%|$|(?!($allowed_format)?[sdF]))/", '%%\\1', $query ); // Escape any unescaped percents.
  1347 		$query = preg_replace( "/%(?:%|$|(?!($allowed_format)?[sdF]))/", '%%\\1', $query ); // Escape any unescaped percents.
  1275 
  1348 
  1276 		// Count the number of valid placeholders in the query.
  1349 		// Count the number of valid placeholders in the query.
  1277 		$placeholders = preg_match_all( "/(^|[^%]|(%%)+)%($allowed_format)?[sdF]/", $query, $matches );
  1350 		$placeholders = preg_match_all( "/(^|[^%]|(%%)+)%($allowed_format)?[sdF]/", $query, $matches );
  1287 				/*
  1360 				/*
  1288 				 * If we don't have the right number of placeholders, but they were passed as individual arguments,
  1361 				 * 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.
  1362 				 * or we were expecting multiple arguments in an array, throw a warning.
  1290 				 */
  1363 				 */
  1291 				wp_load_translations_early();
  1364 				wp_load_translations_early();
  1292 				_doing_it_wrong( 'wpdb::prepare',
  1365 				_doing_it_wrong(
       
  1366 					'wpdb::prepare',
  1293 					/* translators: 1: number of placeholders, 2: number of arguments passed */
  1367 					/* 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).' ),
  1368 					sprintf(
       
  1369 						__( 'The query does not contain the correct number of placeholders (%1$d) for the number of arguments passed (%2$d).' ),
  1295 						$placeholders,
  1370 						$placeholders,
  1296 						count( $args ) ),
  1371 						count( $args )
       
  1372 					),
  1297 					'4.8.3'
  1373 					'4.8.3'
  1298 				);
  1374 				);
  1299 			}
  1375 			}
  1300 		}
  1376 		}
  1301 
  1377 
  1342 	 * @return false|void False if the showing of errors is disabled.
  1418 	 * @return false|void False if the showing of errors is disabled.
  1343 	 */
  1419 	 */
  1344 	public function print_error( $str = '' ) {
  1420 	public function print_error( $str = '' ) {
  1345 		global $EZSQL_ERROR;
  1421 		global $EZSQL_ERROR;
  1346 
  1422 
  1347 		if ( !$str ) {
  1423 		if ( ! $str ) {
  1348 			if ( $this->use_mysqli ) {
  1424 			if ( $this->use_mysqli ) {
  1349 				$str = mysqli_error( $this->dbh );
  1425 				$str = mysqli_error( $this->dbh );
  1350 			} else {
  1426 			} else {
  1351 				$str = mysql_error( $this->dbh );
  1427 				$str = mysql_error( $this->dbh );
  1352 			}
  1428 			}
  1353 		}
  1429 		}
  1354 		$EZSQL_ERROR[] = array( 'query' => $this->last_query, 'error_str' => $str );
  1430 		$EZSQL_ERROR[] = array(
  1355 
  1431 			'query'     => $this->last_query,
  1356 		if ( $this->suppress_errors )
  1432 			'error_str' => $str,
       
  1433 		);
       
  1434 
       
  1435 		if ( $this->suppress_errors ) {
  1357 			return false;
  1436 			return false;
       
  1437 		}
  1358 
  1438 
  1359 		wp_load_translations_early();
  1439 		wp_load_translations_early();
  1360 
  1440 
  1361 		if ( $caller = $this->get_caller() ) {
  1441 		if ( $caller = $this->get_caller() ) {
  1362 			/* translators: 1: Database error message, 2: SQL query, 3: Name of the calling function */
  1442 			/* translators: 1: Database error message, 2: SQL query, 3: Name of the calling function */
  1367 		}
  1447 		}
  1368 
  1448 
  1369 		error_log( $error_str );
  1449 		error_log( $error_str );
  1370 
  1450 
  1371 		// Are we showing errors?
  1451 		// Are we showing errors?
  1372 		if ( ! $this->show_errors )
  1452 		if ( ! $this->show_errors ) {
  1373 			return false;
  1453 			return false;
       
  1454 		}
  1374 
  1455 
  1375 		// If there is an error then take note of it
  1456 		// If there is an error then take note of it
  1376 		if ( is_multisite() ) {
  1457 		if ( is_multisite() ) {
  1377 			$msg = sprintf(
  1458 			$msg = sprintf(
  1378 				"%s [%s]\n%s\n",
  1459 				"%s [%s]\n%s\n",
  1413 	 *
  1494 	 *
  1414 	 * @param bool $show Whether to show or hide errors
  1495 	 * @param bool $show Whether to show or hide errors
  1415 	 * @return bool Old value for showing errors.
  1496 	 * @return bool Old value for showing errors.
  1416 	 */
  1497 	 */
  1417 	public function show_errors( $show = true ) {
  1498 	public function show_errors( $show = true ) {
  1418 		$errors = $this->show_errors;
  1499 		$errors            = $this->show_errors;
  1419 		$this->show_errors = $show;
  1500 		$this->show_errors = $show;
  1420 		return $errors;
  1501 		return $errors;
  1421 	}
  1502 	}
  1422 
  1503 
  1423 	/**
  1504 	/**
  1429 	 * @see wpdb::show_errors()
  1510 	 * @see wpdb::show_errors()
  1430 	 *
  1511 	 *
  1431 	 * @return bool Whether showing of errors was active
  1512 	 * @return bool Whether showing of errors was active
  1432 	 */
  1513 	 */
  1433 	public function hide_errors() {
  1514 	public function hide_errors() {
  1434 		$show = $this->show_errors;
  1515 		$show              = $this->show_errors;
  1435 		$this->show_errors = false;
  1516 		$this->show_errors = false;
  1436 		return $show;
  1517 		return $show;
  1437 	}
  1518 	}
  1438 
  1519 
  1439 	/**
  1520 	/**
  1446 	 * @see wpdb::hide_errors()
  1527 	 * @see wpdb::hide_errors()
  1447 	 * @param bool $suppress Optional. New value. Defaults to true.
  1528 	 * @param bool $suppress Optional. New value. Defaults to true.
  1448 	 * @return bool Old value
  1529 	 * @return bool Old value
  1449 	 */
  1530 	 */
  1450 	public function suppress_errors( $suppress = true ) {
  1531 	public function suppress_errors( $suppress = true ) {
  1451 		$errors = $this->suppress_errors;
  1532 		$errors                = $this->suppress_errors;
  1452 		$this->suppress_errors = (bool) $suppress;
  1533 		$this->suppress_errors = (bool) $suppress;
  1453 		return $errors;
  1534 		return $errors;
  1454 	}
  1535 	}
  1455 
  1536 
  1456 	/**
  1537 	/**
  1457 	 * Kill cached query results.
  1538 	 * Kill cached query results.
  1458 	 *
  1539 	 *
  1459 	 * @since 0.71
  1540 	 * @since 0.71
  1460 	 */
  1541 	 */
  1461 	public function flush() {
  1542 	public function flush() {
  1462 		$this->last_result = array();
  1543 		$this->last_result   = array();
  1463 		$this->col_info    = null;
  1544 		$this->col_info      = null;
  1464 		$this->last_query  = null;
  1545 		$this->last_query    = null;
  1465 		$this->rows_affected = $this->num_rows = 0;
  1546 		$this->rows_affected = $this->num_rows = 0;
  1466 		$this->last_error  = '';
  1547 		$this->last_error    = '';
  1467 
  1548 
  1468 		if ( $this->use_mysqli && $this->result instanceof mysqli_result ) {
  1549 		if ( $this->use_mysqli && $this->result instanceof mysqli_result ) {
  1469 			mysqli_free_result( $this->result );
  1550 			mysqli_free_result( $this->result );
  1470 			$this->result = null;
  1551 			$this->result = null;
  1471 
  1552 
  1472 			// Sanity check before using the handle
  1553 			// Sanity check before using the handle
  1473 			if ( empty( $this->dbh ) || !( $this->dbh instanceof mysqli ) ) {
  1554 			if ( empty( $this->dbh ) || ! ( $this->dbh instanceof mysqli ) ) {
  1474 				return;
  1555 				return;
  1475 			}
  1556 			}
  1476 
  1557 
  1477 			// Clear out any results from a multi-query
  1558 			// Clear out any results from a multi-query
  1478 			while ( mysqli_more_results( $this->dbh ) ) {
  1559 			while ( mysqli_more_results( $this->dbh ) ) {
  1500 
  1581 
  1501 		/*
  1582 		/*
  1502 		 * Deprecated in 3.9+ when using MySQLi. No equivalent
  1583 		 * Deprecated in 3.9+ when using MySQLi. No equivalent
  1503 		 * $new_link parameter exists for mysqli_* functions.
  1584 		 * $new_link parameter exists for mysqli_* functions.
  1504 		 */
  1585 		 */
  1505 		$new_link = defined( 'MYSQL_NEW_LINK' ) ? MYSQL_NEW_LINK : true;
  1586 		$new_link     = defined( 'MYSQL_NEW_LINK' ) ? MYSQL_NEW_LINK : true;
  1506 		$client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0;
  1587 		$client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0;
  1507 
  1588 
  1508 		if ( $this->use_mysqli ) {
  1589 		if ( $this->use_mysqli ) {
  1509 			$this->dbh = mysqli_init();
  1590 			$this->dbh = mysqli_init();
  1510 
  1591 
  1536 			if ( $this->dbh->connect_errno ) {
  1617 			if ( $this->dbh->connect_errno ) {
  1537 				$this->dbh = null;
  1618 				$this->dbh = null;
  1538 
  1619 
  1539 				/*
  1620 				/*
  1540 				 * It's possible ext/mysqli is misconfigured. Fall back to ext/mysql if:
  1621 				 * It's possible ext/mysqli is misconfigured. Fall back to ext/mysql if:
  1541 		 		 *  - We haven't previously connected, and
  1622 				  *  - We haven't previously connected, and
  1542 		 		 *  - WP_USE_EXT_MYSQL isn't set to false, and
  1623 				  *  - WP_USE_EXT_MYSQL isn't set to false, and
  1543 		 		 *  - ext/mysql is loaded.
  1624 				  *  - ext/mysql is loaded.
  1544 		 		 */
  1625 				  */
  1545 				$attempt_fallback = true;
  1626 				$attempt_fallback = true;
  1546 
  1627 
  1547 				if ( $this->has_connected ) {
  1628 				if ( $this->has_connected ) {
  1548 					$attempt_fallback = false;
  1629 					$attempt_fallback = false;
  1549 				} elseif ( defined( 'WP_USE_EXT_MYSQL' ) && ! WP_USE_EXT_MYSQL ) {
  1630 				} elseif ( defined( 'WP_USE_EXT_MYSQL' ) && ! WP_USE_EXT_MYSQL ) {
  1575 			}
  1656 			}
  1576 
  1657 
  1577 			$message = '<h1>' . __( 'Error establishing a database connection' ) . "</h1>\n";
  1658 			$message = '<h1>' . __( 'Error establishing a database connection' ) . "</h1>\n";
  1578 
  1659 
  1579 			$message .= '<p>' . sprintf(
  1660 			$message .= '<p>' . sprintf(
  1580 				/* translators: 1: wp-config.php. 2: database host */
  1661 				/* translators: 1: wp-config.php, 2: database host */
  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.' ),
  1662 				__( '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.' ),
  1582 				'<code>wp-config.php</code>',
  1663 				'<code>wp-config.php</code>',
  1583 				'<code>' . htmlspecialchars( $this->dbhost, ENT_QUOTES ) . '</code>'
  1664 				'<code>' . htmlspecialchars( $this->dbhost, ENT_QUOTES ) . '</code>'
  1584 			) . "</p>\n";
  1665 			) . "</p>\n";
  1585 
  1666 
  1590 			$message .= "</ul>\n";
  1671 			$message .= "</ul>\n";
  1591 
  1672 
  1592 			$message .= '<p>' . sprintf(
  1673 			$message .= '<p>' . sprintf(
  1593 				/* translators: %s: support forums URL */
  1674 				/* 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>.' ),
  1675 				__( '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/' )
  1676 				__( 'https://wordpress.org/support/forums/' )
  1596 			) . "</p>\n";
  1677 			) . "</p>\n";
  1597 
  1678 
  1598 			$this->bail( $message, 'db_connect_fail' );
  1679 			$this->bail( $message, 'db_connect_fail' );
  1599 
  1680 
  1600 			return false;
  1681 			return false;
  1638 
  1719 
  1639 		// First peel off the socket parameter from the right, if it exists.
  1720 		// First peel off the socket parameter from the right, if it exists.
  1640 		$socket_pos = strpos( $host, ':/' );
  1721 		$socket_pos = strpos( $host, ':/' );
  1641 		if ( $socket_pos !== false ) {
  1722 		if ( $socket_pos !== false ) {
  1642 			$socket = substr( $host, $socket_pos + 1 );
  1723 			$socket = substr( $host, $socket_pos + 1 );
  1643 			$host = substr( $host, 0, $socket_pos );
  1724 			$host   = substr( $host, 0, $socket_pos );
  1644 		}
  1725 		}
  1645 
  1726 
  1646 		// We need to check for an IPv6 address first.
  1727 		// We need to check for an IPv6 address first.
  1647 		// An IPv6 address will always contain at least two colons.
  1728 		// An IPv6 address will always contain at least two colons.
  1648 		if ( substr_count( $host, ':' ) > 1 ) {
  1729 		if ( substr_count( $host, ':' ) > 1 ) {
  1652 			// We seem to be dealing with an IPv4 address.
  1733 			// We seem to be dealing with an IPv4 address.
  1653 			$pattern = '#^(?P<host>[^:/]*)(?::(?P<port>[\d]+))?#';
  1734 			$pattern = '#^(?P<host>[^:/]*)(?::(?P<port>[\d]+))?#';
  1654 		}
  1735 		}
  1655 
  1736 
  1656 		$matches = array();
  1737 		$matches = array();
  1657 		$result = preg_match( $pattern, $host, $matches );
  1738 		$result  = preg_match( $pattern, $host, $matches );
  1658 
  1739 
  1659 		if ( 1 !== $result ) {
  1740 		if ( 1 !== $result ) {
  1660 			// Couldn't parse the address, bail.
  1741 			// Couldn't parse the address, bail.
  1661 			return false;
  1742 			return false;
  1662 		}
  1743 		}
  1748 		$message .= "</ul>\n";
  1829 		$message .= "</ul>\n";
  1749 
  1830 
  1750 		$message .= '<p>' . sprintf(
  1831 		$message .= '<p>' . sprintf(
  1751 			/* translators: %s: support forums URL */
  1832 			/* 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>.' ),
  1833 			__( '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/' )
  1834 			__( 'https://wordpress.org/support/forums/' )
  1754 		) . "</p>\n";
  1835 		) . "</p>\n";
  1755 
  1836 
  1756 		// We weren't able to reconnect, so we better bail.
  1837 		// We weren't able to reconnect, so we better bail.
  1757 		$this->bail( $message, 'db_connect_fail' );
  1838 		$this->bail( $message, 'db_connect_fail' );
  1758 
  1839 
  1766 	 * More information can be found on the codex page.
  1847 	 * More information can be found on the codex page.
  1767 	 *
  1848 	 *
  1768 	 * @since 0.71
  1849 	 * @since 0.71
  1769 	 *
  1850 	 *
  1770 	 * @param string $query Database query
  1851 	 * @param string $query Database query
  1771 	 * @return int|false Number of rows affected/selected or false on error
  1852 	 * @return int|bool Boolean true for CREATE, ALTER, TRUNCATE and DROP queries. Number of rows
       
  1853 	 *                  affected/selected for all other queries. Boolean false on error.
  1772 	 */
  1854 	 */
  1773 	public function query( $query ) {
  1855 	public function query( $query ) {
  1774 		if ( ! $this->ready ) {
  1856 		if ( ! $this->ready ) {
  1775 			$this->check_current_query = true;
  1857 			$this->check_current_query = true;
  1776 			return false;
  1858 			return false;
  1856 			}
  1938 			}
  1857 		}
  1939 		}
  1858 
  1940 
  1859 		if ( $this->last_error ) {
  1941 		if ( $this->last_error ) {
  1860 			// Clear insert_id on a subsequent failed insert.
  1942 			// Clear insert_id on a subsequent failed insert.
  1861 			if ( $this->insert_id && preg_match( '/^\s*(insert|replace)\s/i', $query ) )
  1943 			if ( $this->insert_id && preg_match( '/^\s*(insert|replace)\s/i', $query ) ) {
  1862 				$this->insert_id = 0;
  1944 				$this->insert_id = 0;
       
  1945 			}
  1863 
  1946 
  1864 			$this->print_error();
  1947 			$this->print_error();
  1865 			return false;
  1948 			return false;
  1866 		}
  1949 		}
  1867 
  1950 
  1885 			$return_val = $this->rows_affected;
  1968 			$return_val = $this->rows_affected;
  1886 		} else {
  1969 		} else {
  1887 			$num_rows = 0;
  1970 			$num_rows = 0;
  1888 			if ( $this->use_mysqli && $this->result instanceof mysqli_result ) {
  1971 			if ( $this->use_mysqli && $this->result instanceof mysqli_result ) {
  1889 				while ( $row = mysqli_fetch_object( $this->result ) ) {
  1972 				while ( $row = mysqli_fetch_object( $this->result ) ) {
  1890 					$this->last_result[$num_rows] = $row;
  1973 					$this->last_result[ $num_rows ] = $row;
  1891 					$num_rows++;
  1974 					$num_rows++;
  1892 				}
  1975 				}
  1893 			} elseif ( is_resource( $this->result ) ) {
  1976 			} elseif ( is_resource( $this->result ) ) {
  1894 				while ( $row = mysql_fetch_object( $this->result ) ) {
  1977 				while ( $row = mysql_fetch_object( $this->result ) ) {
  1895 					$this->last_result[$num_rows] = $row;
  1978 					$this->last_result[ $num_rows ] = $row;
  1896 					$num_rows++;
  1979 					$num_rows++;
  1897 				}
  1980 				}
  1898 			}
  1981 			}
  1899 
  1982 
  1900 			// Log number of rows the query returned
  1983 			// Log number of rows the query returned
  1926 			$this->result = mysql_query( $query, $this->dbh );
  2009 			$this->result = mysql_query( $query, $this->dbh );
  1927 		}
  2010 		}
  1928 		$this->num_queries++;
  2011 		$this->num_queries++;
  1929 
  2012 
  1930 		if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
  2013 		if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
  1931 			$this->queries[] = array( $query, $this->timer_stop(), $this->get_caller() );
  2014 			$this->queries[] = array(
       
  2015 				$query,
       
  2016 				$this->timer_stop(),
       
  2017 				$this->get_caller(),
       
  2018 				$this->time_start,
       
  2019 			);
  1932 		}
  2020 		}
  1933 	}
  2021 	}
  1934 
  2022 
  1935 	/**
  2023 	/**
  1936 	 * Generates and returns a placeholder escape string for use in queries returned by ::prepare().
  2024 	 * Generates and returns a placeholder escape string for use in queries returned by ::prepare().
  1951 			$placeholder = '{' . hash_hmac( $algo, uniqid( $salt, true ), $salt ) . '}';
  2039 			$placeholder = '{' . hash_hmac( $algo, uniqid( $salt, true ), $salt ) . '}';
  1952 		}
  2040 		}
  1953 
  2041 
  1954 		/*
  2042 		/*
  1955 		 * Add the filter to remove the placeholder escaper. Uses priority 0, so that anything
  2043 		 * 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.
  2044 		 * else attached to this filter will receive the query with the placeholder string removed.
  1957 		 */
  2045 		 */
  1958 		if ( ! has_filter( 'query', array( $this, 'remove_placeholder_escape' ) ) ) {
  2046 		if ( ! has_filter( 'query', array( $this, 'remove_placeholder_escape' ) ) ) {
  1959 			add_filter( 'query', array( $this, 'remove_placeholder_escape' ), 0 );
  2047 			add_filter( 'query', array( $this, 'remove_placeholder_escape' ), 0 );
  1960 		}
  2048 		}
  1961 
  2049 
  2152 				$conditions[] = "`$field` IS NULL";
  2240 				$conditions[] = "`$field` IS NULL";
  2153 				continue;
  2241 				continue;
  2154 			}
  2242 			}
  2155 
  2243 
  2156 			$conditions[] = "`$field` = " . $value['format'];
  2244 			$conditions[] = "`$field` = " . $value['format'];
  2157 			$values[] = $value['value'];
  2245 			$values[]     = $value['value'];
  2158 		}
  2246 		}
  2159 
  2247 
  2160 		$fields = implode( ', ', $fields );
  2248 		$fields     = implode( ', ', $fields );
  2161 		$conditions = implode( ' AND ', $conditions );
  2249 		$conditions = implode( ' AND ', $conditions );
  2162 
  2250 
  2163 		$sql = "UPDATE `$table` SET $fields WHERE $conditions";
  2251 		$sql = "UPDATE `$table` SET $fields WHERE $conditions";
  2164 
  2252 
  2165 		$this->check_current_query = false;
  2253 		$this->check_current_query = false;
  2204 				$conditions[] = "`$field` IS NULL";
  2292 				$conditions[] = "`$field` IS NULL";
  2205 				continue;
  2293 				continue;
  2206 			}
  2294 			}
  2207 
  2295 
  2208 			$conditions[] = "`$field` = " . $value['format'];
  2296 			$conditions[] = "`$field` = " . $value['format'];
  2209 			$values[] = $value['value'];
  2297 			$values[]     = $value['value'];
  2210 		}
  2298 		}
  2211 
  2299 
  2212 		$conditions = implode( ' AND ', $conditions );
  2300 		$conditions = implode( ' AND ', $conditions );
  2213 
  2301 
  2214 		$sql = "DELETE FROM `$table` WHERE $conditions";
  2302 		$sql = "DELETE FROM `$table` WHERE $conditions";
  2379 		if ( $query ) {
  2467 		if ( $query ) {
  2380 			$this->query( $query );
  2468 			$this->query( $query );
  2381 		}
  2469 		}
  2382 
  2470 
  2383 		// Extract var out of cached results based x,y vals
  2471 		// Extract var out of cached results based x,y vals
  2384 		if ( !empty( $this->last_result[$y] ) ) {
  2472 		if ( ! empty( $this->last_result[ $y ] ) ) {
  2385 			$values = array_values( get_object_vars( $this->last_result[$y] ) );
  2473 			$values = array_values( get_object_vars( $this->last_result[ $y ] ) );
  2386 		}
  2474 		}
  2387 
  2475 
  2388 		// If there is a value return it else return null
  2476 		// If there is a value return it else return null
  2389 		return ( isset( $values[$x] ) && $values[$x] !== '' ) ? $values[$x] : null;
  2477 		return ( isset( $values[ $x ] ) && $values[ $x ] !== '' ) ? $values[ $x ] : null;
  2390 	}
  2478 	}
  2391 
  2479 
  2392 	/**
  2480 	/**
  2393 	 * Retrieve one row from the database.
  2481 	 * Retrieve one row from the database.
  2394 	 *
  2482 	 *
  2413 			$this->query( $query );
  2501 			$this->query( $query );
  2414 		} else {
  2502 		} else {
  2415 			return null;
  2503 			return null;
  2416 		}
  2504 		}
  2417 
  2505 
  2418 		if ( !isset( $this->last_result[$y] ) )
  2506 		if ( ! isset( $this->last_result[ $y ] ) ) {
  2419 			return null;
  2507 			return null;
       
  2508 		}
  2420 
  2509 
  2421 		if ( $output == OBJECT ) {
  2510 		if ( $output == OBJECT ) {
  2422 			return $this->last_result[$y] ? $this->last_result[$y] : null;
  2511 			return $this->last_result[ $y ] ? $this->last_result[ $y ] : null;
  2423 		} elseif ( $output == ARRAY_A ) {
  2512 		} elseif ( $output == ARRAY_A ) {
  2424 			return $this->last_result[$y] ? get_object_vars( $this->last_result[$y] ) : null;
  2513 			return $this->last_result[ $y ] ? get_object_vars( $this->last_result[ $y ] ) : null;
  2425 		} elseif ( $output == ARRAY_N ) {
  2514 		} elseif ( $output == ARRAY_N ) {
  2426 			return $this->last_result[$y] ? array_values( get_object_vars( $this->last_result[$y] ) ) : null;
  2515 			return $this->last_result[ $y ] ? array_values( get_object_vars( $this->last_result[ $y ] ) ) : null;
  2427 		} elseif ( strtoupper( $output ) === OBJECT ) {
  2516 		} elseif ( strtoupper( $output ) === OBJECT ) {
  2428 			// Back compat for OBJECT being previously case insensitive.
  2517 			// Back compat for OBJECT being previously case insensitive.
  2429 			return $this->last_result[$y] ? $this->last_result[$y] : null;
  2518 			return $this->last_result[ $y ] ? $this->last_result[ $y ] : null;
  2430 		} else {
  2519 		} else {
  2431 			$this->print_error( " \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N" );
  2520 			$this->print_error( ' $db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N' );
  2432 		}
  2521 		}
  2433 	}
  2522 	}
  2434 
  2523 
  2435 	/**
  2524 	/**
  2436 	 * Retrieve one column from the database.
  2525 	 * Retrieve one column from the database.
  2443 	 *
  2532 	 *
  2444 	 * @param string|null $query Optional. SQL query. Defaults to previous query.
  2533 	 * @param string|null $query Optional. SQL query. Defaults to previous query.
  2445 	 * @param int         $x     Optional. Column to return. Indexed from 0.
  2534 	 * @param int         $x     Optional. Column to return. Indexed from 0.
  2446 	 * @return array Database query result. Array indexed from 0 by SQL result row number.
  2535 	 * @return array Database query result. Array indexed from 0 by SQL result row number.
  2447 	 */
  2536 	 */
  2448 	public function get_col( $query = null , $x = 0 ) {
  2537 	public function get_col( $query = null, $x = 0 ) {
  2449 		if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
  2538 		if ( $this->check_current_query && $this->check_safe_collation( $query ) ) {
  2450 			$this->check_current_query = false;
  2539 			$this->check_current_query = false;
  2451 		}
  2540 		}
  2452 
  2541 
  2453 		if ( $query ) {
  2542 		if ( $query ) {
  2454 			$this->query( $query );
  2543 			$this->query( $query );
  2455 		}
  2544 		}
  2456 
  2545 
  2457 		$new_array = array();
  2546 		$new_array = array();
  2458 		// Extract the column values
  2547 		// Extract the column values
  2459 		for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) {
  2548 		if ( $this->last_result ) {
  2460 			$new_array[$i] = $this->get_var( null, $x, $i );
  2549 			for ( $i = 0, $j = count( $this->last_result ); $i < $j; $i++ ) {
       
  2550 				$new_array[ $i ] = $this->get_var( null, $x, $i );
       
  2551 			}
  2461 		}
  2552 		}
  2462 		return $new_array;
  2553 		return $new_array;
  2463 	}
  2554 	}
  2464 
  2555 
  2465 	/**
  2556 	/**
  2495 			// Return an integer-keyed array of row objects
  2586 			// Return an integer-keyed array of row objects
  2496 			return $this->last_result;
  2587 			return $this->last_result;
  2497 		} elseif ( $output == OBJECT_K ) {
  2588 		} elseif ( $output == OBJECT_K ) {
  2498 			// Return an array of row objects with keys from column 1
  2589 			// Return an array of row objects with keys from column 1
  2499 			// (Duplicates are discarded)
  2590 			// (Duplicates are discarded)
  2500 			foreach ( $this->last_result as $row ) {
  2591 			if ( $this->last_result ) {
  2501 				$var_by_ref = get_object_vars( $row );
  2592 				foreach ( $this->last_result as $row ) {
  2502 				$key = array_shift( $var_by_ref );
  2593 					$var_by_ref = get_object_vars( $row );
  2503 				if ( ! isset( $new_array[ $key ] ) )
  2594 					$key        = array_shift( $var_by_ref );
  2504 					$new_array[ $key ] = $row;
  2595 					if ( ! isset( $new_array[ $key ] ) ) {
       
  2596 						$new_array[ $key ] = $row;
       
  2597 					}
       
  2598 				}
  2505 			}
  2599 			}
  2506 			return $new_array;
  2600 			return $new_array;
  2507 		} elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
  2601 		} elseif ( $output == ARRAY_A || $output == ARRAY_N ) {
  2508 			// Return an integer-keyed array of...
  2602 			// Return an integer-keyed array of...
  2509 			if ( $this->last_result ) {
  2603 			if ( $this->last_result ) {
  2557 		}
  2651 		}
  2558 
  2652 
  2559 		$charsets = $columns = array();
  2653 		$charsets = $columns = array();
  2560 
  2654 
  2561 		$table_parts = explode( '.', $table );
  2655 		$table_parts = explode( '.', $table );
  2562 		$table = '`' . implode( '`.`', $table_parts ) . '`';
  2656 		$table       = '`' . implode( '`.`', $table_parts ) . '`';
  2563 		$results = $this->get_results( "SHOW FULL COLUMNS FROM $table" );
  2657 		$results     = $this->get_results( "SHOW FULL COLUMNS FROM $table" );
  2564 		if ( ! $results ) {
  2658 		if ( ! $results ) {
  2565 			return new WP_Error( 'wpdb_get_table_charset_failure' );
  2659 			return new WP_Error( 'wpdb_get_table_charset_failure' );
  2566 		}
  2660 		}
  2567 
  2661 
  2568 		foreach ( $results as $column ) {
  2662 		foreach ( $results as $column ) {
  2634 	 * @param string $column Column name.
  2728 	 * @param string $column Column name.
  2635 	 * @return string|false|WP_Error Column character set as a string. False if the column has no
  2729 	 * @return string|false|WP_Error Column character set as a string. False if the column has no
  2636 	 *                               character set. WP_Error object if there was an error.
  2730 	 *                               character set. WP_Error object if there was an error.
  2637 	 */
  2731 	 */
  2638 	public function get_col_charset( $table, $column ) {
  2732 	public function get_col_charset( $table, $column ) {
  2639 		$tablekey = strtolower( $table );
  2733 		$tablekey  = strtolower( $table );
  2640 		$columnkey = strtolower( $column );
  2734 		$columnkey = strtolower( $column );
  2641 
  2735 
  2642 		/**
  2736 		/**
  2643 		 * Filters the column charset value before the DB is checked.
  2737 		 * Filters the column charset value before the DB is checked.
  2644 		 *
  2738 		 *
  2699 	 * @return array|false|WP_Error array( 'length' => (int), 'type' => 'byte' | 'char' )
  2793 	 * @return array|false|WP_Error array( 'length' => (int), 'type' => 'byte' | 'char' )
  2700 	 *                              false if the column has no length (for example, numeric column)
  2794 	 *                              false if the column has no length (for example, numeric column)
  2701 	 *                              WP_Error object if there was an error.
  2795 	 *                              WP_Error object if there was an error.
  2702 	 */
  2796 	 */
  2703 	public function get_col_length( $table, $column ) {
  2797 	public function get_col_length( $table, $column ) {
  2704 		$tablekey = strtolower( $table );
  2798 		$tablekey  = strtolower( $table );
  2705 		$columnkey = strtolower( $column );
  2799 		$columnkey = strtolower( $column );
  2706 
  2800 
  2707 		// Skip this entirely if this isn't a MySQL database.
  2801 		// Skip this entirely if this isn't a MySQL database.
  2708 		if ( empty( $this->is_mysql ) ) {
  2802 		if ( empty( $this->is_mysql ) ) {
  2709 			return false;
  2803 			return false;
  2728 			$length = trim( $typeinfo[1], ')' );
  2822 			$length = trim( $typeinfo[1], ')' );
  2729 		} else {
  2823 		} else {
  2730 			$length = false;
  2824 			$length = false;
  2731 		}
  2825 		}
  2732 
  2826 
  2733 		switch( $type ) {
  2827 		switch ( $type ) {
  2734 			case 'char':
  2828 			case 'char':
  2735 			case 'varchar':
  2829 			case 'varchar':
  2736 				return array(
  2830 				return array(
  2737 					'type'   => 'char',
  2831 					'type'   => 'char',
  2738 					'length' => (int) $length,
  2832 					'length' => (int) $length,
  2829 		if ( ! $table ) {
  2923 		if ( ! $table ) {
  2830 			return false;
  2924 			return false;
  2831 		}
  2925 		}
  2832 
  2926 
  2833 		$this->checking_collation = true;
  2927 		$this->checking_collation = true;
  2834 		$collation = $this->get_table_charset( $table );
  2928 		$collation                = $this->get_table_charset( $table );
  2835 		$this->checking_collation = false;
  2929 		$this->checking_collation = false;
  2836 
  2930 
  2837 		// Tables with no collation, or latin1 only, don't need extra checking.
  2931 		// Tables with no collation, or latin1 only, don't need extra checking.
  2838 		if ( false === $collation || 'latin1' === $collation ) {
  2932 		if ( false === $collation || 'latin1' === $collation ) {
  2839 			return true;
  2933 			return true;
  2876 
  2970 
  2877 		foreach ( $data as &$value ) {
  2971 		foreach ( $data as &$value ) {
  2878 			$charset = $value['charset'];
  2972 			$charset = $value['charset'];
  2879 
  2973 
  2880 			if ( is_array( $value['length'] ) ) {
  2974 			if ( is_array( $value['length'] ) ) {
  2881 				$length = $value['length']['length'];
  2975 				$length                  = $value['length']['length'];
  2882 				$truncate_by_byte_length = 'byte' === $value['length']['type'];
  2976 				$truncate_by_byte_length = 'byte' === $value['length']['type'];
  2883 			} else {
  2977 			} else {
  2884 				$length = false;
  2978 				$length = false;
  2885 				// Since we have no length, we'll never truncate.
  2979 				// Since we have no length, we'll never truncate.
  2886 				// Initialize the variable to false. true would take us
  2980 				// Initialize the variable to false. true would take us
  2905 			||
  2999 			||
  2906 				// ASCII is always OK.
  3000 				// ASCII is always OK.
  2907 				( ! isset( $value['ascii'] ) && $this->check_ascii( $value['value'] ) )
  3001 				( ! isset( $value['ascii'] ) && $this->check_ascii( $value['value'] ) )
  2908 			) {
  3002 			) {
  2909 				$truncate_by_byte_length = true;
  3003 				$truncate_by_byte_length = true;
  2910 				$needs_validation = false;
  3004 				$needs_validation        = false;
  2911 			}
  3005 			}
  2912 
  3006 
  2913 			if ( $truncate_by_byte_length ) {
  3007 			if ( $truncate_by_byte_length ) {
  2914 				mbstring_binary_safe_encoding();
  3008 				mbstring_binary_safe_encoding();
  2915 				if ( false !== $length && strlen( $value['value'] ) > $length ) {
  3009 				if ( false !== $length && strlen( $value['value'] ) > $length ) {
  2939 						|    [\xF1-\xF3][\x80-\xBF]{3}
  3033 						|    [\xF1-\xF3][\x80-\xBF]{3}
  2940 						|    \xF4[\x80-\x8F][\x80-\xBF]{2}
  3034 						|    \xF4[\x80-\x8F][\x80-\xBF]{2}
  2941 					';
  3035 					';
  2942 				}
  3036 				}
  2943 
  3037 
  2944 				$regex .= '){1,40}                          # ...one or more times
  3038 				$regex         .= '){1,40}                          # ...one or more times
  2945 					)
  3039 					)
  2946 					| .                                  # anything else
  3040 					| .                                  # anything else
  2947 					/x';
  3041 					/x';
  2948 				$value['value'] = preg_replace( $regex, '$1', $value['value'] );
  3042 				$value['value'] = preg_replace( $regex, '$1', $value['value'] );
  2949 
       
  2950 
  3043 
  2951 				if ( false !== $length && mb_strlen( $value['value'], 'UTF-8' ) > $length ) {
  3044 				if ( false !== $length && mb_strlen( $value['value'], 'UTF-8' ) > $length ) {
  2952 					$value['value'] = mb_substr( $value['value'], 0, $length, 'UTF-8' );
  3045 					$value['value'] = mb_substr( $value['value'], 0, $length, 'UTF-8' );
  2953 				}
  3046 				}
  2954 				continue;
  3047 				continue;
  2980 							$connection_charset = mysql_client_encoding();
  3073 							$connection_charset = mysql_client_encoding();
  2981 						}
  3074 						}
  2982 					}
  3075 					}
  2983 
  3076 
  2984 					if ( is_array( $value['length'] ) ) {
  3077 					if ( is_array( $value['length'] ) ) {
  2985 						$length = sprintf( '%.0f', $value['length']['length'] );
  3078 						$length          = sprintf( '%.0f', $value['length']['length'] );
  2986 						$queries[ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING $charset ), $length ) USING $connection_charset )", $value['value'] );
  3079 						$queries[ $col ] = $this->prepare( "CONVERT( LEFT( CONVERT( %s USING $charset ), $length ) USING $connection_charset )", $value['value'] );
  2987 					} else if ( 'binary' !== $charset ) {
  3080 					} elseif ( 'binary' !== $charset ) {
  2988 						// If we don't have a length, there's no need to convert binary - it will always return the same result.
  3081 						// 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'] );
  3082 						$queries[ $col ] = $this->prepare( "CONVERT( CONVERT( %s USING $charset ) USING $connection_charset )", $value['value'] );
  2990 					}
  3083 					}
  2991 
  3084 
  2992 					unset( $data[ $col ]['db'] );
  3085 					unset( $data[ $col ]['db'] );
  3001 
  3094 
  3002 				$sql[] = $query . " AS x_$column";
  3095 				$sql[] = $query . " AS x_$column";
  3003 			}
  3096 			}
  3004 
  3097 
  3005 			$this->check_current_query = false;
  3098 			$this->check_current_query = false;
  3006 			$row = $this->get_row( "SELECT " . implode( ', ', $sql ), ARRAY_A );
  3099 			$row                       = $this->get_row( 'SELECT ' . implode( ', ', $sql ), ARRAY_A );
  3007 			if ( ! $row ) {
  3100 			if ( ! $row ) {
  3008 				return new WP_Error( 'wpdb_strip_invalid_text_failure' );
  3101 				return new WP_Error( 'wpdb_strip_invalid_text_failure' );
  3009 			}
  3102 			}
  3010 
  3103 
  3011 			foreach ( array_keys( $data ) as $column ) {
  3104 			foreach ( array_keys( $data ) as $column ) {
  3012 				if ( isset( $row["x_$column"] ) ) {
  3105 				if ( isset( $row[ "x_$column" ] ) ) {
  3013 					$data[ $column ]['value'] = $row["x_$column"];
  3106 					$data[ $column ]['value'] = $row[ "x_$column" ];
  3014 				}
  3107 				}
  3015 			}
  3108 			}
  3016 		}
  3109 		}
  3017 
  3110 
  3018 		return $data;
  3111 		return $data;
  3090 		$data = array(
  3183 		$data = array(
  3091 			$column => array(
  3184 			$column => array(
  3092 				'value'   => $value,
  3185 				'value'   => $value,
  3093 				'charset' => $charset,
  3186 				'charset' => $charset,
  3094 				'length'  => $this->get_col_length( $table, $column ),
  3187 				'length'  => $this->get_col_length( $table, $column ),
  3095 			)
  3188 			),
  3096 		);
  3189 		);
  3097 
  3190 
  3098 		$data = $this->strip_invalid_text( $data );
  3191 		$data = $this->strip_invalid_text( $data );
  3099 		if ( is_wp_error( $data ) ) {
  3192 		if ( is_wp_error( $data ) ) {
  3100 			return $data;
  3193 			return $data;
  3120 
  3213 
  3121 		// Strip everything between parentheses except nested selects.
  3214 		// Strip everything between parentheses except nested selects.
  3122 		$query = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', $query );
  3215 		$query = preg_replace( '/\((?!\s*select)[^(]*?\)/is', '()', $query );
  3123 
  3216 
  3124 		// Quickly match most common queries.
  3217 		// Quickly match most common queries.
  3125 		if ( preg_match( '/^\s*(?:'
  3218 		if ( preg_match(
       
  3219 			'/^\s*(?:'
  3126 				. 'SELECT.*?\s+FROM'
  3220 				. 'SELECT.*?\s+FROM'
  3127 				. '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?'
  3221 				. '|INSERT(?:\s+LOW_PRIORITY|\s+DELAYED|\s+HIGH_PRIORITY)?(?:\s+IGNORE)?(?:\s+INTO)?'
  3128 				. '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?'
  3222 				. '|REPLACE(?:\s+LOW_PRIORITY|\s+DELAYED)?(?:\s+INTO)?'
  3129 				. '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?'
  3223 				. '|UPDATE(?:\s+LOW_PRIORITY)?(?:\s+IGNORE)?'
  3130 				. '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:.+?FROM)?'
  3224 				. '|DELETE(?:\s+LOW_PRIORITY|\s+QUICK|\s+IGNORE)*(?:.+?FROM)?'
  3131 				. ')\s+((?:[0-9a-zA-Z$_.`-]|[\xC2-\xDF][\x80-\xBF])+)/is', $query, $maybe ) ) {
  3225 			. ')\s+((?:[0-9a-zA-Z$_.`-]|[\xC2-\xDF][\x80-\xBF])+)/is',
       
  3226 			$query,
       
  3227 			$maybe
       
  3228 		) ) {
  3132 			return str_replace( '`', '', $maybe[1] );
  3229 			return str_replace( '`', '', $maybe[1] );
  3133 		}
  3230 		}
  3134 
  3231 
  3135 		// SHOW TABLE STATUS and SHOW TABLES WHERE Name = 'wp_posts'
  3232 		// SHOW TABLE STATUS and SHOW TABLES WHERE Name = 'wp_posts'
  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 ) ) {
  3233 		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 ) ) {
  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 ) ) {
  3242 		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] );
  3243 			return str_replace( '\\_', '_', $maybe[2] );
  3147 		}
  3244 		}
  3148 
  3245 
  3149 		// Big pattern for the rest of the table-related queries.
  3246 		// Big pattern for the rest of the table-related queries.
  3150 		if ( preg_match( '/^\s*(?:'
  3247 		if ( preg_match(
       
  3248 			'/^\s*(?:'
  3151 				. '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM'
  3249 				. '(?:EXPLAIN\s+(?:EXTENDED\s+)?)?SELECT.*?\s+FROM'
  3152 				. '|DESCRIBE|DESC|EXPLAIN|HANDLER'
  3250 				. '|DESCRIBE|DESC|EXPLAIN|HANDLER'
  3153 				. '|(?:LOCK|UNLOCK)\s+TABLE(?:S)?'
  3251 				. '|(?:LOCK|UNLOCK)\s+TABLE(?:S)?'
  3154 				. '|(?:RENAME|OPTIMIZE|BACKUP|RESTORE|CHECK|CHECKSUM|ANALYZE|REPAIR).*\s+TABLE'
  3252 				. '|(?:RENAME|OPTIMIZE|BACKUP|RESTORE|CHECK|CHECKSUM|ANALYZE|REPAIR).*\s+TABLE'
  3155 				. '|TRUNCATE(?:\s+TABLE)?'
  3253 				. '|TRUNCATE(?:\s+TABLE)?'
  3159 				. '|CREATE(?:\s+\w+)?\s+INDEX.*\s+ON'
  3257 				. '|CREATE(?:\s+\w+)?\s+INDEX.*\s+ON'
  3160 				. '|DROP\s+INDEX.*\s+ON'
  3258 				. '|DROP\s+INDEX.*\s+ON'
  3161 				. '|LOAD\s+DATA.*INFILE.*INTO\s+TABLE'
  3259 				. '|LOAD\s+DATA.*INFILE.*INTO\s+TABLE'
  3162 				. '|(?:GRANT|REVOKE).*ON\s+TABLE'
  3260 				. '|(?:GRANT|REVOKE).*ON\s+TABLE'
  3163 				. '|SHOW\s+(?:.*FROM|.*TABLE)'
  3261 				. '|SHOW\s+(?:.*FROM|.*TABLE)'
  3164 				. ')\s+\(*\s*((?:[0-9a-zA-Z$_.`-]|[\xC2-\xDF][\x80-\xBF])+)\s*\)*/is', $query, $maybe ) ) {
  3262 			. ')\s+\(*\s*((?:[0-9a-zA-Z$_.`-]|[\xC2-\xDF][\x80-\xBF])+)\s*\)*/is',
       
  3263 			$query,
       
  3264 			$maybe
       
  3265 		) ) {
  3165 			return str_replace( '`', '', $maybe[1] );
  3266 			return str_replace( '`', '', $maybe[1] );
  3166 		}
  3267 		}
  3167 
  3268 
  3168 		return false;
  3269 		return false;
  3169 	}
  3270 	}
  3170 
  3271 
  3171 	/**
  3272 	/**
  3172 	 * Load the column metadata from the last query.
  3273 	 * Load the column metadata from the last query.
  3173 	 *
  3274 	 *
  3174 	 * @since 3.5.0
  3275 	 * @since 3.5.0
  3175 	 *
       
  3176 	 */
  3276 	 */
  3177 	protected function load_col_info() {
  3277 	protected function load_col_info() {
  3178 		if ( $this->col_info )
  3278 		if ( $this->col_info ) {
  3179 			return;
  3279 			return;
       
  3280 		}
  3180 
  3281 
  3181 		if ( $this->use_mysqli ) {
  3282 		if ( $this->use_mysqli ) {
  3182 			$num_fields = mysqli_num_fields( $this->result );
  3283 			$num_fields = mysqli_num_fields( $this->result );
  3183 			for ( $i = 0; $i < $num_fields; $i++ ) {
  3284 			for ( $i = 0; $i < $num_fields; $i++ ) {
  3184 				$this->col_info[ $i ] = mysqli_fetch_field( $this->result );
  3285 				$this->col_info[ $i ] = mysqli_fetch_field( $this->result );
  3203 	public function get_col_info( $info_type = 'name', $col_offset = -1 ) {
  3304 	public function get_col_info( $info_type = 'name', $col_offset = -1 ) {
  3204 		$this->load_col_info();
  3305 		$this->load_col_info();
  3205 
  3306 
  3206 		if ( $this->col_info ) {
  3307 		if ( $this->col_info ) {
  3207 			if ( $col_offset == -1 ) {
  3308 			if ( $col_offset == -1 ) {
  3208 				$i = 0;
  3309 				$i         = 0;
  3209 				$new_array = array();
  3310 				$new_array = array();
  3210 				foreach ( (array) $this->col_info as $col ) {
  3311 				foreach ( (array) $this->col_info as $col ) {
  3211 					$new_array[$i] = $col->{$info_type};
  3312 					$new_array[ $i ] = $col->{$info_type};
  3212 					$i++;
  3313 					$i++;
  3213 				}
  3314 				}
  3214 				return $new_array;
  3315 				return $new_array;
  3215 			} else {
  3316 			} else {
  3216 				return $this->col_info[$col_offset]->{$info_type};
  3317 				return $this->col_info[ $col_offset ]->{$info_type};
  3217 			}
  3318 			}
  3218 		}
  3319 		}
  3219 	}
  3320 	}
  3220 
  3321 
  3221 	/**
  3322 	/**
  3251 	 * @param string $message    The Error message
  3352 	 * @param string $message    The Error message
  3252 	 * @param string $error_code Optional. A Computer readable string to identify the error.
  3353 	 * @param string $error_code Optional. A Computer readable string to identify the error.
  3253 	 * @return false|void
  3354 	 * @return false|void
  3254 	 */
  3355 	 */
  3255 	public function bail( $message, $error_code = '500' ) {
  3356 	public function bail( $message, $error_code = '500' ) {
  3256 		if ( !$this->show_errors ) {
  3357 		if ( $this->show_errors ) {
       
  3358 			$error = '';
       
  3359 
       
  3360 			if ( $this->use_mysqli ) {
       
  3361 				if ( $this->dbh instanceof mysqli ) {
       
  3362 					$error = mysqli_error( $this->dbh );
       
  3363 				} elseif ( mysqli_connect_errno() ) {
       
  3364 					$error = mysqli_connect_error();
       
  3365 				}
       
  3366 			} else {
       
  3367 				if ( is_resource( $this->dbh ) ) {
       
  3368 					$error = mysql_error( $this->dbh );
       
  3369 				} else {
       
  3370 					$error = mysql_error();
       
  3371 				}
       
  3372 			}
       
  3373 
       
  3374 			if ( $error ) {
       
  3375 				$message = '<p><code>' . $error . "</code></p>\n" . $message;
       
  3376 			}
       
  3377 
       
  3378 			wp_die( $message );
       
  3379 		} else {
  3257 			if ( class_exists( 'WP_Error', false ) ) {
  3380 			if ( class_exists( 'WP_Error', false ) ) {
  3258 				$this->error = new WP_Error($error_code, $message);
  3381 				$this->error = new WP_Error( $error_code, $message );
  3259 			} else {
  3382 			} else {
  3260 				$this->error = $message;
  3383 				$this->error = $message;
  3261 			}
  3384 			}
       
  3385 
  3262 			return false;
  3386 			return false;
  3263 		}
  3387 		}
  3264 		wp_die($message);
       
  3265 	}
  3388 	}
  3266 
  3389 
  3267 
  3390 
  3268 	/**
  3391 	/**
  3269 	 * Closes the current database connection.
  3392 	 * Closes the current database connection.
  3283 		} else {
  3406 		} else {
  3284 			$closed = mysql_close( $this->dbh );
  3407 			$closed = mysql_close( $this->dbh );
  3285 		}
  3408 		}
  3286 
  3409 
  3287 		if ( $closed ) {
  3410 		if ( $closed ) {
  3288 			$this->dbh = null;
  3411 			$this->dbh           = null;
  3289 			$this->ready = false;
  3412 			$this->ready         = false;
  3290 			$this->has_connected = false;
  3413 			$this->has_connected = false;
  3291 		}
  3414 		}
  3292 
  3415 
  3293 		return $closed;
  3416 		return $closed;
  3294 	}
  3417 	}
  3304 	 * @return WP_Error|void
  3427 	 * @return WP_Error|void
  3305 	 */
  3428 	 */
  3306 	public function check_database_version() {
  3429 	public function check_database_version() {
  3307 		global $wp_version, $required_mysql_version;
  3430 		global $wp_version, $required_mysql_version;
  3308 		// Make sure the server has the required MySQL version
  3431 		// Make sure the server has the required MySQL version
  3309 		if ( version_compare($this->db_version(), $required_mysql_version, '<') ) {
  3432 		if ( version_compare( $this->db_version(), $required_mysql_version, '<' ) ) {
  3310 			/* translators: 1: WordPress version number, 2: Minimum required MySQL version number */
  3433 			/* translators: 1: WordPress version number, 2: Minimum required MySQL version number */
  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 ));
  3434 			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 		}
  3435 		}
  3313 	}
  3436 	}
  3314 
  3437 
  3315 	/**
  3438 	/**
  3316 	 * Whether the database supports collation.
  3439 	 * Whether the database supports collation.
  3337 	 * @return string The database character collate.
  3460 	 * @return string The database character collate.
  3338 	 */
  3461 	 */
  3339 	public function get_charset_collate() {
  3462 	public function get_charset_collate() {
  3340 		$charset_collate = '';
  3463 		$charset_collate = '';
  3341 
  3464 
  3342 		if ( ! empty( $this->charset ) )
  3465 		if ( ! empty( $this->charset ) ) {
  3343 			$charset_collate = "DEFAULT CHARACTER SET $this->charset";
  3466 			$charset_collate = "DEFAULT CHARACTER SET $this->charset";
  3344 		if ( ! empty( $this->collate ) )
  3467 		}
       
  3468 		if ( ! empty( $this->collate ) ) {
  3345 			$charset_collate .= " COLLATE $this->collate";
  3469 			$charset_collate .= " COLLATE $this->collate";
       
  3470 		}
  3346 
  3471 
  3347 		return $charset_collate;
  3472 		return $charset_collate;
  3348 	}
  3473 	}
  3349 
  3474 
  3350 	/**
  3475 	/**
  3363 	 */
  3488 	 */
  3364 	public function has_cap( $db_cap ) {
  3489 	public function has_cap( $db_cap ) {
  3365 		$version = $this->db_version();
  3490 		$version = $this->db_version();
  3366 
  3491 
  3367 		switch ( strtolower( $db_cap ) ) {
  3492 		switch ( strtolower( $db_cap ) ) {
  3368 			case 'collation' :    // @since 2.5.0
  3493 			case 'collation':    // @since 2.5.0
  3369 			case 'group_concat' : // @since 2.7.0
  3494 			case 'group_concat': // @since 2.7.0
  3370 			case 'subqueries' :   // @since 2.7.0
  3495 			case 'subqueries':   // @since 2.7.0
  3371 				return version_compare( $version, '4.1', '>=' );
  3496 				return version_compare( $version, '4.1', '>=' );
  3372 			case 'set_charset' :
  3497 			case 'set_charset':
  3373 				return version_compare( $version, '5.0.7', '>=' );
  3498 				return version_compare( $version, '5.0.7', '>=' );
  3374 			case 'utf8mb4' :      // @since 4.1.0
  3499 			case 'utf8mb4':      // @since 4.1.0
  3375 				if ( version_compare( $version, '5.5.3', '<' ) ) {
  3500 				if ( version_compare( $version, '5.5.3', '<' ) ) {
  3376 					return false;
  3501 					return false;
  3377 				}
  3502 				}
  3378 				if ( $this->use_mysqli ) {
  3503 				if ( $this->use_mysqli ) {
  3379 					$client_version = mysqli_get_client_info();
  3504 					$client_version = mysqli_get_client_info();
  3389 					$client_version = preg_replace( '/^\D+([\d.]+).*/', '$1', $client_version );
  3514 					$client_version = preg_replace( '/^\D+([\d.]+).*/', '$1', $client_version );
  3390 					return version_compare( $client_version, '5.0.9', '>=' );
  3515 					return version_compare( $client_version, '5.0.9', '>=' );
  3391 				} else {
  3516 				} else {
  3392 					return version_compare( $client_version, '5.5.3', '>=' );
  3517 					return version_compare( $client_version, '5.5.3', '>=' );
  3393 				}
  3518 				}
  3394 			case 'utf8mb4_520' : // @since 4.6.0
  3519 			case 'utf8mb4_520': // @since 4.6.0
  3395 				return version_compare( $version, '5.6', '>=' );
  3520 				return version_compare( $version, '5.6', '>=' );
  3396 		}
  3521 		}
  3397 
  3522 
  3398 		return false;
  3523 		return false;
  3399 	}
  3524 	}
  3404 	 * Searches up the list of functions until it reaches
  3529 	 * Searches up the list of functions until it reaches
  3405 	 * the one that would most logically had called this method.
  3530 	 * the one that would most logically had called this method.
  3406 	 *
  3531 	 *
  3407 	 * @since 2.5.0
  3532 	 * @since 2.5.0
  3408 	 *
  3533 	 *
  3409 	 * @return string|array The name of the calling function
  3534 	 * @return string Comma separated list of the calling functions.
  3410 	 */
  3535 	 */
  3411 	public function get_caller() {
  3536 	public function get_caller() {
  3412 		return wp_debug_backtrace_summary( __CLASS__ );
  3537 		return wp_debug_backtrace_summary( __CLASS__ );
  3413 	}
  3538 	}
  3414 
  3539