diff -r 7b1b88e27a20 -r 48c4eec2b7e6 wp/wp-admin/includes/class-wp-site-health.php --- a/wp/wp-admin/includes/class-wp-site-health.php Thu Sep 29 08:06:27 2022 +0200 +++ b/wp/wp-admin/includes/class-wp-site-health.php Fri Sep 05 18:40:08 2025 +0200 @@ -7,16 +7,18 @@ * @since 5.2.0 */ +#[AllowDynamicProperties] class WP_Site_Health { private static $instance = null; - private $mysql_min_version_check; - private $mysql_rec_version_check; - - public $is_mariadb = false; - private $mysql_server_version = ''; - private $health_check_mysql_required_version = '5.5'; - private $health_check_mysql_rec_version = ''; + private $is_acceptable_mysql_version; + private $is_recommended_mysql_version; + + public $is_mariadb = false; + private $mysql_server_version = ''; + private $mysql_required_version = '5.5'; + private $mysql_recommended_version = '8.0'; + private $mariadb_recommended_version = '10.5'; public $php_memory_limit; @@ -55,7 +57,7 @@ } /** - * Output the content of a tab in the Site Health screen. + * Outputs the content of a tab in the Site Health screen. * * @since 5.8.0 * @@ -63,12 +65,12 @@ */ public function show_site_health_tab( $tab ) { if ( 'debug' === $tab ) { - require_once ABSPATH . '/wp-admin/site-health-info.php'; + require_once ABSPATH . 'wp-admin/site-health-info.php'; } } /** - * Return an instance of the WP_Site_Health class, or create one if none exist yet. + * Returns an instance of the WP_Site_Health class, or create one if none exist yet. * * @since 5.4.0 * @@ -160,7 +162,7 @@ } /** - * Run a Site Health test directly. + * Runs a Site Health test directly. * * @since 5.4.0 * @@ -193,7 +195,7 @@ } /** - * Run the SQL version checks. + * Runs the SQL version checks. * * These values are used in later tests, but the part of preparing them is more easily managed * early in the class for ease of access and discovery. @@ -205,29 +207,21 @@ private function prepare_sql_data() { global $wpdb; - if ( $wpdb->use_mysqli ) { - // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_server_info - $mysql_server_type = mysqli_get_server_info( $wpdb->dbh ); - } else { - // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_server_info,PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved - $mysql_server_type = mysql_get_server_info( $wpdb->dbh ); - } + $mysql_server_type = $wpdb->db_server_info(); $this->mysql_server_version = $wpdb->get_var( 'SELECT VERSION()' ); - $this->health_check_mysql_rec_version = '5.6'; - if ( stristr( $mysql_server_type, 'mariadb' ) ) { - $this->is_mariadb = true; - $this->health_check_mysql_rec_version = '10.0'; + $this->is_mariadb = true; + $this->mysql_recommended_version = $this->mariadb_recommended_version; } - $this->mysql_min_version_check = version_compare( '5.5', $this->mysql_server_version, '<=' ); - $this->mysql_rec_version_check = version_compare( $this->health_check_mysql_rec_version, $this->mysql_server_version, '<=' ); + $this->is_acceptable_mysql_version = version_compare( $this->mysql_required_version, $this->mysql_server_version, '<=' ); + $this->is_recommended_mysql_version = version_compare( $this->mysql_recommended_version, $this->mysql_server_version, '<=' ); } /** - * Test if `wp_version_check` is blocked. + * Tests whether `wp_version_check` is blocked. * * It's possible to block updates with the `wp_version_check` filter, but this can't be checked * during an Ajax call, as the filter is never introduced then. @@ -349,9 +343,9 @@ } /** - * Test if plugins are outdated, or unnecessary. + * Tests if plugins are outdated, or unnecessary. * - * The tests checks if your plugins are up to date, and encourages you to remove any + * The test checks if your plugins are up to date, and encourages you to remove any * that are not in use. * * @since 5.2.0 @@ -381,24 +375,20 @@ $plugins = get_plugins(); $plugin_updates = get_plugin_updates(); - $plugins_have_updates = false; - $plugins_active = 0; - $plugins_total = 0; - $plugins_need_update = 0; + $plugins_active = 0; + $plugins_total = 0; + $plugins_need_update = 0; // Loop over the available plugins and check their versions and active state. foreach ( $plugins as $plugin_path => $plugin ) { - $plugins_total++; + ++$plugins_total; if ( is_plugin_active( $plugin_path ) ) { - $plugins_active++; + ++$plugins_active; } - $plugin_version = $plugin['Version']; - if ( array_key_exists( $plugin_path, $plugin_updates ) ) { - $plugins_need_update++; - $plugins_have_updates = true; + ++$plugins_need_update; } } @@ -432,7 +422,7 @@ '

