From fed98bd9ef9a232d102c41e74944d3c21cd6183e Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Tue, 4 Oct 2022 15:39:28 +0000 Subject: [PATCH] Database: Correct MariaDB version check in `wpdb::has_cap()`. MariaDB version is reported differently between PHP versions: * PHP 8.0.16 or later: `10.6.8-MariaDB` * PHP 8.0.15 or earlier: `5.5.5-10.6.8-MariaDB` The latter includes PHP 7.4.x and PHP 5.6.x as well, where the version is also reported with the `5.5.5-` prefix. This commit makes an adjustment to `wpdb::has_cap()` to check for the correct MariaDB version. This resolves an issue where the `utf8mb4_unicode_520_ci` collation, which is available in MariaDB since version 10.2, was previously not detected correctly. References: * [https://github.com/php/php-src/issues/7972 php-src: #7972: MariaDB version prefix 5.5.5- is not stripped] * [https://github.com/php/php-src/pull/7963 php-src: PR #7963 Fix GH-7932: MariaDB version prefix not always stripped] * [https://mariadb.com/docs/reference/mdb/collations/utf8mb4_unicode_520_ci/ MariaDB Documentation: utf8mb4_unicode_520_ci] Follow-up to [37523], [53919]. Props jamieburchell, SergeyBiryukov. Fixes #54841. git-svn-id: https://develop.svn.wordpress.org/trunk@54384 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-wpdb.php | 20 +++++++++++++++----- tests/phpunit/tests/db/charset.php | 18 +++++++++++++++++- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/wp-includes/class-wpdb.php b/src/wp-includes/class-wpdb.php index 043bca0a07..88317f535e 100644 --- a/src/wp-includes/class-wpdb.php +++ b/src/wp-includes/class-wpdb.php @@ -3960,17 +3960,27 @@ class wpdb { * @return bool True when the database feature is supported, false otherwise. */ public function has_cap( $db_cap ) { - $version = $this->db_version(); + $db_version = $this->db_version(); + $db_server_info = $this->db_server_info(); + + // Account for MariaDB version being prefixed with '5.5.5-' on older PHP versions. + if ( '5.5.5' === $db_version && str_contains( $db_server_info, 'MariaDB' ) + && PHP_VERSION_ID < 80016 // PHP 8.0.15 or older. + ) { + // Strip the '5.5.5-' prefix and set the version to the correct value. + $db_server_info = preg_replace( '/^5\.5\.5-(.*)/', '$1', $db_server_info ); + $db_version = preg_replace( '/[^0-9.].*/', '', $db_server_info ); + } 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', '>=' ); + return version_compare( $db_version, '4.1', '>=' ); case 'set_charset': - return version_compare( $version, '5.0.7', '>=' ); + return version_compare( $db_version, '5.0.7', '>=' ); case 'utf8mb4': // @since 4.1.0 - if ( version_compare( $version, '5.5.3', '<' ) ) { + if ( version_compare( $db_version, '5.5.3', '<' ) ) { return false; } if ( $this->use_mysqli ) { @@ -3990,7 +4000,7 @@ class wpdb { return version_compare( $client_version, '5.5.3', '>=' ); } case 'utf8mb4_520': // @since 4.6.0 - return version_compare( $version, '5.6', '>=' ); + return version_compare( $db_version, '5.6', '>=' ); case 'identifier_placeholders': // @since 6.1.0 /* * As of WordPress 6.1, wpdb::prepare() supports identifiers via '%i', diff --git a/tests/phpunit/tests/db/charset.php b/tests/phpunit/tests/db/charset.php index 6fc2162526..627526bff2 100644 --- a/tests/phpunit/tests/db/charset.php +++ b/tests/phpunit/tests/db/charset.php @@ -47,7 +47,7 @@ class Tests_DB_Charset extends WP_UnitTestCase { self::$db_server_info = self::$_wpdb->db_server_info(); // Account for MariaDB version being prefixed with '5.5.5-' on older PHP versions. - if ( str_contains( self::$db_server_info, 'MariaDB' ) && '5.5.5' === self::$db_version + if ( '5.5.5' === self::$db_version && str_contains( self::$db_server_info, 'MariaDB' ) && PHP_VERSION_ID < 80016 // PHP 8.0.15 or older. ) { // Strip the '5.5.5-' prefix and set the version to the correct value. @@ -1189,4 +1189,20 @@ class Tests_DB_Charset extends WP_UnitTestCase { self::$_wpdb->set_charset( self::$_wpdb->dbh ); } + + /** + * @ticket 54841 + */ + public function test_mariadb_supports_utf8mb4_520() { + global $wpdb; + + // utf8mb4_520 is available in MariaDB since version 10.2. + if ( ! str_contains( self::$db_server_info, 'MariaDB' ) + || version_compare( self::$db_version, '10.2', '<' ) + ) { + $this->markTestSkipped( 'This test requires MariaDB 10.2 or later.' ); + } + + $this->assertTrue( $wpdb->has_cap( 'utf8mb4_520' ) ); + } }