* file to your class. The wpdb class will still be included,
* so you can extend it or simply use your own.
*
- * @link http://codex.wordpress.org/Function_Reference/wpdb_Class
+ * @link https://codex.wordpress.org/Function_Reference/wpdb_Class
*
* @package WordPress
* @subpackage Database
var $ready = false;
/**
- * {@internal Missing Description}}
+ * Blog ID.
*
* @since 3.0.0
* @access public
public $blogid = 0;
/**
- * {@internal Missing Description}}
+ * Site ID.
*
* @since 3.0.0
* @access public
}
}
- $this->init_charset();
-
$this->dbuser = $dbuser;
$this->dbpassword = $dbpassword;
$this->dbname = $dbname;
public function init_charset() {
if ( function_exists('is_multisite') && is_multisite() ) {
$this->charset = 'utf8';
- if ( defined( 'DB_COLLATE' ) && DB_COLLATE )
+ if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) {
$this->collate = DB_COLLATE;
- else
+ } else {
$this->collate = 'utf8_general_ci';
+ }
} elseif ( defined( 'DB_COLLATE' ) ) {
$this->collate = DB_COLLATE;
}
- if ( defined( 'DB_CHARSET' ) )
+ if ( defined( 'DB_CHARSET' ) ) {
$this->charset = DB_CHARSET;
+ }
+
+ if ( ( $this->use_mysqli && ! ( $this->dbh instanceof mysqli ) )
+ || ( empty( $this->dbh ) || ! ( $this->dbh instanceof mysqli ) ) ) {
+ 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';
+ }
}
/**
while ( mysqli_more_results( $this->dbh ) ) {
mysqli_next_result( $this->dbh );
}
- } else if ( is_resource( $this->result ) ) {
+ } elseif ( is_resource( $this->result ) ) {
mysql_free_result( $this->result );
}
}
if ( $this->has_connected ) {
$attempt_fallback = false;
- } else if ( defined( 'WP_USE_EXT_MYSQL' ) && ! WP_USE_EXT_MYSQL ) {
+ } elseif ( defined( 'WP_USE_EXT_MYSQL' ) && ! WP_USE_EXT_MYSQL ) {
$attempt_fallback = false;
- } else if ( ! function_exists( 'mysql_connect' ) ) {
+ } elseif ( ! function_exists( 'mysql_connect' ) ) {
$attempt_fallback = false;
}
" ), htmlspecialchars( $this->dbhost, ENT_QUOTES ) ), 'db_connect_fail' );
return false;
- } else if ( $this->dbh ) {
+ } elseif ( $this->dbh ) {
+ if ( ! $this->has_connected ) {
+ $this->init_charset();
+ }
+
$this->has_connected = true;
+
$this->set_charset( $this->dbh );
- $this->set_sql_mode();
+
$this->ready = true;
+ $this->set_sql_mode();
$this->select( $this->dbname, $this->dbh );
return true;
}
$this->check_current_query = true;
+
// Keep track of the last query for debug..
$this->last_query = $query;
$this->last_result[$num_rows] = $row;
$num_rows++;
}
- } else if ( is_resource( $this->result ) ) {
+ } elseif ( is_resource( $this->result ) ) {
while ( $row = @mysql_fetch_object( $this->result ) ) {
$this->last_result[$num_rows] = $row;
$num_rows++;
*/
protected function process_fields( $table, $data, $format ) {
$data = $this->process_field_formats( $data, $format );
- if ( false === $data ) {
- return false;
- }
-
$data = $this->process_field_charsets( $data, $table );
if ( false === $data ) {
return false;
}
- $data = $this->process_field_lengths( $data, $table );
- if ( false === $data ) {
- return false;
- }
-
$converted_data = $this->strip_invalid_text( $data );
if ( $data !== $converted_data ) {
/**
* Adds field charsets to field/value/format arrays generated by
- * the {@see wpdb::process_field_formats()} method.
+ * the wpdb::process_field_formats() method.
*
* @since 4.2.0
* @access protected
*
- * @param array $data As it comes from the {@see wpdb::process_field_formats()} method.
+ * @param array $data As it comes from the wpdb::process_field_formats() method.
* @param string $table Table name.
* @return The same array as $data with additional 'charset' keys.
*/
return $data;
}
- /**
- * For string fields, record the maximum string length that field can safely save.
- *
- * @since 4.2.1
- * @access protected
- *
- * @param array $data As it comes from the wpdb::process_field_charsets() method.
- * @param string $table Table name.
- * @return array|False The same array as $data with additional 'length' keys, or false if
- * any of the values were too long for their corresponding field.
- */
- protected function process_field_lengths( $data, $table ) {
- foreach ( $data as $field => $value ) {
- if ( '%d' === $value['format'] || '%f' === $value['format'] ) {
- // We can skip this field if we know it isn't a string.
- // This checks %d/%f versus ! %s because it's sprintf() could take more.
- $value['length'] = false;
- } else {
- $value['length'] = $this->get_col_length( $table, $field );
- if ( is_wp_error( $value['length'] ) ) {
- return false;
- }
- }
-
- if ( false !== $value['length'] && strlen( $value['value'] ) > $value['length'] ) {
- return false;
- }
-
- $data[ $field ] = $value;
- }
-
- return $data;
- }
-
/**
* Retrieve one variable from the database.
*
* @access protected
*
* @param string $table Table name.
- * @return string|WP_Error Table character set, {@see WP_Error} object if it couldn't be found.
+ * @return string|WP_Error Table character set, WP_Error object if it couldn't be found.
*/
protected function get_table_charset( $table ) {
$tablekey = strtolower( $table );
foreach ( $columns as $column ) {
if ( ! empty( $column->Collation ) ) {
list( $charset ) = explode( '_', $column->Collation );
+
+ // If the current connection can't support utf8mb4 characters, let's only send 3-byte utf8 characters.
+ if ( 'utf8mb4' === $charset && ! $this->has_cap( 'utf8mb4' ) ) {
+ $charset = 'utf8';
+ }
+
$charsets[ strtolower( $charset ) ] = true;
}
* @param string $table Table name.
* @param string $column Column name.
* @return mixed Column character set as a string. False if the column has no
- * character set. {@see WP_Error} object if there was an error.
+ * character set. WP_Error object if there was an error.
*/
public function get_col_charset( $table, $column ) {
$tablekey = strtolower( $table );
return $charset;
}
- /**
- * Retrieve the maximum string length allowed in a given column.
- *
- * @since 4.2.1
- * @access public
- *
- * @param string $table Table name.
- * @param string $column Column name.
- * @return mixed Max column length as an int. False if the column has no
- * length. WP_Error object if there was an error.
- */
- public function get_col_length( $table, $column ) {
- $tablekey = strtolower( $table );
- $columnkey = strtolower( $column );
-
- // Skip this entirely if this isn't a MySQL database.
- if ( false === $this->is_mysql ) {
- return false;
- }
-
- if ( empty( $this->col_meta[ $tablekey ] ) ) {
- // This primes column information for us.
- $table_charset = $this->get_table_charset( $table );
- if ( is_wp_error( $table_charset ) ) {
- return $table_charset;
- }
- }
-
- if ( empty( $this->col_meta[ $tablekey ][ $columnkey ] ) ) {
- return false;
- }
-
- $typeinfo = explode( '(', $this->col_meta[ $tablekey ][ $columnkey ]->Type );
-
- $type = strtolower( $typeinfo[0] );
- if ( ! empty( $typeinfo[1] ) ) {
- $length = trim( $typeinfo[1], ')' );
- } else {
- $length = false;
- }
-
- switch( $type ) {
- case 'binary':
- case 'char':
- case 'varbinary':
- case 'varchar':
- return $length;
- break;
- case 'tinyblob':
- case 'tinytext':
- return 255; // 2^8 - 1
- break;
- case 'blob':
- case 'text':
- return 65535; // 2^16 - 1
- break;
- case 'mediumblob':
- case 'mediumtext':
- return 16777215; // 2^24 - 1
- break;
- case 'longblob':
- case 'longtext':
- return 4294967295; // 2^32 - 1
- break;
- default:
- return false;
- }
-
- return false;
- }
-
/**
* Check if a string is ASCII.
*
* @return array|WP_Error The $data parameter, with invalid characters removed from
* each value. This works as a passthrough: any additional keys
* such as 'field' are retained in each value array. If we cannot
- * remove invalid characters, a {@see WP_Error} object is returned.
+ * remove invalid characters, a WP_Error object is returned.
*/
- // If any of the columns don't have one of these collations, it needs more sanity checking.
protected function strip_invalid_text( $data ) {
// Some multibyte character sets that we can check in PHP.
$mb_charsets = array(
* @access protected
*
* @param string $query Query to convert.
- * @return string|WP_Error The converted query, or a {@see WP_Error} object if the conversion fails.
+ * @return string|WP_Error The converted query, or a WP_Error object if the conversion fails.
*/
protected function strip_invalid_text_from_query( $query ) {
$table = $this->get_table_from_query( $query );
* @param string $table Table name.
* @param string $column Column name.
* @param string $value The text to check.
- * @return string|WP_Error The converted string, or a `WP_Error` object if the conversion fails.
+ * @return string|WP_Error The converted string, or a WP_Error object if the conversion fails.
*/
public function strip_invalid_text_for_column( $table, $column, $value ) {
if ( ! is_string( $value ) || $this->check_ascii( $value ) ) {
case 'set_charset' :
return version_compare( $version, '5.0.7', '>=' );
case 'utf8mb4' : // @since 4.1.0
- return version_compare( $version, '5.5.3', '>=' );
+ 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;