%s

', __( 'Your site has 1 active plugin, and it is up to date.' ) ); - } else { + } elseif ( $plugins_active > 0 ) { $result['description'] .= sprintf( '

%s

', sprintf( @@ -445,6 +435,11 @@ $plugins_active ) ); + } else { + $result['description'] .= sprintf( + '

%s

', + __( 'Your site does not have any active plugins.' ) + ); } } @@ -481,9 +476,9 @@ } /** - * Test if themes are outdated, or unnecessary. + * Tests if themes are outdated, or unnecessary. * - * Сhecks if your site has a default theme (to fall back on if there is a need), + * Checks if your site has a default theme (to fall back on if there is a need), * if your themes are up to date and, finally, encourages you to remove any themes * that are not needed. * @@ -548,21 +543,21 @@ } foreach ( $all_themes as $theme_slug => $theme ) { - $themes_total++; + ++$themes_total; if ( array_key_exists( $theme_slug, $theme_updates ) ) { - $themes_need_updates++; + ++$themes_need_updates; } } // If this is a child theme, increase the allowed theme count by one, to account for the parent. if ( is_child_theme() ) { - $allowed_theme_count++; + ++$allowed_theme_count; } // If there's a default theme installed and not in use, we count that as allowed as well. if ( $has_default_theme && ! $using_default_theme ) { - $allowed_theme_count++; + ++$allowed_theme_count; } if ( $themes_total > $allowed_theme_count ) { @@ -595,7 +590,7 @@ '

%s

', __( 'Your site has 1 installed theme, and it is up to date.' ) ); - } else { + } elseif ( $themes_total > 0 ) { $result['description'] .= sprintf( '

%s

', sprintf( @@ -608,6 +603,11 @@ $themes_total ) ); + } else { + $result['description'] .= sprintf( + '

%s

', + __( 'Your site does not have any installed themes.' ) + ); } } @@ -717,7 +717,7 @@ } /** - * Test if the supplied PHP version is supported. + * Tests if the supplied PHP version is supported. * * @since 5.2.0 * @@ -741,15 +741,15 @@ '

%s

', sprintf( /* translators: %s: The minimum recommended PHP version. */ - __( 'PHP is the programming language used to build and maintain WordPress. Newer versions of PHP are created with increased performance in mind, so you may see a positive effect on your site’s performance. The minimum recommended version of PHP is %s.' ), + __( 'PHP is one of the programming languages used to build WordPress. Newer versions of PHP receive regular security updates and may increase your site’s performance. The minimum recommended version of PHP is %s.' ), $response ? $response['recommended_version'] : '' ) ), 'actions' => sprintf( - '

%s %s

', + '

%s %s

', esc_url( wp_get_update_php_url() ), __( 'Learn more about updating PHP' ), - /* translators: Accessibility text. */ + /* translators: Hidden accessibility text. */ __( '(opens in a new tab)' ) ), 'test' => 'php_version', @@ -764,7 +764,7 @@ if ( $response['is_supported'] ) { $result['label'] = sprintf( /* translators: %s: The server PHP version. */ - __( 'Your site is running an older version of PHP (%s)' ), + __( 'Your site is running on an older version of PHP (%s)' ), PHP_VERSION ); $result['status'] = 'recommended'; @@ -772,11 +772,30 @@ return $result; } + /* + * The PHP version is still receiving security fixes, but is lower than + * the expected minimum version that will be required by WordPress in the near future. + */ + if ( $response['is_secure'] && $response['is_lower_than_future_minimum'] ) { + // The `is_secure` array key name doesn't actually imply this is a secure version of PHP. It only means it receives security updates. + + $result['label'] = sprintf( + /* translators: %s: The server PHP version. */ + __( 'Your site is running on an outdated version of PHP (%s), which soon will not be supported by WordPress.' ), + PHP_VERSION + ); + + $result['status'] = 'critical'; + $result['badge']['label'] = __( 'Requirements' ); + + return $result; + } + // The PHP version is only receiving security fixes. if ( $response['is_secure'] ) { $result['label'] = sprintf( /* translators: %s: The server PHP version. */ - __( 'Your site is running an older version of PHP (%s), which should be updated' ), + __( 'Your site is running on an older version of PHP (%s), which should be updated' ), PHP_VERSION ); $result['status'] = 'recommended'; @@ -784,20 +803,32 @@ return $result; } - // Anything no longer secure must be updated. - $result['label'] = sprintf( - /* translators: %s: The server PHP version. */ - __( 'Your site is running an outdated version of PHP (%s), which requires an update' ), - PHP_VERSION - ); - $result['status'] = 'critical'; + // No more security updates for the PHP version, and lower than the expected minimum version required by WordPress. + if ( $response['is_lower_than_future_minimum'] ) { + $message = sprintf( + /* translators: %s: The server PHP version. */ + __( 'Your site is running on an outdated version of PHP (%s), which does not receive security updates and soon will not be supported by WordPress.' ), + PHP_VERSION + ); + } else { + // No more security updates for the PHP version, must be updated. + $message = sprintf( + /* translators: %s: The server PHP version. */ + __( 'Your site is running on an outdated version of PHP (%s), which does not receive security updates. It should be updated.' ), + PHP_VERSION + ); + } + + $result['label'] = $message; + $result['status'] = 'critical'; + $result['badge']['label'] = __( 'Security' ); return $result; } /** - * Check if the passed extension or function are available. + * Checks if the passed extension or function are available. * * Make the check for available PHP modules into a simple boolean operator for a cleaner test runner. * @@ -836,7 +867,7 @@ } /** - * Test if required PHP modules are installed on the host. + * Tests if required PHP modules are installed on the host. * * This test builds on the recommendations made by the WordPress Hosting Team * as seen at https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions @@ -863,8 +894,8 @@ esc_url( __( 'https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions' ) ), 'target="_blank" rel="noopener"', sprintf( - ' %s', - /* translators: Accessibility text. */ + ' %s', + /* translators: Hidden accessibility text. */ __( '(opens in a new tab)' ) ) ) @@ -971,7 +1002,7 @@ ); /** - * An array representing all the modules we wish to test for. + * Filters the array representing all the modules we wish to test for. * * @since 5.2.0 * @since 5.3.0 The `$constant` and `$class` parameters were added. @@ -1022,7 +1053,8 @@ if ( $module['required'] ) { $result['status'] = 'critical'; - $class = 'error'; + $class = 'error'; + /* translators: Hidden accessibility text. */ $screen_reader = __( 'Error' ); $message = sprintf( /* translators: %s: The module name. */ @@ -1030,7 +1062,8 @@ $library ); } else { - $class = 'warning'; + $class = 'warning'; + /* translators: Hidden accessibility text. */ $screen_reader = __( 'Warning' ); $message = sprintf( /* translators: %s: The module name. */ @@ -1075,7 +1108,7 @@ } /** - * Test if the PHP default timezone is set to UTC. + * Tests if the PHP default timezone is set to UTC. * * @since 5.3.1 * @@ -1116,7 +1149,7 @@ } /** - * Test if there's an active PHP session that can affect loopback requests. + * Tests if there's an active PHP session that can affect loopback requests. * * @since 5.5.0 * @@ -1162,7 +1195,7 @@ } /** - * Test if the SQL server is up to date. + * Tests if the SQL server is up to date. * * @since 5.2.0 * @@ -1185,11 +1218,11 @@ __( 'The SQL server is a required piece of software for the database WordPress uses to store all your site’s content and settings.' ) ), 'actions' => sprintf( - '

