From 11df92738b07de35ae42fa6ee14c5ed506432241 Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Fri, 23 Jun 2023 12:15:06 +0000 Subject: [PATCH] Database: Replace `str_contains()` and `str_ends_with()` usage in `wpdb` methods. This avoids fatal errors on PHP < 8.0 if the file is included directly outside of WordPress core, e.g. by HyperDB. While WordPress core does include polyfills for these functions, they are not directly loaded in the `wpdb` class. Follow-up to [54384], [55157], [55158], [55988], [55990]. Props dd32, ryelle, joedolson. See #58206. git-svn-id: https://develop.svn.wordpress.org/trunk@55994 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-admin/load-styles.php | 2 +- src/wp-includes/class-wpdb.php | 40 ++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/wp-admin/load-styles.php b/src/wp-admin/load-styles.php index eb05554de2..fe4a4ee66e 100644 --- a/src/wp-admin/load-styles.php +++ b/src/wp-admin/load-styles.php @@ -73,7 +73,7 @@ foreach ( $load as $handle ) { $content = get_file( $path ) . "\n"; - // str_starts_with() is not used here, as wp-includes/compat.php is not loaded in this file. + // Note: str_starts_with() is not used here, as wp-includes/compat.php is not loaded in this file. if ( 0 === strpos( $style->src, '/' . WPINC . '/css/' ) ) { $content = str_replace( '../images/', '../' . WPINC . '/images/', $content ); $content = str_replace( '../js/tinymce/', '../' . WPINC . '/js/tinymce/', $content ); diff --git a/src/wp-includes/class-wpdb.php b/src/wp-includes/class-wpdb.php index 0f145e7f8b..59a8a8ca89 100644 --- a/src/wp-includes/class-wpdb.php +++ b/src/wp-includes/class-wpdb.php @@ -1496,8 +1496,14 @@ class wpdb { return; } - // This is not meant to be foolproof -- but it will catch obviously incorrect usage. - if ( ! str_contains( $query, '%' ) ) { + /* + * This is not meant to be foolproof -- but it will catch obviously incorrect usage. + * + * Note: str_contains() is not used here, as this file can be included + * directly outside of WordPress core, e.g. by HyperDB, in which case + * the polyfills from wp-includes/compat.php are not loaded. + */ + if ( false === strpos( $query, '%' ) ) { wp_load_translations_early(); _doing_it_wrong( 'wpdb::prepare', @@ -1564,7 +1570,12 @@ class wpdb { $type = substr( $placeholder, -1 ); if ( 'f' === $type && true === $this->allow_unsafe_unquoted_parameters - && str_ends_with( $split_query[ $key - 1 ], '%' ) + /* + * Note: str_ends_with() is not used here, as this file can be included + * directly outside of WordPress core, e.g. by HyperDB, in which case + * the polyfills from wp-includes/compat.php are not loaded. + */ + && '%' === substr( $split_query[ $key - 1 ], -1, 1 ) ) { /* @@ -1625,7 +1636,12 @@ class wpdb { * Second, if "%s" has a "%" before it, even if it's unrelated (e.g. "LIKE '%%%s%%'"). */ if ( true !== $this->allow_unsafe_unquoted_parameters - || ( '' === $format && ! str_ends_with( $split_query[ $key - 1 ], '%' ) ) + /* + * Note: str_ends_with() is not used here, as this file can be included + * directly outside of WordPress core, e.g. by HyperDB, in which case + * the polyfills from wp-includes/compat.php are not loaded. + */ + || ( '' === $format && '%' !== substr( $split_query[ $key - 1 ], -1, 1 ) ) ) { $placeholder = "'%" . $format . "s'"; } @@ -4038,8 +4054,14 @@ class wpdb { $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' ) + /* + * Account for MariaDB version being prefixed with '5.5.5-' on older PHP versions. + * + * Note: str_contains() is not used here, as this file can be included + * directly outside of WordPress core, e.g. by HyperDB, in which case + * the polyfills from wp-includes/compat.php are not loaded. + */ + if ( '5.5.5' === $db_version && false !== strpos( $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. @@ -4067,8 +4089,12 @@ class wpdb { /* * libmysql has supported utf8mb4 since 5.5.3, same as the MySQL server. * mysqlnd has supported utf8mb4 since 5.0.9. + * + * Note: str_contains() is not used here, as this file can be included + * directly outside of WordPress core, e.g. by HyperDB, in which case + * the polyfills from wp-includes/compat.php are not loaded. */ - if ( str_contains( $client_version, 'mysqlnd' ) ) { + if ( false !== strpos( $client_version, 'mysqlnd' ) ) { $client_version = preg_replace( '/^\D+([\d.]+).*/', '$1', $client_version ); return version_compare( $client_version, '5.0.9', '>=' ); } else {