changeset 19 | 3d72ae0968f4 |
parent 18 | be944660c56a |
child 21 | 48c4eec2b7e6 |
18:be944660c56a | 19:3d72ae0968f4 |
---|---|
282 $core_current_version |
282 $core_current_version |
283 ); |
283 ); |
284 |
284 |
285 $result['description'] = sprintf( |
285 $result['description'] = sprintf( |
286 '<p>%s</p>', |
286 '<p>%s</p>', |
287 __( 'We were unable to check if any new versions of WordPress are available.' ) |
287 __( 'Unable to check if any new versions of WordPress are available.' ) |
288 ); |
288 ); |
289 |
289 |
290 $result['actions'] = sprintf( |
290 $result['actions'] = sprintf( |
291 '<a href="%s">%s</a>', |
291 '<a href="%s">%s</a>', |
292 esc_url( admin_url( 'update-core.php?force-check=1' ) ), |
292 esc_url( admin_url( 'update-core.php?force-check=1' ) ), |
465 'Your site has %d inactive plugins.', |
465 'Your site has %d inactive plugins.', |
466 $unused_plugins |
466 $unused_plugins |
467 ), |
467 ), |
468 $unused_plugins |
468 $unused_plugins |
469 ), |
469 ), |
470 __( 'Inactive plugins are tempting targets for attackers. If you’re not going to use a plugin, we recommend you remove it.' ) |
470 __( 'Inactive plugins are tempting targets for attackers. If you are not going to use a plugin, you should consider removing it.' ) |
471 ); |
471 ); |
472 |
472 |
473 $result['actions'] .= sprintf( |
473 $result['actions'] .= sprintf( |
474 '<p><a href="%s">%s</a></p>', |
474 '<p><a href="%s">%s</a></p>', |
475 esc_url( admin_url( 'plugins.php?plugin_status=inactive' ) ), |
475 esc_url( admin_url( 'plugins.php?plugin_status=inactive' ) ), |
632 ), |
632 ), |
633 $themes_inactive |
633 $themes_inactive |
634 ), |
634 ), |
635 sprintf( |
635 sprintf( |
636 /* translators: 1: The currently active theme. 2: The active theme's parent theme. */ |
636 /* translators: 1: The currently active theme. 2: The active theme's parent theme. */ |
637 __( 'To enhance your site’s security, we recommend you remove any themes you’re not using. You should keep your current theme, %1$s, and %2$s, its parent theme.' ), |
637 __( 'To enhance your site’s security, you should consider removing any themes you are not using. You should keep your active theme, %1$s, and %2$s, its parent theme.' ), |
638 $active_theme->name, |
638 $active_theme->name, |
639 $active_theme->parent()->name |
639 $active_theme->parent()->name |
640 ) |
640 ) |
641 ); |
641 ); |
642 } else { |
642 } else { |
651 ), |
651 ), |
652 $themes_inactive |
652 $themes_inactive |
653 ), |
653 ), |
654 sprintf( |
654 sprintf( |
655 /* translators: 1: The default theme for WordPress. 2: The currently active theme. 3: The active theme's parent theme. */ |
655 /* translators: 1: The default theme for WordPress. 2: The currently active theme. 3: The active theme's parent theme. */ |
656 __( 'To enhance your site’s security, we recommend you remove any themes you’re not using. You should keep %1$s, the default WordPress theme, %2$s, your current theme, and %3$s, its parent theme.' ), |
656 __( 'To enhance your site’s security, you should consider removing any themes you are not using. You should keep %1$s, the default WordPress theme, %2$s, your active theme, and %3$s, its parent theme.' ), |
657 $default_theme ? $default_theme->name : WP_DEFAULT_THEME, |
657 $default_theme ? $default_theme->name : WP_DEFAULT_THEME, |
658 $active_theme->name, |
658 $active_theme->name, |
659 $active_theme->parent()->name |
659 $active_theme->parent()->name |
660 ) |
660 ) |
661 ); |
661 ); |
677 $themes_inactive |
677 $themes_inactive |
678 ), |
678 ), |
679 $themes_inactive, |
679 $themes_inactive, |
680 $active_theme->name |
680 $active_theme->name |
681 ), |
681 ), |
682 __( 'We recommend removing any unused themes to enhance your site’s security.' ) |
682 __( 'You should consider removing any unused themes to enhance your site’s security.' ) |
683 ); |
683 ); |
684 } else { |
684 } else { |
685 $result['description'] .= sprintf( |
685 $result['description'] .= sprintf( |
686 '<p>%s %s</p>', |
686 '<p>%s %s</p>', |
687 sprintf( |
687 sprintf( |
693 ), |
693 ), |
694 $themes_inactive, |
694 $themes_inactive, |
695 $default_theme ? $default_theme->name : WP_DEFAULT_THEME, |
695 $default_theme ? $default_theme->name : WP_DEFAULT_THEME, |
696 $active_theme->name |
696 $active_theme->name |
697 ), |
697 ), |
698 __( 'We recommend removing any unused themes to enhance your site’s security.' ) |
698 __( 'You should consider removing any unused themes to enhance your site’s security.' ) |
699 ); |
699 ); |
700 } |
700 } |
701 } |
701 } |
702 } |
702 } |
703 |
703 |
800 * Check if the passed extension or function are available. |
800 * Check if the passed extension or function are available. |
801 * |
801 * |
802 * Make the check for available PHP modules into a simple boolean operator for a cleaner test runner. |
802 * Make the check for available PHP modules into a simple boolean operator for a cleaner test runner. |
803 * |
803 * |
804 * @since 5.2.0 |
804 * @since 5.2.0 |
805 * @since 5.3.0 The `$constant` and `$class` parameters were added. |
805 * @since 5.3.0 The `$constant_name` and `$class_name` parameters were added. |
806 * |
806 * |
807 * @param string $extension Optional. The extension name to test. Default null. |
807 * @param string $extension_name Optional. The extension name to test. Default null. |
808 * @param string $function Optional. The function name to test. Default null. |
808 * @param string $function_name Optional. The function name to test. Default null. |
809 * @param string $constant Optional. The constant name to test for. Default null. |
809 * @param string $constant_name Optional. The constant name to test for. Default null. |
810 * @param string $class Optional. The class name to test for. Default null. |
810 * @param string $class_name Optional. The class name to test for. Default null. |
811 * @return bool Whether or not the extension and function are available. |
811 * @return bool Whether or not the extension and function are available. |
812 */ |
812 */ |
813 private function test_php_extension_availability( $extension = null, $function = null, $constant = null, $class = null ) { |
813 private function test_php_extension_availability( $extension_name = null, $function_name = null, $constant_name = null, $class_name = null ) { |
814 // If no extension or function is passed, claim to fail testing, as we have nothing to test against. |
814 // If no extension or function is passed, claim to fail testing, as we have nothing to test against. |
815 if ( ! $extension && ! $function && ! $constant && ! $class ) { |
815 if ( ! $extension_name && ! $function_name && ! $constant_name && ! $class_name ) { |
816 return false; |
816 return false; |
817 } |
817 } |
818 |
818 |
819 if ( $extension && ! extension_loaded( $extension ) ) { |
819 if ( $extension_name && ! extension_loaded( $extension_name ) ) { |
820 return false; |
820 return false; |
821 } |
821 } |
822 if ( $function && ! function_exists( $function ) ) { |
822 |
823 if ( $function_name && ! function_exists( $function_name ) ) { |
|
823 return false; |
824 return false; |
824 } |
825 } |
825 if ( $constant && ! defined( $constant ) ) { |
826 |
827 if ( $constant_name && ! defined( $constant_name ) ) { |
|
826 return false; |
828 return false; |
827 } |
829 } |
828 if ( $class && ! class_exists( $class ) ) { |
830 |
831 if ( $class_name && ! class_exists( $class_name ) ) { |
|
829 return false; |
832 return false; |
830 } |
833 } |
831 |
834 |
832 return true; |
835 return true; |
833 } |
836 } |
889 ), |
892 ), |
890 'hash' => array( |
893 'hash' => array( |
891 'function' => 'hash', |
894 'function' => 'hash', |
892 'required' => false, |
895 'required' => false, |
893 ), |
896 ), |
897 'imagick' => array( |
|
898 'extension' => 'imagick', |
|
899 'required' => false, |
|
900 ), |
|
894 'json' => array( |
901 'json' => array( |
895 'function' => 'json_last_error', |
902 'function' => 'json_last_error', |
896 'required' => true, |
903 'required' => true, |
897 ), |
904 ), |
898 'mbstring' => array( |
905 'mbstring' => array( |
914 ), |
921 ), |
915 'pcre' => array( |
922 'pcre' => array( |
916 'function' => 'preg_match', |
923 'function' => 'preg_match', |
917 'required' => false, |
924 'required' => false, |
918 ), |
925 ), |
919 'imagick' => array( |
|
920 'extension' => 'imagick', |
|
921 'required' => false, |
|
922 ), |
|
923 'mod_xml' => array( |
926 'mod_xml' => array( |
924 'extension' => 'libxml', |
927 'extension' => 'libxml', |
925 'required' => false, |
928 'required' => false, |
926 ), |
929 ), |
927 'zip' => array( |
930 'zip' => array( |
938 'fallback_for' => 'imagick', |
941 'fallback_for' => 'imagick', |
939 ), |
942 ), |
940 'iconv' => array( |
943 'iconv' => array( |
941 'function' => 'iconv', |
944 'function' => 'iconv', |
942 'required' => false, |
945 'required' => false, |
946 ), |
|
947 'intl' => array( |
|
948 'extension' => 'intl', |
|
949 'required' => false, |
|
943 ), |
950 ), |
944 'mcrypt' => array( |
951 'mcrypt' => array( |
945 'extension' => 'mcrypt', |
952 'extension' => 'mcrypt', |
946 'required' => false, |
953 'required' => false, |
947 'fallback_for' => 'libsodium', |
954 'fallback_for' => 'libsodium', |
988 $modules = apply_filters( 'site_status_test_php_modules', $modules ); |
995 $modules = apply_filters( 'site_status_test_php_modules', $modules ); |
989 |
996 |
990 $failures = array(); |
997 $failures = array(); |
991 |
998 |
992 foreach ( $modules as $library => $module ) { |
999 foreach ( $modules as $library => $module ) { |
993 $extension = ( isset( $module['extension'] ) ? $module['extension'] : null ); |
1000 $extension_name = ( isset( $module['extension'] ) ? $module['extension'] : null ); |
994 $function = ( isset( $module['function'] ) ? $module['function'] : null ); |
1001 $function_name = ( isset( $module['function'] ) ? $module['function'] : null ); |
995 $constant = ( isset( $module['constant'] ) ? $module['constant'] : null ); |
1002 $constant_name = ( isset( $module['constant'] ) ? $module['constant'] : null ); |
996 $class_name = ( isset( $module['class'] ) ? $module['class'] : null ); |
1003 $class_name = ( isset( $module['class'] ) ? $module['class'] : null ); |
997 |
1004 |
998 // If this module is a fallback for another function, check if that other function passed. |
1005 // If this module is a fallback for another function, check if that other function passed. |
999 if ( isset( $module['fallback_for'] ) ) { |
1006 if ( isset( $module['fallback_for'] ) ) { |
1000 /* |
1007 /* |
1001 * If that other function has a failure, mark this module as required for usual operations. |
1008 * If that other function has a failure, mark this module as required for usual operations. |
1006 } else { |
1013 } else { |
1007 continue; |
1014 continue; |
1008 } |
1015 } |
1009 } |
1016 } |
1010 |
1017 |
1011 if ( ! $this->test_php_extension_availability( $extension, $function, $constant, $class_name ) && ( ! isset( $module['php_bundled_version'] ) || version_compare( PHP_VERSION, $module['php_bundled_version'], '<' ) ) ) { |
1018 if ( ! $this->test_php_extension_availability( $extension_name, $function_name, $constant_name, $class_name ) |
1019 && ( ! isset( $module['php_bundled_version'] ) |
|
1020 || version_compare( PHP_VERSION, $module['php_bundled_version'], '<' ) ) |
|
1021 ) { |
|
1012 if ( $module['required'] ) { |
1022 if ( $module['required'] ) { |
1013 $result['status'] = 'critical'; |
1023 $result['status'] = 'critical'; |
1014 |
1024 |
1015 $class = 'error'; |
1025 $class = 'error'; |
1016 $screen_reader = __( 'Error' ); |
1026 $screen_reader = __( 'Error' ); |
1194 |
1204 |
1195 $result['description'] .= sprintf( |
1205 $result['description'] .= sprintf( |
1196 '<p>%s</p>', |
1206 '<p>%s</p>', |
1197 sprintf( |
1207 sprintf( |
1198 /* translators: 1: The database engine in use (MySQL or MariaDB). 2: Database server recommended version number. */ |
1208 /* translators: 1: The database engine in use (MySQL or MariaDB). 2: Database server recommended version number. */ |
1199 __( 'For optimal performance and security reasons, we recommend running %1$s version %2$s or higher. Contact your web hosting company to correct this.' ), |
1209 __( '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.' ), |
1200 ( $this->is_mariadb ? 'MariaDB' : 'MySQL' ), |
1210 ( $this->is_mariadb ? 'MariaDB' : 'MySQL' ), |
1201 $this->health_check_mysql_rec_version |
1211 $this->health_check_mysql_rec_version |
1202 ) |
1212 ) |
1203 ); |
1213 ); |
1204 } |
1214 } |
1460 'test' => 'is_in_debug_mode', |
1470 'test' => 'is_in_debug_mode', |
1461 ); |
1471 ); |
1462 |
1472 |
1463 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { |
1473 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { |
1464 if ( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) { |
1474 if ( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) { |
1465 $result['label'] = __( 'Your site is set to log errors to a potentially public file.' ); |
1475 $result['label'] = __( 'Your site is set to log errors to a potentially public file' ); |
1466 |
1476 |
1467 $result['status'] = ( 0 === strpos( ini_get( 'error_log' ), ABSPATH ) ) ? 'critical' : 'recommended'; |
1477 $result['status'] = ( 0 === strpos( ini_get( 'error_log' ), ABSPATH ) ) ? 'critical' : 'recommended'; |
1468 |
1478 |
1469 $result['description'] .= sprintf( |
1479 $result['description'] .= sprintf( |
1470 '<p>%s</p>', |
1480 '<p>%s</p>', |
2106 * |
2116 * |
2107 * @return array The test results. |
2117 * @return array The test results. |
2108 */ |
2118 */ |
2109 public function get_test_file_uploads() { |
2119 public function get_test_file_uploads() { |
2110 $result = array( |
2120 $result = array( |
2111 'label' => __( 'Files can be uploaded.' ), |
2121 'label' => __( 'Files can be uploaded' ), |
2112 'status' => 'good', |
2122 'status' => 'good', |
2113 'badge' => array( |
2123 'badge' => array( |
2114 'label' => __( 'Performance' ), |
2124 'label' => __( 'Performance' ), |
2115 'color' => 'blue', |
2125 'color' => 'blue', |
2116 ), |
2126 ), |
2155 $upload_max_filesize = ini_get( 'upload_max_filesize' ); |
2165 $upload_max_filesize = ini_get( 'upload_max_filesize' ); |
2156 |
2166 |
2157 if ( wp_convert_hr_to_bytes( $post_max_size ) < wp_convert_hr_to_bytes( $upload_max_filesize ) ) { |
2167 if ( wp_convert_hr_to_bytes( $post_max_size ) < wp_convert_hr_to_bytes( $upload_max_filesize ) ) { |
2158 $result['label'] = sprintf( |
2168 $result['label'] = sprintf( |
2159 /* translators: 1: post_max_size, 2: upload_max_filesize */ |
2169 /* translators: 1: post_max_size, 2: upload_max_filesize */ |
2160 __( 'The "%1$s" value is smaller than "%2$s".' ), |
2170 __( 'The "%1$s" value is smaller than "%2$s"' ), |
2161 'post_max_size', |
2171 'post_max_size', |
2162 'upload_max_filesize' |
2172 'upload_max_filesize' |
2163 ); |
2173 ); |
2164 $result['status'] = 'recommended'; |
2174 $result['status'] = 'recommended'; |
2165 |
2175 |
2198 * |
2208 * |
2199 * @return array |
2209 * @return array |
2200 */ |
2210 */ |
2201 public function get_test_authorization_header() { |
2211 public function get_test_authorization_header() { |
2202 $result = array( |
2212 $result = array( |
2203 'label' => __( 'The Authorization header is working as expected.' ), |
2213 'label' => __( 'The Authorization header is working as expected' ), |
2204 'status' => 'good', |
2214 'status' => 'good', |
2205 'badge' => array( |
2215 'badge' => array( |
2206 'label' => __( 'Security' ), |
2216 'label' => __( 'Security' ), |
2207 'color' => 'blue', |
2217 'color' => 'blue', |
2208 ), |
2218 ), |
2213 'actions' => '', |
2223 'actions' => '', |
2214 'test' => 'authorization_header', |
2224 'test' => 'authorization_header', |
2215 ); |
2225 ); |
2216 |
2226 |
2217 if ( ! isset( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) ) { |
2227 if ( ! isset( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) ) { |
2218 $result['label'] = __( 'The authorization header is missing.' ); |
2228 $result['label'] = __( 'The authorization header is missing' ); |
2219 } elseif ( 'user' !== $_SERVER['PHP_AUTH_USER'] || 'pwd' !== $_SERVER['PHP_AUTH_PW'] ) { |
2229 } elseif ( 'user' !== $_SERVER['PHP_AUTH_USER'] || 'pwd' !== $_SERVER['PHP_AUTH_PW'] ) { |
2220 $result['label'] = __( 'The authorization header is invalid.' ); |
2230 $result['label'] = __( 'The authorization header is invalid' ); |
2221 } else { |
2231 } else { |
2222 return $result; |
2232 return $result; |
2223 } |
2233 } |
2224 |
2234 |
2225 $result['status'] = 'recommended'; |
2235 $result['status'] = 'recommended'; |
2369 |
2379 |
2370 /** |
2380 /** |
2371 * Add or modify which site status tests are run on a site. |
2381 * Add or modify which site status tests are run on a site. |
2372 * |
2382 * |
2373 * The site health is determined by a set of tests based on best practices from |
2383 * The site health is determined by a set of tests based on best practices from |
2374 * both the WordPress Hosting Team, but also web standards in general. |
2384 * both the WordPress Hosting Team and web standards in general. |
2375 * |
2385 * |
2376 * Some sites may not have the same requirements, for example the automatic update |
2386 * Some sites may not have the same requirements, for example the automatic update |
2377 * checks may be handled by a host, and are therefore disabled in core. |
2387 * checks may be handled by a host, and are therefore disabled in core. |
2378 * Or maybe you want to introduce a new test, is caching enabled/disabled/stale for example. |
2388 * Or maybe you want to introduce a new test, is caching enabled/disabled/stale for example. |
2379 * |
2389 * |
2380 * Tests may be added either as direct, or asynchronous ones. Any test that may require some time |
2390 * Tests may be added either as direct, or asynchronous ones. Any test that may require some time |
2381 * to complete should run asynchronously, to avoid extended loading periods within wp-admin. |
2391 * to complete should run asynchronously, to avoid extended loading periods within wp-admin. |
2382 * |
2392 * |
2383 * @since 5.2.0 |
2393 * @since 5.2.0 |
2384 * @since 5.6.0 Added the `async_direct_test` array key. |
2394 * @since 5.6.0 Added the `async_direct_test` array key for asynchronous tests. |
2385 * Added the `skip_cron` array key. |
2395 * Added the `skip_cron` array key for all tests. |
2386 * |
2396 * |
2387 * @param array $test_type { |
2397 * @param array[] $tests { |
2388 * An associative array, where the `$test_type` is either `direct` or |
2398 * An associative array of direct and asynchronous tests. |
2389 * `async`, to declare if the test should run via Ajax calls after page load. |
|
2390 * |
2399 * |
2391 * @type array $identifier { |
2400 * @type array[] $direct { |
2392 * `$identifier` should be a unique identifier for the test that should run. |
2401 * An array of direct tests. |
2393 * Plugins and themes are encouraged to prefix test identifiers with their slug |
|
2394 * to avoid any collisions between tests. |
|
2395 * |
2402 * |
2396 * @type string $label A friendly label for your test to identify it by. |
2403 * @type array ...$identifier { |
2397 * @type mixed $test A callable to perform a direct test, or a string AJAX action |
2404 * `$identifier` should be a unique identifier for the test. Plugins and themes are encouraged to |
2398 * to be called to perform an async test. |
2405 * prefix test identifiers with their slug to avoid collisions between tests. |
2399 * @type boolean $has_rest Optional. Denote if `$test` has a REST API endpoint. |
2406 * |
2400 * @type boolean $skip_cron Whether to skip this test when running as cron. |
2407 * @type string $label The friendly label to identify the test. |
2401 * @type callable $async_direct_test A manner of directly calling the test marked as asynchronous, |
2408 * @type callable $test The callback function that runs the test and returns its result. |
2402 * as the scheduled event can not authenticate, and endpoints |
2409 * @type bool $skip_cron Whether to skip this test when running as cron. |
2403 * may require authentication. |
2410 * } |
2411 * } |
|
2412 * @type array[] $async { |
|
2413 * An array of asynchronous tests. |
|
2414 * |
|
2415 * @type array ...$identifier { |
|
2416 * `$identifier` should be a unique identifier for the test. Plugins and themes are encouraged to |
|
2417 * prefix test identifiers with their slug to avoid collisions between tests. |
|
2418 * |
|
2419 * @type string $label The friendly label to identify the test. |
|
2420 * @type string $test An admin-ajax.php action to be called to perform the test, or |
|
2421 * if `$has_rest` is true, a URL to a REST API endpoint to perform |
|
2422 * the test. |
|
2423 * @type bool $has_rest Whether the `$test` property points to a REST API endpoint. |
|
2424 * @type bool $skip_cron Whether to skip this test when running as cron. |
|
2425 * @type callable $async_direct_test A manner of directly calling the test marked as asynchronous, |
|
2426 * as the scheduled event can not authenticate, and endpoints |
|
2427 * may require authentication. |
|
2428 * } |
|
2404 * } |
2429 * } |
2405 * } |
2430 * } |
2406 */ |
2431 */ |
2407 $tests = apply_filters( 'site_status_tests', $tests ); |
2432 $tests = apply_filters( 'site_status_tests', $tests ); |
2408 |
2433 |
2547 * |
2572 * |
2548 * @since 5.5.0 |
2573 * @since 5.5.0 |
2549 * |
2574 * |
2550 * @return object The test results. |
2575 * @return object The test results. |
2551 */ |
2576 */ |
2552 function detect_plugin_theme_auto_update_issues() { |
2577 public function detect_plugin_theme_auto_update_issues() { |
2553 $mock_plugin = (object) array( |
2578 $mock_plugin = (object) array( |
2554 'id' => 'w.org/plugins/a-fake-plugin', |
2579 'id' => 'w.org/plugins/a-fake-plugin', |
2555 'slug' => 'a-fake-plugin', |
2580 'slug' => 'a-fake-plugin', |
2556 'plugin' => 'a-fake-plugin/a-fake-plugin.php', |
2581 'plugin' => 'a-fake-plugin/a-fake-plugin.php', |
2557 'new_version' => '9.9', |
2582 'new_version' => '9.9', |
2630 * |
2655 * |
2631 * @since 5.2.0 |
2656 * @since 5.2.0 |
2632 * |
2657 * |
2633 * @return object The test results. |
2658 * @return object The test results. |
2634 */ |
2659 */ |
2635 function can_perform_loopback() { |
2660 public function can_perform_loopback() { |
2636 $body = array( 'site-health' => 'loopback-test' ); |
2661 $body = array( 'site-health' => 'loopback-test' ); |
2637 $cookies = wp_unslash( $_COOKIE ); |
2662 $cookies = wp_unslash( $_COOKIE ); |
2638 $timeout = 10; |
2663 $timeout = 10; |
2639 $headers = array( |
2664 $headers = array( |
2640 'Cache-Control' => 'no-cache', |
2665 'Cache-Control' => 'no-cache', |