%s %s

', + '

%s %s

', /* translators: Localized version of WordPress requirements if one exists. */ esc_url( __( 'https://wordpress.org/about/requirements/' ) ), __( 'Learn more about what WordPress requires to run.' ), - /* translators: Accessibility text. */ + /* translators: Hidden accessibility text. */ __( '(opens in a new tab)' ) ), 'test' => 'sql_server', @@ -1197,7 +1230,7 @@ $db_dropin = file_exists( WP_CONTENT_DIR . '/db.php' ); - if ( ! $this->mysql_rec_version_check ) { + if ( ! $this->is_recommended_mysql_version ) { $result['status'] = 'recommended'; $result['label'] = __( 'Outdated SQL server' ); @@ -1208,12 +1241,12 @@ /* translators: 1: The database engine in use (MySQL or MariaDB). 2: Database server recommended version number. */ __( 'For optimal performance and security reasons, you should consider running %1$s version %2$s or higher. Contact your web hosting company to correct this.' ), ( $this->is_mariadb ? 'MariaDB' : 'MySQL' ), - $this->health_check_mysql_rec_version + $this->mysql_recommended_version ) ); } - if ( ! $this->mysql_min_version_check ) { + if ( ! $this->is_acceptable_mysql_version ) { $result['status'] = 'critical'; $result['label'] = __( 'Severely outdated SQL server' ); @@ -1225,7 +1258,7 @@ /* translators: 1: The database engine in use (MySQL or MariaDB). 2: Database server minimum version number. */ __( 'WordPress requires %1$s version %2$s or higher. Contact your web hosting company to correct this.' ), ( $this->is_mariadb ? 'MariaDB' : 'MySQL' ), - $this->health_check_mysql_required_version + $this->mysql_required_version ) ); } @@ -1251,128 +1284,7 @@ } /** - * Test if the database server is capable of using utf8mb4. - * - * @since 5.2.0 - * - * @return array The test results. - */ - public function get_test_utf8mb4_support() { - global $wpdb; - - if ( ! $this->mysql_server_version ) { - $this->prepare_sql_data(); - } - - $result = array( - 'label' => __( 'UTF8MB4 is supported' ), - 'status' => 'good', - 'badge' => array( - 'label' => __( 'Performance' ), - 'color' => 'blue', - ), - 'description' => sprintf( - '

