/** * Database Password * * @since 3.1.0 * @access protected * @var string */ protected $dbpassword; /** * Database Name * * @since 3.1.0 * @access protected * @var string */ protected $dbname; /** * Database Host * * @since 3.1.0 * @access protected * @var string */ protected $dbhost; /** * Database Handle * * @since 0.71 * @access protected * @var string */ protected $dbh; /** * A textual description of the last query/get_row/get_var call * * @since 3.0.0 * @access public * @var string */ public $func_call; /** * Whether MySQL is used as the database engine. * * Set in WPDB::db_connect() to true, by default. This is used when checking * against the required MySQL version for WordPress. Normally, a replacement * database drop-in (db.php) will skip these checks, but setting this to true * will force the checks to occur. * * @since 3.3.0 * @access public * @var bool */ public $is_mysql = null; /** * A list of incompatible SQL modes. * * @since 3.9.0 * @access protected * @var array */ protected $incompatible_modes = array( 'NO_ZERO_DATE', 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'TRADITIONAL' ); /** * Whether to use mysqli over mysql. * * @since 3.9.0 * @access private * @var bool */ private $use_mysqli = false; /** * Whether we've managed to successfully connect at some point * * @since 3.9.0 * @access private * @var bool */ private $has_connected = false; /** * Connects to the database server and selects a database * * PHP5 style constructor for compatibility with PHP5. Does * the actual setting up of the class properties and connection * to the database. * * @link https://core.trac.wordpress.org/ticket/3354 * @since 2.0.8 * * @global string $wp_version * * @param string $dbuser MySQL database user * @param string $dbpassword MySQL database password * @param string $dbname MySQL database name * @param string $dbhost MySQL database host */ public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) { register_shutdown_function( array( $this, '__destruct' ) ); if ( WP_DEBUG && WP_DEBUG_DISPLAY ) $this->show_errors(); /* Use ext/mysqli if it exists and: * - WP_USE_EXT_MYSQL is defined as false, or * - We are a development version of WordPress, or * - We are running PHP 5.5 or greater, or * - ext/mysql is not loaded. */ if ( function_exists( 'mysqli_connect' ) ) { if ( defined( 'WP_USE_EXT_MYSQL' ) ) { $this->use_mysqli = ! WP_USE_EXT_MYSQL; } elseif ( version_compare( phpversion(), '5.5', '>=' ) || ! function_exists( 'mysql_connect' ) ) { $this->use_mysqli = true; } elseif ( false !== strpos( $GLOBALS['wp_version'], '-' ) ) { $this->use_mysqli = true; } } $this->dbuser = $dbuser; $this->dbpassword = $dbpassword; $this->dbname = $dbname; $this->dbhost = $dbhost; // wp-config.php creation will manually connect when ready. if ( defined( 'WP_SETUP_CONFIG' ) ) { return; } $this->db_connect(); } /** * PHP5 style destructor and will run when database object is destroyed. * * @see wpdb::__construct() * @since 2.0.8 * @return true */ public function __destruct() { return true; } /** * PHP5 style magic getter, used to lazy-load expensive data. * * @since 3.5.0 * * @param string $name The private member to get, and optionally process * @return mixed The private member */ public function __get( $name ) { if ( 'col_info' === $name ) $this->load_col_info(); return $this->$name; } /** * Magic function, for backwards compatibility. * * @since 3.5.0 * * @param string $name The private member to set * @param mixed $value The value to set */ public function __set( $name, $value ) { $protected_members = array( 'col_meta', 'table_charset', 'check_current_query', ); if ( in_array( $name, $protected_members, true ) ) { return; } $this->$name = $value; } /** * Magic function, for backwards compatibility. * * @since 3.5.0 * * @param string $name The private member to check * * @return bool If the member is set or not */ public function __isset( $name ) { return isset( $this->$name ); } /** * Magic function, for backwards compatibility. * * @since 3.5.0 * * @param string $name The private member to unset */ public function __unset( $name ) { unset( $this->$name ); } /** * Set $this->charset and $this->collate * * @since 3.1.0 */ public function init_charset() { if ( function_exists('is_multisite') && is_multisite() ) { $this->charset = 'utf8'; if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) { $this->collate = DB_COLLATE; } else { $this->collate = 'utf8_general_ci'; } } elseif ( defined( 'DB_COLLATE' ) ) { $this->collate = DB_COLLATE; } if ( defined( 'DB_CHARSET' ) ) { $this->charset = DB_CHARSET; } if ( ( $this->use_mysqli && ! ( $this->dbh instanceof mysqli ) ) || empty( $this->dbh ) ) { return; } if ( 'utf8' === $this->charset && $this->has_cap( 'utf8mb4' ) ) { $this->charset = 'utf8mb4'; } if ( 'utf8mb4' === $this->charset && ( ! $this->collate || stripos( $this->collate, 'utf8_' ) === 0 ) ) { $this->collate = 'utf8mb4_unicode_ci'; } } /** * Sets the connection's character set. * * @since 3.1.0 * * @param resource $dbh The resource given by mysql_connect * @param string $charset Optional. The character set. Default null. * @param string $collate Optional. The collation. Default null. */ public function set_charset( $dbh, $charset = null, $collate = null ) { if ( ! isset( $charset ) ) $charset = $this->charset; if ( ! isset( $collate ) ) $collate = $this->collate; if ( $this->has_cap( 'collation' ) && ! empty( $charset ) ) { if ( $this->use_mysqli ) { if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset' ) ) { mysqli_set_charset( $dbh, $charset ); } else { $query = $this->prepare( 'SET NAMES %s', $charset ); if ( ! empty( $collate ) ) $query .= $this->prepare( ' COLLATE %s', $collate ); mysqli_query( $dbh, $query ); } } else { if ( function_exists( 'mysql_set_charset' ) && $this->has_cap( 'set_charset' ) ) { mysql_set_charset( $charset, $dbh ); } else { $query = $this->prepare( 'SET NAMES %s', $charset ); if ( ! empty( $collate ) ) $query .= $this->prepare( ' COLLATE %s', $collate ); mysql_query( $query, $dbh ); } } } } /** * Change the current SQL mode, and ensure its WordPress compatibility. * * If no modes are passed, it will ensure the current MySQL server * modes are compatible. * * @since 3.9.0 * * @param array $modes Optional. A list of SQL modes to set. */ public function set_sql_mode( $modes = array() ) { if ( empty( $modes ) ) { if ( $this->use_mysqli ) { $res = mysqli_query( $this->dbh, 'SELECT @@SESSION.sql_mode' ); } else { $res = mysql_query( 'SELECT @@SESSION.sql_mode', $this->dbh ); } if ( empty( $res ) ) { return; } if ( $this->use_mysqli ) { $modes_array = mysqli_fetch_array( $res ); if ( empty( $modes_array[0] ) ) { return; } $modes_str = $modes_array[0]; } else { $modes_str = mysql_result( $res, 0 ); } if ( empty( $modes_str ) ) { return; } $modes = explode( ',', $modes_str ); } $modes = array_change_key_case( $modes, CASE_UPPER ); /** * Filter the list of incompatible SQL modes to exclude. * * @since 3.9.0 * * @param array $incompatible_modes An array of incompatible modes. */ $incompatible_modes = (array) apply_filters( 'incompatible_sql_modes', $this->incompatible_modes ); foreach( $modes as $i => $mode ) { if ( in_array( $mode, $incompatible_modes ) ) { unset( $modes[ $i ] ); } } $modes_str = implode( ',', $modes ); if ( $this->use_mysqli ) { mysqli_query( $this->dbh, "SET SESSION sql_mode='$modes_str'" ); } else { mysql_query( "SET SESSIe supports collation. * * Called when WordPress is generating the table scheme. * * @since 2.5.0 * @deprecated 3.5.0 * @deprecated Use wpdb::has_cap( 'collation' ) * * @return bool True if collation is supported, false if version does not */ public function supports_collation() { _deprecated_function( __FUNCTION__, '3.5', 'wpdb::has_cap( \'collation\' )' ); return $this->has_cap( 'collation' ); } /** * The database character collate. * * @since 3.5.0 * * @return string The database character collate. */ public function get_charset_collate() { $charset_collate = ''; if ( ! empty( $this->charset ) ) $charset_collate = "DEFAULT CHARACTER SET $this->charset"; if ( ! empty( $this->collate ) ) $charset_collate .= " COLLATE $this->collate"; return $charset_collate; } /** * Determine if a database supports a particular feature. * * @since 2.7.0 * @since 4.1.0 Support was added for the 'utf8mb4' feature. * * @see wpdb::db_version() * * @param string $db_cap The feature to check for. Accepts 'collation', * 'group_concat', 'subqueries', 'set_charset', * or 'utf8mb4'. * @return int|false Whether the database feature is supported, false otherwise. */ public function has_cap( $db_cap ) { $version = $this->db_version(); switch ( strtolower( $db_cap ) ) { case 'collation' : // @since 2.5.0 case 'group_concat' : // @since 2.7.0 case 'subqueries' : // @since 2.7.0 return version_compare( $version, '4.1', '>=' ); case 'set_charset' : return version_compare( $version, '5.0.7', '>=' ); case 'utf8mb4' : // @since 4.1.0 if ( version_compare( $version, '5.5.3', '<' ) ) { return false; } if ( $this->use_mysqli ) { $client_version = mysqli_get_client_info(); } else { $client_version = mysql_get_client_info(); } /* * libmysql has supported utf8mb4 since 5.5.3, same as the MySQL server. * mysqlnd has supported utf8mb4 since 5.0.9. */ if ( false !== strpos( $client_version, 'mysqlnd' ) ) { $client_version = preg_replace( '/^\D+([\d.]+).*/', '$1', $client_version ); return version_compare( $client_version, '5.0.9', '>=' ); } else { return version_compare( $client_version, '5.5.3', '>=' ); } } return false; } /** * Retrieve the name of the function that called wpdb. * * Searches up the list of functions until it reaches * the one that would most logically had called this method. * * @since 2.5.0 * * @return string|array The name of the calling function */ public function get_caller() { return wp_debug_backtrace_summary( __CLASS__ ); } /** * The database version number. * * @since 2.7.0 * * @return null|string Null on failure, version number on success. */ public function db_version() { if ( $this->use_mysqli ) { $server_info = mysqli_get_server_info( $this->dbh ); } else { $server_info = mysql_get_server_info( $this->dbh ); } return preg_replace( '/[^0-9.].*/', '', $server_info ); } }