6 * @subpackage Site_Health |
6 * @subpackage Site_Health |
7 * @since 5.2.0 |
7 * @since 5.2.0 |
8 */ |
8 */ |
9 |
9 |
10 class WP_Site_Health { |
10 class WP_Site_Health { |
|
11 private static $instance = null; |
|
12 |
11 private $mysql_min_version_check; |
13 private $mysql_min_version_check; |
12 private $mysql_rec_version_check; |
14 private $mysql_rec_version_check; |
13 |
15 |
14 public $is_mariadb = false; |
16 public $is_mariadb = false; |
15 private $mysql_server_version = ''; |
17 private $mysql_server_version = ''; |
16 private $health_check_mysql_required_version = '5.5'; |
18 private $health_check_mysql_required_version = '5.5'; |
17 private $health_check_mysql_rec_version = ''; |
19 private $health_check_mysql_rec_version = ''; |
18 |
20 |
|
21 public $php_memory_limit; |
|
22 |
19 public $schedules; |
23 public $schedules; |
20 public $crons; |
24 public $crons; |
21 public $last_missed_cron = null; |
25 public $last_missed_cron = null; |
|
26 public $last_late_cron = null; |
|
27 private $timeout_missed_cron = null; |
|
28 private $timeout_late_cron = null; |
22 |
29 |
23 /** |
30 /** |
24 * WP_Site_Health constructor. |
31 * WP_Site_Health constructor. |
25 * |
32 * |
26 * @since 5.2.0 |
33 * @since 5.2.0 |
27 */ |
34 */ |
28 public function __construct() { |
35 public function __construct() { |
29 $this->prepare_sql_data(); |
36 $this->maybe_create_scheduled_event(); |
|
37 |
|
38 // Save memory limit before it's affected by wp_raise_memory_limit( 'admin' ). |
|
39 $this->php_memory_limit = ini_get( 'memory_limit' ); |
|
40 |
|
41 $this->timeout_late_cron = 0; |
|
42 $this->timeout_missed_cron = - 5 * MINUTE_IN_SECONDS; |
|
43 |
|
44 if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) { |
|
45 $this->timeout_late_cron = - 15 * MINUTE_IN_SECONDS; |
|
46 $this->timeout_missed_cron = - 1 * HOUR_IN_SECONDS; |
|
47 } |
30 |
48 |
31 add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) ); |
49 add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) ); |
32 |
50 |
33 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); |
51 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); |
|
52 add_action( 'wp_site_health_scheduled_check', array( $this, 'wp_cron_scheduled_check' ) ); |
|
53 } |
|
54 |
|
55 /** |
|
56 * Return an instance of the WP_Site_Health class, or create one if none exist yet. |
|
57 * |
|
58 * @since 5.4.0 |
|
59 * |
|
60 * @return WP_Site_Health|null |
|
61 */ |
|
62 public static function get_instance() { |
|
63 if ( null === self::$instance ) { |
|
64 self::$instance = new WP_Site_Health(); |
|
65 } |
|
66 |
|
67 return self::$instance; |
34 } |
68 } |
35 |
69 |
36 /** |
70 /** |
37 * Enqueues the site health scripts. |
71 * Enqueues the site health scripts. |
38 * |
72 * |
39 * @since 5.2.0 |
73 * @since 5.2.0 |
40 */ |
74 */ |
41 public function enqueue_scripts() { |
75 public function enqueue_scripts() { |
42 $screen = get_current_screen(); |
76 $screen = get_current_screen(); |
43 if ( 'site-health' !== $screen->id ) { |
77 if ( 'site-health' !== $screen->id && 'dashboard' !== $screen->id ) { |
44 return; |
78 return; |
45 } |
79 } |
46 |
80 |
47 $health_check_js_variables = array( |
81 $health_check_js_variables = array( |
48 'screen' => $screen->id, |
82 'screen' => $screen->id, |
107 |
141 |
108 wp_localize_script( 'site-health', 'SiteHealth', $health_check_js_variables ); |
142 wp_localize_script( 'site-health', 'SiteHealth', $health_check_js_variables ); |
109 } |
143 } |
110 |
144 |
111 /** |
145 /** |
|
146 * Run a Site Health test directly. |
|
147 * |
|
148 * @since 5.4.0 |
|
149 * |
|
150 * @param callable $callback |
|
151 * @return mixed|void |
|
152 */ |
|
153 private function perform_test( $callback ) { |
|
154 /** |
|
155 * Filter the output of a finished Site Health test. |
|
156 * |
|
157 * @since 5.3.0 |
|
158 * |
|
159 * @param array $test_result { |
|
160 * An associative array of test result data. |
|
161 * |
|
162 * @type string $label A label describing the test, and is used as a header in the output. |
|
163 * @type string $status The status of the test, which can be a value of `good`, `recommended` or `critical`. |
|
164 * @type array $badge { |
|
165 * Tests are put into categories which have an associated badge shown, these can be modified and assigned here. |
|
166 * |
|
167 * @type string $label The test label, for example `Performance`. |
|
168 * @type string $color Default `blue`. A string representing a color to use for the label. |
|
169 * } |
|
170 * @type string $description A more descriptive explanation of what the test looks for, and why it is important for the end user. |
|
171 * @type string $actions An action to direct the user to where they can resolve the issue, if one exists. |
|
172 * @type string $test The name of the test being ran, used as a reference point. |
|
173 * } |
|
174 */ |
|
175 return apply_filters( 'site_status_test_result', call_user_func( $callback ) ); |
|
176 } |
|
177 |
|
178 /** |
112 * Run the SQL version checks. |
179 * Run the SQL version checks. |
113 * |
180 * |
114 * These values are used in later tests, but the part of preparing them is more easily managed early |
181 * These values are used in later tests, but the part of preparing them is more easily managed |
115 * in the class for ease of access and discovery. |
182 * early in the class for ease of access and discovery. |
116 * |
183 * |
117 * @since 5.2.0 |
184 * @since 5.2.0 |
118 * |
185 * |
119 * @global wpdb $wpdb WordPress database abstraction object. |
186 * @global wpdb $wpdb WordPress database abstraction object. |
120 */ |
187 */ |
121 private function prepare_sql_data() { |
188 private function prepare_sql_data() { |
122 global $wpdb; |
189 global $wpdb; |
123 |
190 |
124 if ( method_exists( $wpdb, 'db_version' ) ) { |
191 if ( $wpdb->use_mysqli ) { |
125 if ( $wpdb->use_mysqli ) { |
192 // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_server_info |
126 // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_server_info |
193 $mysql_server_type = mysqli_get_server_info( $wpdb->dbh ); |
127 $mysql_server_type = mysqli_get_server_info( $wpdb->dbh ); |
194 } else { |
128 } else { |
195 // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_server_info,PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved |
129 // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_server_info |
196 $mysql_server_type = mysql_get_server_info( $wpdb->dbh ); |
130 $mysql_server_type = mysql_get_server_info( $wpdb->dbh ); |
197 } |
131 } |
198 |
132 |
199 $this->mysql_server_version = $wpdb->get_var( 'SELECT VERSION()' ); |
133 $this->mysql_server_version = $wpdb->get_var( 'SELECT VERSION()' ); |
|
134 } |
|
135 |
200 |
136 $this->health_check_mysql_rec_version = '5.6'; |
201 $this->health_check_mysql_rec_version = '5.6'; |
137 |
202 |
138 if ( stristr( $mysql_server_type, 'mariadb' ) ) { |
203 if ( stristr( $mysql_server_type, 'mariadb' ) ) { |
139 $this->is_mariadb = true; |
204 $this->is_mariadb = true; |
443 |
510 |
444 // Populate a list of all themes available in the install. |
511 // Populate a list of all themes available in the install. |
445 $all_themes = wp_get_themes(); |
512 $all_themes = wp_get_themes(); |
446 $active_theme = wp_get_theme(); |
513 $active_theme = wp_get_theme(); |
447 |
514 |
|
515 // If WP_DEFAULT_THEME doesn't exist, fall back to the latest core default theme. |
|
516 $default_theme = wp_get_theme( WP_DEFAULT_THEME ); |
|
517 if ( ! $default_theme->exists() ) { |
|
518 $default_theme = WP_Theme::get_core_default_theme(); |
|
519 } |
|
520 |
|
521 if ( $default_theme ) { |
|
522 $has_default_theme = true; |
|
523 |
|
524 if ( |
|
525 $active_theme->get_stylesheet() === $default_theme->get_stylesheet() |
|
526 || |
|
527 is_child_theme() && $active_theme->get_template() === $default_theme->get_template() |
|
528 ) { |
|
529 $using_default_theme = true; |
|
530 } |
|
531 } |
|
532 |
448 foreach ( $all_themes as $theme_slug => $theme ) { |
533 foreach ( $all_themes as $theme_slug => $theme ) { |
449 $themes_total++; |
534 $themes_total++; |
450 |
535 |
451 if ( WP_DEFAULT_THEME === $theme_slug ) { |
|
452 $has_default_theme = true; |
|
453 |
|
454 if ( get_stylesheet() === $theme_slug ) { |
|
455 $using_default_theme = true; |
|
456 } |
|
457 } |
|
458 |
|
459 if ( array_key_exists( $theme_slug, $theme_updates ) ) { |
536 if ( array_key_exists( $theme_slug, $theme_updates ) ) { |
460 $themes_need_updates++; |
537 $themes_need_updates++; |
461 } |
538 } |
462 } |
539 } |
463 |
540 |
464 // If this is a child theme, increase the allowed theme count by one, to account for the parent. |
541 // If this is a child theme, increase the allowed theme count by one, to account for the parent. |
465 if ( $active_theme->parent() ) { |
542 if ( is_child_theme() ) { |
466 $allowed_theme_count++; |
543 $allowed_theme_count++; |
467 |
|
468 if ( $active_theme->get_template() === WP_DEFAULT_THEME ) { |
|
469 $using_default_theme = true; |
|
470 } |
|
471 } |
544 } |
472 |
545 |
473 // If there's a default theme installed and not in use, we count that as allowed as well. |
546 // If there's a default theme installed and not in use, we count that as allowed as well. |
474 if ( $has_default_theme && ! $using_default_theme ) { |
547 if ( $has_default_theme && ! $using_default_theme ) { |
475 $allowed_theme_count++; |
548 $allowed_theme_count++; |
600 'Your site has %1$d inactive theme, other than %2$s, the default WordPress theme, and %3$s, your active theme.', |
673 'Your site has %1$d inactive theme, other than %2$s, the default WordPress theme, and %3$s, your active theme.', |
601 'Your site has %1$d inactive themes, other than %2$s, the default WordPress theme, and %3$s, your active theme.', |
674 'Your site has %1$d inactive themes, other than %2$s, the default WordPress theme, and %3$s, your active theme.', |
602 $themes_inactive |
675 $themes_inactive |
603 ), |
676 ), |
604 $themes_inactive, |
677 $themes_inactive, |
605 WP_DEFAULT_THEME, |
678 $default_theme ? $default_theme->name : WP_DEFAULT_THEME, |
606 $active_theme->name |
679 $active_theme->name |
607 ), |
680 ), |
608 __( 'We recommend removing any unused themes to enhance your site’s security.' ) |
681 __( 'We recommend removing any unused themes to enhance your site’s security.' ) |
609 ); |
682 ); |
610 } |
683 } |
611 } |
684 } |
612 } |
685 } |
613 |
686 |
614 // If not default Twenty* theme exists. |
687 // If no default Twenty* theme exists. |
615 if ( ! $has_default_theme ) { |
688 if ( ! $has_default_theme ) { |
616 $result['status'] = 'recommended'; |
689 $result['status'] = 'recommended'; |
617 |
690 |
618 $result['label'] = __( 'Have a default theme available' ); |
691 $result['label'] = __( 'Have a default theme available' ); |
619 |
692 |
620 $result['description'] .= sprintf( |
693 $result['description'] .= sprintf( |
621 '<p>%s</p>', |
694 '<p>%s</p>', |
622 __( 'Your site does not have any default theme. Default themes are used by WordPress automatically if anything is wrong with your normal theme.' ) |
695 __( 'Your site does not have any default theme. Default themes are used by WordPress automatically if anything is wrong with your chosen theme.' ) |
623 ); |
696 ); |
624 } |
697 } |
625 |
698 |
626 return $result; |
699 return $result; |
627 } |
700 } |
636 public function get_test_php_version() { |
709 public function get_test_php_version() { |
637 $response = wp_check_php_version(); |
710 $response = wp_check_php_version(); |
638 |
711 |
639 $result = array( |
712 $result = array( |
640 'label' => sprintf( |
713 'label' => sprintf( |
641 // translators: %s: The current PHP version. |
714 /* translators: %s: The current PHP version. */ |
642 __( 'PHP is up to date (%s)' ), |
715 __( 'Your site is running the current version of PHP (%s)' ), |
643 PHP_VERSION |
716 PHP_VERSION |
644 ), |
717 ), |
645 'status' => 'good', |
718 'status' => 'good', |
646 'badge' => array( |
719 'badge' => array( |
647 'label' => __( 'Performance' ), |
720 'label' => __( 'Performance' ), |
648 'color' => 'blue', |
721 'color' => 'blue', |
649 ), |
722 ), |
650 'description' => sprintf( |
723 'description' => sprintf( |
651 '<p>%s</p>', |
724 '<p>%s</p>', |
652 __( 'PHP is the programming language we use to build and maintain WordPress. Newer versions of PHP are both faster and more secure, so updating will have a positive effect on your site’s performance.' ) |
725 sprintf( |
|
726 /* translators: %s: The minimum recommended PHP version. */ |
|
727 __( 'PHP is the programming language used to build and maintain WordPress. Newer versions of PHP are faster and more secure, so staying up to date will help your site’s overall performance and security. The minimum recommended version of PHP is %s.' ), |
|
728 $response ? $response['recommended_version'] : '' |
|
729 ) |
653 ), |
730 ), |
654 'actions' => sprintf( |
731 'actions' => sprintf( |
655 '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>', |
732 '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>', |
656 esc_url( wp_get_update_php_url() ), |
733 esc_url( wp_get_update_php_url() ), |
657 __( 'Learn more about updating PHP' ), |
734 __( 'Learn more about updating PHP' ), |
658 /* translators: accessibility text */ |
735 /* translators: Accessibility text. */ |
659 __( '(opens in a new tab)' ) |
736 __( '(opens in a new tab)' ) |
660 ), |
737 ), |
661 'test' => 'php_version', |
738 'test' => 'php_version', |
662 ); |
739 ); |
663 |
740 |
664 // PHP is up to date. |
741 // PHP is up to date. |
665 if ( ! $response || version_compare( PHP_VERSION, $response['recommended_version'], '>=' ) ) { |
742 if ( ! $response || version_compare( PHP_VERSION, $response['recommended_version'], '>=' ) ) { |
666 return $result; |
743 return $result; |
667 } |
744 } |
668 |
745 |
669 // The PHP version is older than the recommended version, but still acceptable. |
746 // The PHP version is older than the recommended version, but still receiving active support. |
670 if ( $response['is_supported'] ) { |
747 if ( $response['is_supported'] ) { |
671 $result['label'] = __( 'We recommend that you update PHP' ); |
748 $result['label'] = sprintf( |
|
749 /* translators: %s: The server PHP version. */ |
|
750 __( 'Your site is running an older version of PHP (%s)' ), |
|
751 PHP_VERSION |
|
752 ); |
672 $result['status'] = 'recommended'; |
753 $result['status'] = 'recommended'; |
673 |
754 |
674 return $result; |
755 return $result; |
675 } |
756 } |
676 |
757 |
677 // The PHP version is only receiving security fixes. |
758 // The PHP version is only receiving security fixes. |
678 if ( $response['is_secure'] ) { |
759 if ( $response['is_secure'] ) { |
679 $result['label'] = __( 'Your PHP version should be updated' ); |
760 $result['label'] = sprintf( |
|
761 /* translators: %s: The server PHP version. */ |
|
762 __( 'Your site is running an older version of PHP (%s), which should be updated' ), |
|
763 PHP_VERSION |
|
764 ); |
680 $result['status'] = 'recommended'; |
765 $result['status'] = 'recommended'; |
681 |
766 |
682 return $result; |
767 return $result; |
683 } |
768 } |
684 |
769 |
685 // Anything no longer secure must be updated. |
770 // Anything no longer secure must be updated. |
686 $result['label'] = __( 'Your PHP version requires an update' ); |
771 $result['label'] = sprintf( |
|
772 /* translators: %s: The server PHP version. */ |
|
773 __( 'Your site is running an outdated version of PHP (%s), which requires an update' ), |
|
774 PHP_VERSION |
|
775 ); |
687 $result['status'] = 'critical'; |
776 $result['status'] = 'critical'; |
688 $result['badge']['label'] = __( 'Security' ); |
777 $result['badge']['label'] = __( 'Security' ); |
689 |
778 |
690 return $result; |
779 return $result; |
691 } |
780 } |
694 * Check if the passed extension or function are available. |
783 * Check if the passed extension or function are available. |
695 * |
784 * |
696 * Make the check for available PHP modules into a simple boolean operator for a cleaner test runner. |
785 * Make the check for available PHP modules into a simple boolean operator for a cleaner test runner. |
697 * |
786 * |
698 * @since 5.2.0 |
787 * @since 5.2.0 |
|
788 * @since 5.3.0 The `$constant` and `$class` parameters were added. |
699 * |
789 * |
700 * @param string $extension Optional. The extension name to test. Default null. |
790 * @param string $extension Optional. The extension name to test. Default null. |
701 * @param string $function Optional. The function name to test. Default null. |
791 * @param string $function Optional. The function name to test. Default null. |
702 * |
792 * @param string $constant Optional. The constant name to test for. Default null. |
|
793 * @param string $class Optional. The class name to test for. Default null. |
703 * @return bool Whether or not the extension and function are available. |
794 * @return bool Whether or not the extension and function are available. |
704 */ |
795 */ |
705 private function test_php_extension_availability( $extension = null, $function = null ) { |
796 private function test_php_extension_availability( $extension = null, $function = null, $constant = null, $class = null ) { |
706 // If no extension or function is passed, claim to fail testing, as we have nothing to test against. |
797 // If no extension or function is passed, claim to fail testing, as we have nothing to test against. |
707 if ( ! $extension && ! $function ) { |
798 if ( ! $extension && ! $function && ! $constant && ! $class ) { |
708 return false; |
799 return false; |
709 } |
800 } |
710 |
801 |
711 if ( $extension && ! extension_loaded( $extension ) ) { |
802 if ( $extension && ! extension_loaded( $extension ) ) { |
712 return false; |
803 return false; |
713 } |
804 } |
714 if ( $function && ! function_exists( $function ) ) { |
805 if ( $function && ! function_exists( $function ) ) { |
|
806 return false; |
|
807 } |
|
808 if ( $constant && ! defined( $constant ) ) { |
|
809 return false; |
|
810 } |
|
811 if ( $class && ! class_exists( $class ) ) { |
715 return false; |
812 return false; |
716 } |
813 } |
717 |
814 |
718 return true; |
815 return true; |
719 } |
816 } |
745 /* translators: Localized team handbook, if one exists. */ |
842 /* translators: Localized team handbook, if one exists. */ |
746 esc_url( __( 'https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions' ) ), |
843 esc_url( __( 'https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions' ) ), |
747 'target="_blank" rel="noopener noreferrer"', |
844 'target="_blank" rel="noopener noreferrer"', |
748 sprintf( |
845 sprintf( |
749 ' <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span>', |
846 ' <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span>', |
750 /* translators: accessibility text */ |
847 /* translators: Accessibility text. */ |
751 __( '(opens in a new tab)' ) |
848 __( '(opens in a new tab)' ) |
752 ) |
849 ) |
753 ) |
850 ) |
754 ), |
851 ), |
755 'actions' => '', |
852 'actions' => '', |
756 'test' => 'php_extensions', |
853 'test' => 'php_extensions', |
757 ); |
854 ); |
758 |
855 |
759 $modules = array( |
856 $modules = array( |
760 'bcmath' => array( |
|
761 'function' => 'bcadd', |
|
762 'required' => false, |
|
763 ), |
|
764 'curl' => array( |
857 'curl' => array( |
765 'function' => 'curl_version', |
858 'function' => 'curl_version', |
766 'required' => false, |
859 'required' => false, |
767 ), |
860 ), |
|
861 'dom' => array( |
|
862 'class' => 'DOMNode', |
|
863 'required' => false, |
|
864 ), |
768 'exif' => array( |
865 'exif' => array( |
769 'function' => 'exif_read_data', |
866 'function' => 'exif_read_data', |
770 'required' => false, |
867 'required' => false, |
771 ), |
868 ), |
|
869 'fileinfo' => array( |
|
870 'function' => 'finfo_file', |
|
871 'required' => false, |
|
872 ), |
|
873 'hash' => array( |
|
874 'function' => 'hash', |
|
875 'required' => false, |
|
876 ), |
|
877 'json' => array( |
|
878 'function' => 'json_last_error', |
|
879 'required' => true, |
|
880 ), |
|
881 'mbstring' => array( |
|
882 'function' => 'mb_check_encoding', |
|
883 'required' => false, |
|
884 ), |
|
885 'mysqli' => array( |
|
886 'function' => 'mysqli_connect', |
|
887 'required' => false, |
|
888 ), |
|
889 'libsodium' => array( |
|
890 'constant' => 'SODIUM_LIBRARY_VERSION', |
|
891 'required' => false, |
|
892 'php_bundled_version' => '7.2.0', |
|
893 ), |
|
894 'openssl' => array( |
|
895 'function' => 'openssl_encrypt', |
|
896 'required' => false, |
|
897 ), |
|
898 'pcre' => array( |
|
899 'function' => 'preg_match', |
|
900 'required' => false, |
|
901 ), |
|
902 'imagick' => array( |
|
903 'extension' => 'imagick', |
|
904 'required' => false, |
|
905 ), |
|
906 'mod_xml' => array( |
|
907 'extension' => 'libxml', |
|
908 'required' => false, |
|
909 ), |
|
910 'zip' => array( |
|
911 'class' => 'ZipArchive', |
|
912 'required' => false, |
|
913 ), |
772 'filter' => array( |
914 'filter' => array( |
773 'function' => 'filter_list', |
915 'function' => 'filter_list', |
774 'required' => false, |
916 'required' => false, |
775 ), |
|
776 'fileinfo' => array( |
|
777 'function' => 'finfo_file', |
|
778 'required' => false, |
|
779 ), |
|
780 'mod_xml' => array( |
|
781 'extension' => 'libxml', |
|
782 'required' => false, |
|
783 ), |
|
784 'mysqli' => array( |
|
785 'function' => 'mysqli_connect', |
|
786 'required' => false, |
|
787 ), |
|
788 'libsodium' => array( |
|
789 'function' => 'sodium_compare', |
|
790 'required' => false, |
|
791 'php_bundled_version' => '7.2.0', |
|
792 ), |
|
793 'openssl' => array( |
|
794 'function' => 'openssl_encrypt', |
|
795 'required' => false, |
|
796 ), |
|
797 'pcre' => array( |
|
798 'function' => 'preg_match', |
|
799 'required' => false, |
|
800 ), |
|
801 'imagick' => array( |
|
802 'extension' => 'imagick', |
|
803 'required' => false, |
|
804 ), |
917 ), |
805 'gd' => array( |
918 'gd' => array( |
806 'extension' => 'gd', |
919 'extension' => 'gd', |
807 'required' => false, |
920 'required' => false, |
808 'fallback_for' => 'imagick', |
921 'fallback_for' => 'imagick', |
809 ), |
922 ), |
|
923 'iconv' => array( |
|
924 'function' => 'iconv', |
|
925 'required' => false, |
|
926 ), |
810 'mcrypt' => array( |
927 'mcrypt' => array( |
811 'extension' => 'mcrypt', |
928 'extension' => 'mcrypt', |
812 'required' => false, |
929 'required' => false, |
813 'fallback_for' => 'libsodium', |
930 'fallback_for' => 'libsodium', |
814 ), |
931 ), |
|
932 'simplexml' => array( |
|
933 'extension' => 'simplexml', |
|
934 'required' => false, |
|
935 'fallback_for' => 'mod_xml', |
|
936 ), |
815 'xmlreader' => array( |
937 'xmlreader' => array( |
816 'extension' => 'xmlreader', |
938 'extension' => 'xmlreader', |
817 'required' => false, |
939 'required' => false, |
818 'fallback_for' => 'xml', |
940 'fallback_for' => 'mod_xml', |
819 ), |
941 ), |
820 'zlib' => array( |
942 'zlib' => array( |
821 'extension' => 'zlib', |
943 'extension' => 'zlib', |
822 'required' => false, |
944 'required' => false, |
823 'fallback_for' => 'zip', |
945 'fallback_for' => 'zip', |
826 |
948 |
827 /** |
949 /** |
828 * An array representing all the modules we wish to test for. |
950 * An array representing all the modules we wish to test for. |
829 * |
951 * |
830 * @since 5.2.0 |
952 * @since 5.2.0 |
|
953 * @since 5.3.0 The `$constant` and `$class` parameters were added. |
831 * |
954 * |
832 * @param array $modules { |
955 * @param array $modules { |
833 * An associated array of modules to test for. |
956 * An associative array of modules to test for. |
834 * |
957 * |
835 * array $module { |
958 * @type array ...$0 { |
836 * An associated array of module properties used during testing. |
959 * An associative array of module properties used during testing. |
837 * One of either `$function` or `$extension` must be provided, or they will fail by default. |
960 * One of either `$function` or `$extension` must be provided, or they will fail by default. |
838 * |
961 * |
839 * string $function Optional. A function name to test for the existence of. |
962 * @type string $function Optional. A function name to test for the existence of. |
840 * string $extension Optional. An extension to check if is loaded in PHP. |
963 * @type string $extension Optional. An extension to check if is loaded in PHP. |
841 * bool $required Is this a required feature or not. |
964 * @type string $constant Optional. A constant name to check for to verify an extension exists. |
842 * string $fallback_for Optional. The module this module replaces as a fallback. |
965 * @type string $class Optional. A class name to check for to verify an extension exists. |
|
966 * @type bool $required Is this a required feature or not. |
|
967 * @type string $fallback_for Optional. The module this module replaces as a fallback. |
843 * } |
968 * } |
844 * } |
969 * } |
845 */ |
970 */ |
846 $modules = apply_filters( 'site_status_test_php_modules', $modules ); |
971 $modules = apply_filters( 'site_status_test_php_modules', $modules ); |
847 |
972 |
848 $failures = array(); |
973 $failures = array(); |
849 |
974 |
850 foreach ( $modules as $library => $module ) { |
975 foreach ( $modules as $library => $module ) { |
851 $extension = ( isset( $module['extension'] ) ? $module['extension'] : null ); |
976 $extension = ( isset( $module['extension'] ) ? $module['extension'] : null ); |
852 $function = ( isset( $module['function'] ) ? $module['function'] : null ); |
977 $function = ( isset( $module['function'] ) ? $module['function'] : null ); |
|
978 $constant = ( isset( $module['constant'] ) ? $module['constant'] : null ); |
|
979 $class_name = ( isset( $module['class'] ) ? $module['class'] : null ); |
853 |
980 |
854 // If this module is a fallback for another function, check if that other function passed. |
981 // If this module is a fallback for another function, check if that other function passed. |
855 if ( isset( $module['fallback_for'] ) ) { |
982 if ( isset( $module['fallback_for'] ) ) { |
856 /* |
983 /* |
857 * If that other function has a failure, mark this module as required for normal operations. |
984 * If that other function has a failure, mark this module as required for usual operations. |
858 * If that other function hasn't failed, skip this test as it's only a fallback. |
985 * If that other function hasn't failed, skip this test as it's only a fallback. |
859 */ |
986 */ |
860 if ( isset( $failures[ $module['fallback_for'] ] ) ) { |
987 if ( isset( $failures[ $module['fallback_for'] ] ) ) { |
861 $module['required'] = true; |
988 $module['required'] = true; |
862 } else { |
989 } else { |
863 continue; |
990 continue; |
864 } |
991 } |
865 } |
992 } |
866 |
993 |
867 if ( ! $this->test_php_extension_availability( $extension, $function ) && ( ! isset( $module['php_bundled_version'] ) || version_compare( PHP_VERSION, $module['php_bundled_version'], '<' ) ) ) { |
994 if ( ! $this->test_php_extension_availability( $extension, $function, $constant, $class_name ) && ( ! isset( $module['php_bundled_version'] ) || version_compare( PHP_VERSION, $module['php_bundled_version'], '<' ) ) ) { |
868 if ( $module['required'] ) { |
995 if ( $module['required'] ) { |
869 $result['status'] = 'critical'; |
996 $result['status'] = 'critical'; |
870 |
997 |
871 $class = 'error'; |
998 $class = 'error'; |
872 $screen_reader = __( 'Error' ); |
999 $screen_reader = __( 'Error' ); |
912 } |
1039 } |
913 if ( 'critical' === $result['status'] ) { |
1040 if ( 'critical' === $result['status'] ) { |
914 $result['label'] = __( 'One or more required modules are missing' ); |
1041 $result['label'] = __( 'One or more required modules are missing' ); |
915 } |
1042 } |
916 |
1043 |
917 $result['description'] .= sprintf( |
1044 $result['description'] .= $output; |
918 '<p>%s</p>', |
|
919 $output |
|
920 ); |
|
921 } |
1045 } |
922 |
1046 |
923 return $result; |
1047 return $result; |
924 } |
1048 } |
925 |
1049 |
926 /** |
1050 /** |
|
1051 * Test if the PHP default timezone is set to UTC. |
|
1052 * |
|
1053 * @since 5.3.1 |
|
1054 * |
|
1055 * @return array The test results. |
|
1056 */ |
|
1057 public function get_test_php_default_timezone() { |
|
1058 $result = array( |
|
1059 'label' => __( 'PHP default timezone is valid' ), |
|
1060 'status' => 'good', |
|
1061 'badge' => array( |
|
1062 'label' => __( 'Performance' ), |
|
1063 'color' => 'blue', |
|
1064 ), |
|
1065 'description' => sprintf( |
|
1066 '<p>%s</p>', |
|
1067 __( 'PHP default timezone was configured by WordPress on loading. This is necessary for correct calculations of dates and times.' ) |
|
1068 ), |
|
1069 'actions' => '', |
|
1070 'test' => 'php_default_timezone', |
|
1071 ); |
|
1072 |
|
1073 if ( 'UTC' !== date_default_timezone_get() ) { |
|
1074 $result['status'] = 'critical'; |
|
1075 |
|
1076 $result['label'] = __( 'PHP default timezone is invalid' ); |
|
1077 |
|
1078 $result['description'] = sprintf( |
|
1079 '<p>%s</p>', |
|
1080 sprintf( |
|
1081 /* translators: %s: date_default_timezone_set() */ |
|
1082 __( 'PHP default timezone was changed after WordPress loading by a %s function call. This interferes with correct calculations of dates and times.' ), |
|
1083 '<code>date_default_timezone_set()</code>' |
|
1084 ) |
|
1085 ); |
|
1086 } |
|
1087 |
|
1088 return $result; |
|
1089 } |
|
1090 |
|
1091 /** |
|
1092 * Test if there's an active PHP session that can affect loopback requests. |
|
1093 * |
|
1094 * @since 5.5.0 |
|
1095 * |
|
1096 * @return array The test results. |
|
1097 */ |
|
1098 public function get_test_php_sessions() { |
|
1099 $result = array( |
|
1100 'label' => __( 'No PHP sessions detected' ), |
|
1101 'status' => 'good', |
|
1102 'badge' => array( |
|
1103 'label' => __( 'Performance' ), |
|
1104 'color' => 'blue', |
|
1105 ), |
|
1106 'description' => sprintf( |
|
1107 '<p>%s</p>', |
|
1108 sprintf( |
|
1109 /* translators: 1: session_start(), 2: session_write_close() */ |
|
1110 __( 'PHP sessions created by a %1$s function call may interfere with REST API and loopback requests. An active session should be closed by %2$s before making any HTTP requests.' ), |
|
1111 '<code>session_start()</code>', |
|
1112 '<code>session_write_close()</code>' |
|
1113 ) |
|
1114 ), |
|
1115 'test' => 'php_sessions', |
|
1116 ); |
|
1117 |
|
1118 if ( function_exists( 'session_status' ) && PHP_SESSION_ACTIVE === session_status() ) { |
|
1119 $result['status'] = 'critical'; |
|
1120 |
|
1121 $result['label'] = __( 'An active PHP session was detected' ); |
|
1122 |
|
1123 $result['description'] = sprintf( |
|
1124 '<p>%s</p>', |
|
1125 sprintf( |
|
1126 /* translators: 1: session_start(), 2: session_write_close() */ |
|
1127 __( 'A PHP session was created by a %1$s function call. This interferes with REST API and loopback requests. The session should be closed by %2$s before making any HTTP requests.' ), |
|
1128 '<code>session_start()</code>', |
|
1129 '<code>session_write_close()</code>' |
|
1130 ) |
|
1131 ); |
|
1132 } |
|
1133 |
|
1134 return $result; |
|
1135 } |
|
1136 |
|
1137 /** |
927 * Test if the SQL server is up to date. |
1138 * Test if the SQL server is up to date. |
928 * |
1139 * |
929 * @since 5.2.0 |
1140 * @since 5.2.0 |
930 * |
1141 * |
931 * @return array The test results. |
1142 * @return array The test results. |
932 */ |
1143 */ |
933 public function get_test_sql_server() { |
1144 public function get_test_sql_server() { |
|
1145 if ( ! $this->mysql_server_version ) { |
|
1146 $this->prepare_sql_data(); |
|
1147 } |
|
1148 |
934 $result = array( |
1149 $result = array( |
935 'label' => __( 'SQL server is up to date' ), |
1150 'label' => __( 'SQL server is up to date' ), |
936 'status' => 'good', |
1151 'status' => 'good', |
937 'badge' => array( |
1152 'badge' => array( |
938 'label' => __( 'Performance' ), |
1153 'label' => __( 'Performance' ), |
1178 $result['actions'] = sprintf( |
1397 $result['actions'] = sprintf( |
1179 '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>', |
1398 '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>', |
1180 /* translators: Localized Support reference. */ |
1399 /* translators: Localized Support reference. */ |
1181 esc_url( __( 'https://wordpress.org/support' ) ), |
1400 esc_url( __( 'https://wordpress.org/support' ) ), |
1182 __( 'Get help resolving this issue.' ), |
1401 __( 'Get help resolving this issue.' ), |
1183 /* translators: accessibility text */ |
1402 /* translators: Accessibility text. */ |
1184 __( '(opens in a new tab)' ) |
1403 __( '(opens in a new tab)' ) |
1185 ); |
1404 ); |
1186 } |
1405 } |
1187 |
1406 |
1188 return $result; |
1407 return $result; |
1189 } |
1408 } |
1190 |
1409 |
1191 /** |
1410 /** |
1192 * Test if debug information is enabled. |
1411 * Test if debug information is enabled. |
1193 * |
1412 * |
1194 * When WP_DEBUG is enabled, errors and information may be disclosed to site visitors, or it may be |
1413 * When WP_DEBUG is enabled, errors and information may be disclosed to site visitors, |
1195 * logged to a publicly accessible file. |
1414 * or logged to a publicly accessible file. |
1196 * |
1415 * |
1197 * Debugging is also frequently left enabled after looking for errors on a site, as site owners do |
1416 * Debugging is also frequently left enabled after looking for errors on a site, |
1198 * not understand the implications of this. |
1417 * as site owners do not understand the implications of this. |
1199 * |
1418 * |
1200 * @since 5.2.0 |
1419 * @since 5.2.0 |
1201 * |
1420 * |
1202 * @return array The test results. |
1421 * @return array The test results. |
1203 */ |
1422 */ |
1215 ), |
1434 ), |
1216 'actions' => sprintf( |
1435 'actions' => sprintf( |
1217 '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>', |
1436 '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>', |
1218 /* translators: Documentation explaining debugging in WordPress. */ |
1437 /* translators: Documentation explaining debugging in WordPress. */ |
1219 esc_url( __( 'https://wordpress.org/support/article/debugging-in-wordpress/' ) ), |
1438 esc_url( __( 'https://wordpress.org/support/article/debugging-in-wordpress/' ) ), |
1220 __( 'Read about debugging in WordPress.' ), |
1439 __( 'Learn more about debugging in WordPress.' ), |
1221 /* translators: accessibility text */ |
1440 /* translators: Accessibility text. */ |
1222 __( '(opens in a new tab)' ) |
1441 __( '(opens in a new tab)' ) |
1223 ), |
1442 ), |
1224 'test' => 'is_in_debug_mode', |
1443 'test' => 'is_in_debug_mode', |
1225 ); |
1444 ); |
1226 |
1445 |
1227 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { |
1446 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { |
1228 if ( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) { |
1447 if ( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) { |
1229 $result['label'] = __( 'Your site is set to log errors to a potentially public file.' ); |
1448 $result['label'] = __( 'Your site is set to log errors to a potentially public file.' ); |
1230 |
1449 |
1231 $result['status'] = 'critical'; |
1450 $result['status'] = ( 0 === strpos( ini_get( 'error_log' ), ABSPATH ) ) ? 'critical' : 'recommended'; |
1232 |
1451 |
1233 $result['description'] .= sprintf( |
1452 $result['description'] .= sprintf( |
1234 '<p>%s</p>', |
1453 '<p>%s</p>', |
1235 sprintf( |
1454 sprintf( |
1236 /* translators: %s: WP_DEBUG_LOG */ |
1455 /* translators: %s: WP_DEBUG_LOG */ |
1237 __( 'The value, %s, has been added to this website’s configuration file. This means any errors on the site will be written to a file which is potentially available to normal users.' ), |
1456 __( 'The value, %s, has been added to this website’s configuration file. This means any errors on the site will be written to a file which is potentially available to all users.' ), |
1238 '<code>WP_DEBUG_LOG</code>' |
1457 '<code>WP_DEBUG_LOG</code>' |
1239 ) |
1458 ) |
1240 ); |
1459 ); |
1241 } |
1460 } |
1242 |
1461 |
1278 'label' => __( 'Security' ), |
1497 'label' => __( 'Security' ), |
1279 'color' => 'blue', |
1498 'color' => 'blue', |
1280 ), |
1499 ), |
1281 'description' => sprintf( |
1500 'description' => sprintf( |
1282 '<p>%s</p>', |
1501 '<p>%s</p>', |
1283 __( 'An HTTPS connection is needed for many features on the web today, it also gains the trust of your visitors by helping to protecting their online privacy.' ) |
1502 __( 'An HTTPS connection is a more secure way of browsing the web. Many services now have HTTPS as a requirement. HTTPS allows you to take advantage of new features that can increase site speed, improve search rankings, and gain the trust of your visitors by helping to protect their online privacy.' ) |
1284 ), |
1503 ), |
1285 'actions' => sprintf( |
1504 'actions' => sprintf( |
1286 '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>', |
1505 '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s <span class="screen-reader-text">%s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>', |
1287 /* translators: Documentation explaining HTTPS and why it should be used. */ |
1506 /* translators: Documentation explaining HTTPS and why it should be used. */ |
1288 esc_url( __( 'https://wordpress.org/support/article/why-should-i-use-https/' ) ), |
1507 esc_url( __( 'https://wordpress.org/support/article/why-should-i-use-https/' ) ), |
1289 __( 'Read more about why you should use HTTPS' ), |
1508 __( 'Learn more about why you should use HTTPS' ), |
1290 /* translators: accessibility text */ |
1509 /* translators: Accessibility text. */ |
1291 __( '(opens in a new tab)' ) |
1510 __( '(opens in a new tab)' ) |
1292 ), |
1511 ), |
1293 'test' => 'https_status', |
1512 'test' => 'https_status', |
1294 ); |
1513 ); |
1295 |
1514 |
1408 /* translators: %s: The error message returned while from the cron scheduler. */ |
1627 /* translators: %s: The error message returned while from the cron scheduler. */ |
1409 __( 'While trying to test your site’s scheduled events, the following error was returned: %s' ), |
1628 __( 'While trying to test your site’s scheduled events, the following error was returned: %s' ), |
1410 $this->has_missed_cron()->get_error_message() |
1629 $this->has_missed_cron()->get_error_message() |
1411 ) |
1630 ) |
1412 ); |
1631 ); |
1413 } else { |
1632 } elseif ( $this->has_missed_cron() ) { |
1414 if ( $this->has_missed_cron() ) { |
1633 $result['status'] = 'recommended'; |
1415 $result['status'] = 'recommended'; |
1634 |
1416 |
1635 $result['label'] = __( 'A scheduled event has failed' ); |
1417 $result['label'] = __( 'A scheduled event has failed' ); |
1636 |
1418 |
1637 $result['description'] = sprintf( |
1419 $result['description'] = sprintf( |
1638 '<p>%s</p>', |
1420 '<p>%s</p>', |
1639 sprintf( |
1421 sprintf( |
1640 /* translators: %s: The name of the failed cron event. */ |
1422 /* translators: %s: The name of the failed cron event. */ |
1641 __( 'The scheduled event, %s, failed to run. Your site still works, but this may indicate that scheduling posts or automated updates may not work as intended.' ), |
1423 __( 'The scheduled event, %s, failed to run. Your site still works, but this may indicate that scheduling posts or automated updates may not work as intended.' ), |
1642 $this->last_missed_cron |
1424 $this->last_missed_cron |
1643 ) |
1425 ) |
1644 ); |
1426 ); |
1645 } elseif ( $this->has_late_cron() ) { |
1427 } |
1646 $result['status'] = 'recommended'; |
|
1647 |
|
1648 $result['label'] = __( 'A scheduled event is late' ); |
|
1649 |
|
1650 $result['description'] = sprintf( |
|
1651 '<p>%s</p>', |
|
1652 sprintf( |
|
1653 /* translators: %s: The name of the late cron event. */ |
|
1654 __( 'The scheduled event, %s, is late to run. Your site still works, but this may indicate that scheduling posts or automated updates may not work as intended.' ), |
|
1655 $this->last_late_cron |
|
1656 ) |
|
1657 ); |
1428 } |
1658 } |
1429 |
1659 |
1430 return $result; |
1660 return $result; |
1431 } |
1661 } |
1432 |
1662 |
1433 /** |
1663 /** |
1434 * Test if WordPress can run automated background updates. |
1664 * Test if WordPress can run automated background updates. |
1435 * |
1665 * |
1436 * Background updates in WordPress are primarily used for minor releases and security updates. It's important |
1666 * Background updates in WordPress are primarily used for minor releases and security updates. |
1437 * to either have these working, or be aware that they are intentionally disabled for whatever reason. |
1667 * It's important to either have these working, or be aware that they are intentionally disabled |
|
1668 * for whatever reason. |
1438 * |
1669 * |
1439 * @since 5.2.0 |
1670 * @since 5.2.0 |
1440 * |
1671 * |
1441 * @return array The test results. |
1672 * @return array The test results. |
1442 */ |
1673 */ |
1495 } |
1726 } |
1496 |
1727 |
1497 $output .= '</ul>'; |
1728 $output .= '</ul>'; |
1498 |
1729 |
1499 if ( 'good' !== $result['status'] ) { |
1730 if ( 'good' !== $result['status'] ) { |
|
1731 $result['description'] .= $output; |
|
1732 } |
|
1733 |
|
1734 return $result; |
|
1735 } |
|
1736 |
|
1737 /** |
|
1738 * Test if plugin and theme auto-updates appear to be configured correctly. |
|
1739 * |
|
1740 * @since 5.5.0 |
|
1741 * |
|
1742 * @return array The test results. |
|
1743 */ |
|
1744 public function get_test_plugin_theme_auto_updates() { |
|
1745 $result = array( |
|
1746 'label' => __( 'Plugin and theme auto-updates appear to be configured correctly' ), |
|
1747 'status' => 'good', |
|
1748 'badge' => array( |
|
1749 'label' => __( 'Security' ), |
|
1750 'color' => 'blue', |
|
1751 ), |
|
1752 'description' => sprintf( |
|
1753 '<p>%s</p>', |
|
1754 __( 'Plugin and theme auto-updates ensure that the latest versions are always installed.' ) |
|
1755 ), |
|
1756 'actions' => '', |
|
1757 'test' => 'plugin_theme_auto_updates', |
|
1758 ); |
|
1759 |
|
1760 $check_plugin_theme_updates = $this->detect_plugin_theme_auto_update_issues(); |
|
1761 |
|
1762 $result['status'] = $check_plugin_theme_updates->status; |
|
1763 |
|
1764 if ( 'good' !== $result['status'] ) { |
|
1765 $result['label'] = __( 'Your site may have problems auto-updating plugins and themes' ); |
|
1766 |
1500 $result['description'] .= sprintf( |
1767 $result['description'] .= sprintf( |
1501 '<p>%s</p>', |
1768 '<p>%s</p>', |
1502 $output |
1769 $check_plugin_theme_updates->message |
1503 ); |
1770 ); |
1504 } |
1771 } |
1505 |
1772 |
1506 return $result; |
1773 return $result; |
1507 } |
1774 } |
1508 |
1775 |
1509 /** |
1776 /** |
1510 * Test if loopbacks work as expected. |
1777 * Test if loopbacks work as expected. |
1511 * |
1778 * |
1512 * A loopback is when WordPress queries itself, for example to start a new WP_Cron instance, or when editing a |
1779 * A loopback is when WordPress queries itself, for example to start a new WP_Cron instance, |
1513 * plugin or theme. This has shown itself to be a recurring issue as code can very easily break this interaction. |
1780 * or when editing a plugin or theme. This has shown itself to be a recurring issue, |
|
1781 * as code can very easily break this interaction. |
1514 * |
1782 * |
1515 * @since 5.2.0 |
1783 * @since 5.2.0 |
1516 * |
1784 * |
1517 * @return array The test results. |
1785 * @return array The test results. |
1518 */ |
1786 */ |
1722 |
1993 |
1723 return $result; |
1994 return $result; |
1724 } |
1995 } |
1725 |
1996 |
1726 /** |
1997 /** |
|
1998 * Test if 'file_uploads' directive in PHP.ini is turned off. |
|
1999 * |
|
2000 * @since 5.5.0 |
|
2001 * |
|
2002 * @return array The test results. |
|
2003 */ |
|
2004 public function get_test_file_uploads() { |
|
2005 $result = array( |
|
2006 'label' => __( 'Files can be uploaded.' ), |
|
2007 'status' => 'good', |
|
2008 'badge' => array( |
|
2009 'label' => __( 'Performance' ), |
|
2010 'color' => 'blue', |
|
2011 ), |
|
2012 'description' => sprintf( |
|
2013 '<p>%s</p>', |
|
2014 sprintf( |
|
2015 /* translators: 1: file_uploads, 2: php.ini */ |
|
2016 __( 'The %1$s directive in %2$s determines if uploading files is allowed on your site.' ), |
|
2017 '<code>file_uploads</code>', |
|
2018 '<code>php.ini</code>' |
|
2019 ) |
|
2020 ), |
|
2021 'actions' => '', |
|
2022 'test' => 'file_uploads', |
|
2023 ); |
|
2024 |
|
2025 if ( ! function_exists( 'ini_get' ) ) { |
|
2026 $result['status'] = 'critical'; |
|
2027 $result['description'] .= sprintf( |
|
2028 /* translators: %s: ini_get() */ |
|
2029 __( 'The %s function has been disabled, some media settings are unavailable because of this.' ), |
|
2030 '<code>ini_get()</code>' |
|
2031 ); |
|
2032 return $result; |
|
2033 } |
|
2034 |
|
2035 if ( empty( ini_get( 'file_uploads' ) ) ) { |
|
2036 $result['status'] = 'critical'; |
|
2037 $result['description'] .= sprintf( |
|
2038 '<p>%s</p>', |
|
2039 sprintf( |
|
2040 /* translators: 1: file_uploads, 2: 0 */ |
|
2041 __( '%1$s is set to %2$s. You won\'t be able to upload files on your site.' ), |
|
2042 '<code>file_uploads</code>', |
|
2043 '<code>0</code>' |
|
2044 ) |
|
2045 ); |
|
2046 return $result; |
|
2047 } |
|
2048 |
|
2049 $post_max_size = ini_get( 'post_max_size' ); |
|
2050 $upload_max_filesize = ini_get( 'upload_max_filesize' ); |
|
2051 |
|
2052 if ( wp_convert_hr_to_bytes( $post_max_size ) < wp_convert_hr_to_bytes( $upload_max_filesize ) ) { |
|
2053 $result['label'] = sprintf( |
|
2054 /* translators: 1: post_max_size, 2: upload_max_filesize */ |
|
2055 __( 'The "%1$s" value is smaller than "%2$s".' ), |
|
2056 'post_max_size', |
|
2057 'upload_max_filesize' |
|
2058 ); |
|
2059 $result['status'] = 'recommended'; |
|
2060 $result['description'] = sprintf( |
|
2061 '<p>%s</p>', |
|
2062 sprintf( |
|
2063 /* translators: 1: post_max_size, 2: upload_max_filesize */ |
|
2064 __( 'The setting for %1$s is smaller than %2$s, this could cause some problems when trying to upload files.' ), |
|
2065 '<code>post_max_size</code>', |
|
2066 '<code>upload_max_filesize</code>' |
|
2067 ) |
|
2068 ); |
|
2069 return $result; |
|
2070 } |
|
2071 |
|
2072 return $result; |
|
2073 } |
|
2074 |
|
2075 /** |
1727 * Return a set of tests that belong to the site status page. |
2076 * Return a set of tests that belong to the site status page. |
1728 * |
2077 * |
1729 * Each site status test is defined here, they may be `direct` tests, that run on page load, or `async` tests |
2078 * Each site status test is defined here, they may be `direct` tests, that run on page load, or `async` tests |
1730 * which will run later down the line via JavaScript calls to improve page performance and hopefully also user |
2079 * which will run later down the line via JavaScript calls to improve page performance and hopefully also user |
1731 * experiences. |
2080 * experiences. |
1735 * @return array The list of tests to run. |
2084 * @return array The list of tests to run. |
1736 */ |
2085 */ |
1737 public static function get_tests() { |
2086 public static function get_tests() { |
1738 $tests = array( |
2087 $tests = array( |
1739 'direct' => array( |
2088 'direct' => array( |
1740 'wordpress_version' => array( |
2089 'wordpress_version' => array( |
1741 'label' => __( 'WordPress Version' ), |
2090 'label' => __( 'WordPress Version' ), |
1742 'test' => 'wordpress_version', |
2091 'test' => 'wordpress_version', |
1743 ), |
2092 ), |
1744 'plugin_version' => array( |
2093 'plugin_version' => array( |
1745 'label' => __( 'Plugin Versions' ), |
2094 'label' => __( 'Plugin Versions' ), |
1746 'test' => 'plugin_version', |
2095 'test' => 'plugin_version', |
1747 ), |
2096 ), |
1748 'theme_version' => array( |
2097 'theme_version' => array( |
1749 'label' => __( 'Theme Versions' ), |
2098 'label' => __( 'Theme Versions' ), |
1750 'test' => 'theme_version', |
2099 'test' => 'theme_version', |
1751 ), |
2100 ), |
1752 'php_version' => array( |
2101 'php_version' => array( |
1753 'label' => __( 'PHP Version' ), |
2102 'label' => __( 'PHP Version' ), |
1754 'test' => 'php_version', |
2103 'test' => 'php_version', |
1755 ), |
2104 ), |
1756 'sql_server' => array( |
2105 'php_extensions' => array( |
|
2106 'label' => __( 'PHP Extensions' ), |
|
2107 'test' => 'php_extensions', |
|
2108 ), |
|
2109 'php_default_timezone' => array( |
|
2110 'label' => __( 'PHP Default Timezone' ), |
|
2111 'test' => 'php_default_timezone', |
|
2112 ), |
|
2113 'php_sessions' => array( |
|
2114 'label' => __( 'PHP Sessions' ), |
|
2115 'test' => 'php_sessions', |
|
2116 ), |
|
2117 'sql_server' => array( |
1757 'label' => __( 'Database Server version' ), |
2118 'label' => __( 'Database Server version' ), |
1758 'test' => 'sql_server', |
2119 'test' => 'sql_server', |
1759 ), |
2120 ), |
1760 'php_extensions' => array( |
2121 'utf8mb4_support' => array( |
1761 'label' => __( 'PHP Extensions' ), |
|
1762 'test' => 'php_extensions', |
|
1763 ), |
|
1764 'utf8mb4_support' => array( |
|
1765 'label' => __( 'MySQL utf8mb4 support' ), |
2122 'label' => __( 'MySQL utf8mb4 support' ), |
1766 'test' => 'utf8mb4_support', |
2123 'test' => 'utf8mb4_support', |
1767 ), |
2124 ), |
1768 'https_status' => array( |
2125 'https_status' => array( |
1769 'label' => __( 'HTTPS status' ), |
2126 'label' => __( 'HTTPS status' ), |
1770 'test' => 'https_status', |
2127 'test' => 'https_status', |
1771 ), |
2128 ), |
1772 'ssl_support' => array( |
2129 'ssl_support' => array( |
1773 'label' => __( 'Secure communication' ), |
2130 'label' => __( 'Secure communication' ), |
1774 'test' => 'ssl_support', |
2131 'test' => 'ssl_support', |
1775 ), |
2132 ), |
1776 'scheduled_events' => array( |
2133 'scheduled_events' => array( |
1777 'label' => __( 'Scheduled events' ), |
2134 'label' => __( 'Scheduled events' ), |
1778 'test' => 'scheduled_events', |
2135 'test' => 'scheduled_events', |
1779 ), |
2136 ), |
1780 'http_requests' => array( |
2137 'http_requests' => array( |
1781 'label' => __( 'HTTP Requests' ), |
2138 'label' => __( 'HTTP Requests' ), |
1782 'test' => 'http_requests', |
2139 'test' => 'http_requests', |
1783 ), |
2140 ), |
1784 'debug_enabled' => array( |
2141 'debug_enabled' => array( |
1785 'label' => __( 'Debugging enabled' ), |
2142 'label' => __( 'Debugging enabled' ), |
1786 'test' => 'is_in_debug_mode', |
2143 'test' => 'is_in_debug_mode', |
|
2144 ), |
|
2145 'file_uploads' => array( |
|
2146 'label' => __( 'File uploads' ), |
|
2147 'test' => 'file_uploads', |
|
2148 ), |
|
2149 'plugin_theme_auto_updates' => array( |
|
2150 'label' => __( 'Plugin and theme auto-updates' ), |
|
2151 'test' => 'plugin_theme_auto_updates', |
1787 ), |
2152 ), |
1788 ), |
2153 ), |
1789 'async' => array( |
2154 'async' => array( |
1790 'dotorg_communication' => array( |
2155 'dotorg_communication' => array( |
1791 'label' => __( 'Communication with WordPress.org' ), |
2156 'label' => __( 'Communication with WordPress.org' ), |
1825 * |
2190 * |
1826 * @since 5.2.0 |
2191 * @since 5.2.0 |
1827 * |
2192 * |
1828 * @param array $test_type { |
2193 * @param array $test_type { |
1829 * An associative array, where the `$test_type` is either `direct` or |
2194 * An associative array, where the `$test_type` is either `direct` or |
1830 * `async`, to declare if the test should run via AJAX calls after page load. |
2195 * `async`, to declare if the test should run via Ajax calls after page load. |
1831 * |
2196 * |
1832 * @type array $identifier { |
2197 * @type array $identifier { |
1833 * `$identifier` should be a unique identifier for the test that should run. |
2198 * `$identifier` should be a unique identifier for the test that should run. |
1834 * Plugins and themes are encouraged to prefix test identifiers with their slug |
2199 * Plugins and themes are encouraged to prefix test identifiers with their slug |
1835 * to avoid any collisions between tests. |
2200 * to avoid any collisions between tests. |
1836 * |
2201 * |
1837 * @type string $label A friendly label for your test to identify it by. |
2202 * @type string $label A friendly label for your test to identify it by. |
1838 * @type mixed $test A callable to perform a direct test, or a string AJAX action to be called |
2203 * @type mixed $test A callable to perform a direct test, or a string Ajax action to be called |
1839 * to perform an async test. |
2204 * to perform an async test. |
1840 * } |
2205 * } |
1841 * } |
2206 * } |
1842 */ |
2207 */ |
1843 $tests = apply_filters( 'site_status_tests', $tests ); |
2208 $tests = apply_filters( 'site_status_tests', $tests ); |
1844 |
2209 |
|
2210 // Ensure that the filtered tests contain the required array keys. |
|
2211 $tests = array_merge( |
|
2212 array( |
|
2213 'direct' => array(), |
|
2214 'async' => array(), |
|
2215 ), |
|
2216 $tests |
|
2217 ); |
|
2218 |
1845 return $tests; |
2219 return $tests; |
1846 } |
2220 } |
1847 |
2221 |
1848 /** |
2222 /** |
1849 * Add a class to the body HTML tag. |
2223 * Add a class to the body HTML tag. |
1905 } |
2284 } |
1906 |
2285 |
1907 /** |
2286 /** |
1908 * Check if any scheduled tasks have been missed. |
2287 * Check if any scheduled tasks have been missed. |
1909 * |
2288 * |
1910 * Returns a boolean value of `true` if a scheduled task has been missed and ends processing. If the list of |
2289 * Returns a boolean value of `true` if a scheduled task has been missed and ends processing. |
1911 * crons is an instance of WP_Error, return the instance instead of a boolean value. |
2290 * |
1912 * |
2291 * If the list of crons is an instance of WP_Error, returns the instance instead of a boolean value. |
1913 * @since 5.2.0 |
2292 * |
1914 * |
2293 * @since 5.2.0 |
1915 * @return bool|WP_Error true if a cron was missed, false if it wasn't. WP_Error if the cron is set to that. |
2294 * |
|
2295 * @return bool|WP_Error True if a cron was missed, false if not. WP_Error if the cron is set to that. |
1916 */ |
2296 */ |
1917 public function has_missed_cron() { |
2297 public function has_missed_cron() { |
1918 if ( is_wp_error( $this->crons ) ) { |
2298 if ( is_wp_error( $this->crons ) ) { |
1919 return $this->crons; |
2299 return $this->crons; |
1920 } |
2300 } |
1921 |
2301 |
1922 foreach ( $this->crons as $id => $cron ) { |
2302 foreach ( $this->crons as $id => $cron ) { |
1923 if ( ( $cron->time - time() ) < 0 ) { |
2303 if ( ( $cron->time - time() ) < $this->timeout_missed_cron ) { |
1924 $this->last_missed_cron = $cron->hook; |
2304 $this->last_missed_cron = $cron->hook; |
1925 return true; |
2305 return true; |
1926 } |
2306 } |
1927 } |
2307 } |
1928 |
2308 |
1929 return false; |
2309 return false; |
|
2310 } |
|
2311 |
|
2312 /** |
|
2313 * Check if any scheduled tasks are late. |
|
2314 * |
|
2315 * Returns a boolean value of `true` if a scheduled task is late and ends processing. |
|
2316 * |
|
2317 * If the list of crons is an instance of WP_Error, returns the instance instead of a boolean value. |
|
2318 * |
|
2319 * @since 5.3.0 |
|
2320 * |
|
2321 * @return bool|WP_Error True if a cron is late, false if not. WP_Error if the cron is set to that. |
|
2322 */ |
|
2323 public function has_late_cron() { |
|
2324 if ( is_wp_error( $this->crons ) ) { |
|
2325 return $this->crons; |
|
2326 } |
|
2327 |
|
2328 foreach ( $this->crons as $id => $cron ) { |
|
2329 $cron_offset = $cron->time - time(); |
|
2330 if ( |
|
2331 $cron_offset >= $this->timeout_missed_cron && |
|
2332 $cron_offset < $this->timeout_late_cron |
|
2333 ) { |
|
2334 $this->last_late_cron = $cron->hook; |
|
2335 return true; |
|
2336 } |
|
2337 } |
|
2338 |
|
2339 return false; |
|
2340 } |
|
2341 |
|
2342 /** |
|
2343 * Check for potential issues with plugin and theme auto-updates. |
|
2344 * |
|
2345 * Though there is no way to 100% determine if plugin and theme auto-updates are configured |
|
2346 * correctly, a few educated guesses could be made to flag any conditions that would |
|
2347 * potentially cause unexpected behaviors. |
|
2348 * |
|
2349 * @since 5.5.0 |
|
2350 * |
|
2351 * @return object The test results. |
|
2352 */ |
|
2353 function detect_plugin_theme_auto_update_issues() { |
|
2354 $mock_plugin = (object) array( |
|
2355 'id' => 'w.org/plugins/a-fake-plugin', |
|
2356 'slug' => 'a-fake-plugin', |
|
2357 'plugin' => 'a-fake-plugin/a-fake-plugin.php', |
|
2358 'new_version' => '9.9', |
|
2359 'url' => 'https://wordpress.org/plugins/a-fake-plugin/', |
|
2360 'package' => 'https://downloads.wordpress.org/plugin/a-fake-plugin.9.9.zip', |
|
2361 'icons' => array( |
|
2362 '2x' => 'https://ps.w.org/a-fake-plugin/assets/icon-256x256.png', |
|
2363 '1x' => 'https://ps.w.org/a-fake-plugin/assets/icon-128x128.png', |
|
2364 ), |
|
2365 'banners' => array( |
|
2366 '2x' => 'https://ps.w.org/a-fake-plugin/assets/banner-1544x500.png', |
|
2367 '1x' => 'https://ps.w.org/a-fake-plugin/assets/banner-772x250.png', |
|
2368 ), |
|
2369 'banners_rtl' => array(), |
|
2370 'tested' => '5.5.0', |
|
2371 'requires_php' => '5.6.20', |
|
2372 'compatibility' => new stdClass(), |
|
2373 ); |
|
2374 |
|
2375 $mock_theme = (object) array( |
|
2376 'theme' => 'a-fake-theme', |
|
2377 'new_version' => '9.9', |
|
2378 'url' => 'https://wordpress.org/themes/a-fake-theme/', |
|
2379 'package' => 'https://downloads.wordpress.org/theme/a-fake-theme.9.9.zip', |
|
2380 'requires' => '5.0.0', |
|
2381 'requires_php' => '5.6.20', |
|
2382 ); |
|
2383 |
|
2384 $type = 'plugin'; |
|
2385 /** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */ |
|
2386 $test_plugins_enabled = apply_filters( "auto_update_{$type}", true, $mock_plugin ); |
|
2387 |
|
2388 $type = 'theme'; |
|
2389 /** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */ |
|
2390 $test_themes_enabled = apply_filters( "auto_update_{$type}", true, $mock_theme ); |
|
2391 |
|
2392 $ui_enabled_for_plugins = wp_is_auto_update_enabled_for_type( 'plugin' ); |
|
2393 $ui_enabled_for_themes = wp_is_auto_update_enabled_for_type( 'theme' ); |
|
2394 $plugin_filter_present = has_filter( 'auto_update_plugin' ); |
|
2395 $theme_filter_present = has_filter( 'auto_update_theme' ); |
|
2396 |
|
2397 if ( ( ! $test_plugins_enabled && $ui_enabled_for_plugins ) |
|
2398 || ( ! $test_themes_enabled && $ui_enabled_for_themes ) |
|
2399 ) { |
|
2400 return (object) array( |
|
2401 'status' => 'critical', |
|
2402 'message' => __( 'Auto-updates for plugins and/or themes appear to be disabled, but settings are still set to be displayed. This could cause auto-updates to not work as expected.' ), |
|
2403 ); |
|
2404 } |
|
2405 |
|
2406 if ( ( ! $test_plugins_enabled && $plugin_filter_present ) |
|
2407 && ( ! $test_themes_enabled && $theme_filter_present ) |
|
2408 ) { |
|
2409 return (object) array( |
|
2410 'status' => 'recommended', |
|
2411 'message' => __( 'Auto-updates for plugins and themes appear to be disabled. This will prevent your site from receiving new versions automatically when available.' ), |
|
2412 ); |
|
2413 } elseif ( ! $test_plugins_enabled && $plugin_filter_present ) { |
|
2414 return (object) array( |
|
2415 'status' => 'recommended', |
|
2416 'message' => __( 'Auto-updates for plugins appear to be disabled. This will prevent your site from receiving new versions automatically when available.' ), |
|
2417 ); |
|
2418 } elseif ( ! $test_themes_enabled && $theme_filter_present ) { |
|
2419 return (object) array( |
|
2420 'status' => 'recommended', |
|
2421 'message' => __( 'Auto-updates for themes appear to be disabled. This will prevent your site from receiving new versions automatically when available.' ), |
|
2422 ); |
|
2423 } |
|
2424 |
|
2425 return (object) array( |
|
2426 'status' => 'good', |
|
2427 'message' => __( 'There appear to be no issues with plugin and theme auto-updates.' ), |
|
2428 ); |
1930 } |
2429 } |
1931 |
2430 |
1932 /** |
2431 /** |
1933 * Run a loopback test on our site. |
2432 * Run a loopback test on our site. |
1934 * |
2433 * |
1943 $cookies = wp_unslash( $_COOKIE ); |
2442 $cookies = wp_unslash( $_COOKIE ); |
1944 $timeout = 10; |
2443 $timeout = 10; |
1945 $headers = array( |
2444 $headers = array( |
1946 'Cache-Control' => 'no-cache', |
2445 'Cache-Control' => 'no-cache', |
1947 ); |
2446 ); |
|
2447 /** This filter is documented in wp-includes/class-wp-http-streams.php */ |
|
2448 $sslverify = apply_filters( 'https_local_ssl_verify', false ); |
1948 |
2449 |
1949 // Include Basic auth in loopback requests. |
2450 // Include Basic auth in loopback requests. |
1950 if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) { |
2451 if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) { |
1951 $headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) ); |
2452 $headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) ); |
1952 } |
2453 } |
1953 |
2454 |
1954 $url = admin_url(); |
2455 $url = admin_url(); |
1955 |
2456 |
1956 $r = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout' ) ); |
2457 $r = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout', 'sslverify' ) ); |
1957 |
2458 |
1958 if ( is_wp_error( $r ) ) { |
2459 if ( is_wp_error( $r ) ) { |
1959 return (object) array( |
2460 return (object) array( |
1960 'status' => 'critical', |
2461 'status' => 'critical', |
1961 'message' => sprintf( |
2462 'message' => sprintf( |
1962 '%s<br>%s', |
2463 '%s<br>%s', |
1963 __( 'The loopback request to your site failed, this means features relying on them are not currently working as expected.' ), |
2464 __( 'The loopback request to your site failed, this means features relying on them are not currently working as expected.' ), |
1964 sprintf( |
2465 sprintf( |
1965 // translators: 1: The HTTP response code. 2: The error message returned. |
2466 /* translators: 1: The WordPress error message. 2: The WordPress error code. */ |
1966 __( 'Error: [%1$s] %2$s' ), |
2467 __( 'Error: %1$s (%2$s)' ), |
1967 wp_remote_retrieve_response_code( $r ), |
2468 $r->get_error_message(), |
1968 $r->get_error_message() |
2469 $r->get_error_code() |
1969 ) |
2470 ) |
1970 ), |
2471 ), |
1971 ); |
2472 ); |
1972 } |
2473 } |
1973 |
2474 |
1974 if ( 200 !== wp_remote_retrieve_response_code( $r ) ) { |
2475 if ( 200 !== wp_remote_retrieve_response_code( $r ) ) { |
1975 return (object) array( |
2476 return (object) array( |
1976 'status' => 'recommended', |
2477 'status' => 'recommended', |
1977 'message' => sprintf( |
2478 'message' => sprintf( |
1978 // translators: %d: The HTTP response code returned. |
2479 /* translators: %d: The HTTP response code returned. */ |
1979 __( 'The loopback request returned an unexpected http status code, %d, it was not possible to determine if this will prevent features from working as expected.' ), |
2480 __( 'The loopback request returned an unexpected http status code, %d, it was not possible to determine if this will prevent features from working as expected.' ), |
1980 wp_remote_retrieve_response_code( $r ) |
2481 wp_remote_retrieve_response_code( $r ) |
1981 ), |
2482 ), |
1982 ); |
2483 ); |
1983 } |
2484 } |
1985 return (object) array( |
2486 return (object) array( |
1986 'status' => 'good', |
2487 'status' => 'good', |
1987 'message' => __( 'The loopback request to your site completed successfully.' ), |
2488 'message' => __( 'The loopback request to your site completed successfully.' ), |
1988 ); |
2489 ); |
1989 } |
2490 } |
|
2491 |
|
2492 /** |
|
2493 * Create a weekly cron event, if one does not already exist. |
|
2494 * |
|
2495 * @since 5.4.0 |
|
2496 */ |
|
2497 public function maybe_create_scheduled_event() { |
|
2498 if ( ! wp_next_scheduled( 'wp_site_health_scheduled_check' ) && ! wp_installing() ) { |
|
2499 wp_schedule_event( time() + DAY_IN_SECONDS, 'weekly', 'wp_site_health_scheduled_check' ); |
|
2500 } |
|
2501 } |
|
2502 |
|
2503 /** |
|
2504 * Run our scheduled event to check and update the latest site health status for the website. |
|
2505 * |
|
2506 * @since 5.4.0 |
|
2507 */ |
|
2508 public function wp_cron_scheduled_check() { |
|
2509 // Bootstrap wp-admin, as WP_Cron doesn't do this for us. |
|
2510 require_once trailingslashit( ABSPATH ) . 'wp-admin/includes/admin.php'; |
|
2511 |
|
2512 $tests = WP_Site_Health::get_tests(); |
|
2513 |
|
2514 $results = array(); |
|
2515 |
|
2516 $site_status = array( |
|
2517 'good' => 0, |
|
2518 'recommended' => 0, |
|
2519 'critical' => 0, |
|
2520 ); |
|
2521 |
|
2522 // Don't run https test on localhost. |
|
2523 if ( 'localhost' === preg_replace( '|https?://|', '', get_site_url() ) ) { |
|
2524 unset( $tests['direct']['https_status'] ); |
|
2525 } |
|
2526 |
|
2527 foreach ( $tests['direct'] as $test ) { |
|
2528 |
|
2529 if ( is_string( $test['test'] ) ) { |
|
2530 $test_function = sprintf( |
|
2531 'get_test_%s', |
|
2532 $test['test'] |
|
2533 ); |
|
2534 |
|
2535 if ( method_exists( $this, $test_function ) && is_callable( array( $this, $test_function ) ) ) { |
|
2536 $results[] = $this->perform_test( array( $this, $test_function ) ); |
|
2537 continue; |
|
2538 } |
|
2539 } |
|
2540 |
|
2541 if ( is_callable( $test['test'] ) ) { |
|
2542 $results[] = $this->perform_test( $test['test'] ); |
|
2543 } |
|
2544 } |
|
2545 |
|
2546 foreach ( $tests['async'] as $test ) { |
|
2547 if ( is_string( $test['test'] ) ) { |
|
2548 if ( isset( $test['has_rest'] ) && $test['has_rest'] ) { |
|
2549 $result_fetch = wp_remote_post( |
|
2550 rest_url( $test['test'] ), |
|
2551 array( |
|
2552 'body' => array( |
|
2553 '_wpnonce' => wp_create_nonce( 'wp_rest' ), |
|
2554 ), |
|
2555 ) |
|
2556 ); |
|
2557 } else { |
|
2558 $result_fetch = wp_remote_post( |
|
2559 admin_url( 'admin-ajax.php' ), |
|
2560 array( |
|
2561 'body' => array( |
|
2562 'action' => $test['test'], |
|
2563 '_wpnonce' => wp_create_nonce( 'health-check-site-status' ), |
|
2564 ), |
|
2565 ) |
|
2566 ); |
|
2567 } |
|
2568 |
|
2569 if ( ! is_wp_error( $result_fetch ) ) { |
|
2570 $result = json_decode( wp_remote_retrieve_body( $result_fetch ), true ); |
|
2571 } else { |
|
2572 $result = false; |
|
2573 } |
|
2574 |
|
2575 if ( is_array( $result ) ) { |
|
2576 $results[] = $result; |
|
2577 } else { |
|
2578 $results[] = array( |
|
2579 'status' => 'recommended', |
|
2580 'label' => __( 'A test is unavailable' ), |
|
2581 ); |
|
2582 } |
|
2583 } |
|
2584 } |
|
2585 |
|
2586 foreach ( $results as $result ) { |
|
2587 if ( 'critical' === $result['status'] ) { |
|
2588 $site_status['critical']++; |
|
2589 } elseif ( 'recommended' === $result['status'] ) { |
|
2590 $site_status['recommended']++; |
|
2591 } else { |
|
2592 $site_status['good']++; |
|
2593 } |
|
2594 } |
|
2595 |
|
2596 set_transient( 'health-check-site-status-result', wp_json_encode( $site_status ) ); |
|
2597 } |
1990 } |
2598 } |