%s

', - __( 'UTF8MB4 is the character set WordPress prefers for database storage because it safely supports the widest set of characters and encodings, including Emoji, enabling better support for non-English languages.' ) - ), - 'actions' => '', - 'test' => 'utf8mb4_support', - ); - - if ( ! $this->is_mariadb ) { - if ( version_compare( $this->mysql_server_version, '5.5.3', '<' ) ) { - $result['status'] = 'recommended'; - - $result['label'] = __( 'utf8mb4 requires a MySQL update' ); - - $result['description'] .= sprintf( - '

%s

', - sprintf( - /* translators: %s: Version number. */ - __( 'WordPress’ utf8mb4 support requires MySQL version %s or greater. Please contact your server administrator.' ), - '5.5.3' - ) - ); - } else { - $result['description'] .= sprintf( - '

%s

', - __( 'Your MySQL version supports utf8mb4.' ) - ); - } - } else { // MariaDB introduced utf8mb4 support in 5.5.0. - if ( version_compare( $this->mysql_server_version, '5.5.0', '<' ) ) { - $result['status'] = 'recommended'; - - $result['label'] = __( 'utf8mb4 requires a MariaDB update' ); - - $result['description'] .= sprintf( - '

%s

', - sprintf( - /* translators: %s: Version number. */ - __( 'WordPress’ utf8mb4 support requires MariaDB version %s or greater. Please contact your server administrator.' ), - '5.5.0' - ) - ); - } else { - $result['description'] .= sprintf( - '

%s

', - __( 'Your MariaDB version supports utf8mb4.' ) - ); - } - } - - if ( $wpdb->use_mysqli ) { - // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_client_info - $mysql_client_version = mysqli_get_client_info(); - } else { - // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_client_info,PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved - $mysql_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( $mysql_client_version, 'mysqlnd' ) ) { - $mysql_client_version = preg_replace( '/^\D+([\d.]+).*/', '$1', $mysql_client_version ); - if ( version_compare( $mysql_client_version, '5.0.9', '<' ) ) { - $result['status'] = 'recommended'; - - $result['label'] = __( 'utf8mb4 requires a newer client library' ); - - $result['description'] .= sprintf( - '

%s

', - sprintf( - /* translators: 1: Name of the library, 2: Number of version. */ - __( 'WordPress’ utf8mb4 support requires MySQL client library (%1$s) version %2$s or newer. Please contact your server administrator.' ), - 'mysqlnd', - '5.0.9' - ) - ); - } - } else { - if ( version_compare( $mysql_client_version, '5.5.3', '<' ) ) { - $result['status'] = 'recommended'; - - $result['label'] = __( 'utf8mb4 requires a newer client library' ); - - $result['description'] .= sprintf( - '

%s

', - sprintf( - /* translators: 1: Name of the library, 2: Number of version. */ - __( 'WordPress’ utf8mb4 support requires MySQL client library (%1$s) version %2$s or newer. Please contact your server administrator.' ), - 'libmysql', - '5.5.3' - ) - ); - } - } - - return $result; - } - - /** - * Test if the site can communicate with WordPress.org. + * Tests if the site can communicate with WordPress.org. * * @since 5.2.0 * @@ -1411,6 +1323,7 @@ '

%s

', sprintf( '%s %s', + /* translators: Hidden accessibility text. */ __( 'Error' ), sprintf( /* translators: 1: The IP address WordPress.org resolves to. 2: The error returned by the lookup. */ @@ -1422,11 +1335,11 @@ ); $result['actions'] = sprintf( - '

%s %s

', + '

%s %s

', /* translators: Localized Support reference. */ - esc_url( __( 'https://wordpress.org/support' ) ), + esc_url( __( 'https://wordpress.org/support/forums/' ) ), __( 'Get help resolving this issue.' ), - /* translators: Accessibility text. */ + /* translators: Hidden accessibility text. */ __( '(opens in a new tab)' ) ); } @@ -1435,7 +1348,7 @@ } /** - * Test if debug information is enabled. + * Tests if debug information is enabled. * * When WP_DEBUG is enabled, errors and information may be disclosed to site visitors, * or logged to a publicly accessible file. @@ -1460,11 +1373,11 @@ __( 'Debug mode is often enabled to gather more details about an error or site failure, but may contain sensitive information which should not be available on a publicly available website.' ) ), 'actions' => sprintf( - '

%s %s

', + '

%s %s

', /* translators: Documentation explaining debugging in WordPress. */ - esc_url( __( 'https://wordpress.org/support/article/debugging-in-wordpress/' ) ), + esc_url( __( 'https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/' ) ), __( 'Learn more about debugging in WordPress.' ), - /* translators: Accessibility text. */ + /* translators: Hidden accessibility text. */ __( '(opens in a new tab)' ) ), 'test' => 'is_in_debug_mode', @@ -1474,7 +1387,7 @@ if ( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) { $result['label'] = __( 'Your site is set to log errors to a potentially public file' ); - $result['status'] = ( 0 === strpos( ini_get( 'error_log' ), ABSPATH ) ) ? 'critical' : 'recommended'; + $result['status'] = str_starts_with( ini_get( 'error_log' ), ABSPATH ) ? 'critical' : 'recommended'; $result['description'] .= sprintf( '

%s

', @@ -1512,7 +1425,7 @@ } /** - * Test if your site is serving content over HTTPS. + * Tests if the site is serving content over HTTPS. * * Many sites have varying degrees of HTTPS support, the most common of which is sites that have it * enabled, but only if you visit the right site address. @@ -1523,9 +1436,10 @@ * @return array The test results. */ public function get_test_https_status() { - // Enforce fresh HTTPS detection results. This is normally invoked by using cron, - // but for Site Health it should always rely on the latest results. - wp_update_https_detection_errors(); + /* + * Check HTTPS detection results. + */ + $errors = wp_get_https_detection_errors(); $default_update_url = wp_get_default_update_https_url(); @@ -1544,15 +1458,17 @@ '

%s %s

', esc_url( $default_update_url ), __( 'Learn more about why you should use HTTPS' ), - /* translators: Accessibility text. */ + /* translators: Hidden accessibility text. */ __( '(opens in a new tab)' ) ), 'test' => 'https_status', ); if ( ! wp_is_using_https() ) { - // If the website is not using HTTPS, provide more information - // about whether it is supported and how it can be enabled. + /* + * If the website is not using HTTPS, provide more information + * about whether it is supported and how it can be enabled. + */ $result['status'] = 'recommended'; $result['label'] = __( 'Your website does not use HTTPS' ); @@ -1626,7 +1542,7 @@ '

%2$s %3$s

', esc_url( $direct_update_url ), __( 'Update your site to use HTTPS' ), - /* translators: Accessibility text. */ + /* translators: Hidden accessibility text. */ __( '(opens in a new tab)' ) ); } else { @@ -1645,7 +1561,7 @@ '

%s %s

', esc_url( $update_url ), __( 'Talk to your web host about supporting HTTPS for your website.' ), - /* translators: Accessibility text. */ + /* translators: Hidden accessibility text. */ __( '(opens in a new tab)' ) ); } else { @@ -1661,11 +1577,11 @@ } /** - * Check if the HTTP API can handle SSL/TLS requests. + * Checks if the HTTP API can handle SSL/TLS requests. * * @since 5.2.0 * - * @return array The test results. + * @return array The test result. */ public function get_test_ssl_support() { $result = array( @@ -1704,7 +1620,7 @@ } /** - * Test if scheduled events run as intended. + * Tests if scheduled events run as intended. * * If scheduled events are not running, this may indicate something with WP_Cron is not working * as intended, or that there are orphaned events hanging around from older code. @@ -1776,7 +1692,7 @@ } /** - * Test if WordPress can run automated background updates. + * Tests if WordPress can run automated background updates. * * Background updates in WordPress are primarily used for minor releases and security updates. * It's important to either have these working, or be aware that they are intentionally disabled @@ -1806,14 +1722,17 @@ require_once ABSPATH . 'wp-admin/includes/class-wp-site-health-auto-updates.php'; } - // Run the auto-update tests in a separate class, - // as there are many considerations to be made. + /* + * Run the auto-update tests in a separate class, + * as there are many considerations to be made. + */ $automatic_updates = new WP_Site_Health_Auto_Updates(); $tests = $automatic_updates->run_tests(); $output = '