Make WordPress Core

Changeset 47063


Ignore:
Timestamp:
01/12/2020 01:31:49 PM (7 years ago)
Author:
SergeyBiryukov
Message:

Site Health: Introduce Site Health Status dashboard widget.

The widget informs administrators of any potential issues that should be addressed to improve the performance or security of their website, and directs them to the Site Health screen for more details.

Props Clorith, hedgefield, guddu1315.
See #47606.

Location:
trunk/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/class-wp-site-health.php

    r46797 r47063  
    99
    1010class WP_Site_Health {
     11        private static $instance = null;
     12
    1113        private $mysql_min_version_check;
    1214        private $mysql_rec_version_check;
    … …  
    3032         */
    3133        public function __construct() {
     34                $this->maybe_create_scheduled_event();
     35
    3236                $this->prepare_sql_data();
    3337
    … …  
    4347
    4448                add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
     49                add_action( 'wp_site_health_scheduled_check', array( $this, 'wp_cron_scheduled_check' ) );
     50        }
     51
     52        /**
     53         * Return an instance of the WP_Site_Health class, or create one if none exist yet.
     54         *
     55         * @since 5.4.0
     56         *
     57         * @return WP_Site_Health|null
     58         */
     59        public static function initialize() {
     60                if ( null === self::$instance ) {
     61                        self::$instance = new WP_Site_Health();
     62                }
     63
     64                return self::$instance;
    4565        }
    4666
    … …  
    5272        public function enqueue_scripts() {
    5373                $screen = get_current_screen();
    54                 if ( 'site-health' !== $screen->id ) {
     74                if ( 'site-health' !== $screen->id && 'dashboard' !== $screen->id ) {
    5575                        return;
    5676                }
    … …  
    97117
    98118                                        if ( method_exists( $this, $test_function ) && is_callable( array( $this, $test_function ) ) ) {
    99                                                 /**
    100                                                  * Filter the output of a finished Site Health test.
    101                                                  *
    102                                                  * @since 5.3.0
    103                                                  *
    104                                                  * @param array $test_result {
    105                                                  *     An associated array of test result data.
    106                                                  *
    107                                                  *     @param string $label  A label describing the test, and is used as a header in the output.
    108                                                  *     @param string $status The status of the test, which can be a value of `good`, `recommended` or `critical`.
    109                                                  *     @param array  $badge {
    110                                                  *         Tests are put into categories which have an associated badge shown, these can be modified and assigned here.
    111                                                  *
    112                                                  *         @param string $label The test label, for example `Performance`.
    113                                                  *         @param string $color Default `blue`. A string representing a color to use for the label.
    114                                                  *     }
    115                                                  *     @param string $description A more descriptive explanation of what the test looks for, and why it is important for the end user.
    116                                                  *     @param string $actions     An action to direct the user to where they can resolve the issue, if one exists.
    117                                                  *     @param string $test        The name of the test being ran, used as a reference point.
    118                                                  * }
    119                                                  */
    120                                                 $health_check_js_variables['site_status']['direct'][] = apply_filters( 'site_status_test_result', call_user_func( array( $this, $test_function ) ) );
     119                                                $health_check_js_variables['site_status']['direct'][] = $this->perform_test( array( $this, $test_function ) );
    121120                                                continue;
    122121                                        }
    … …  
    124123
    125124                                if ( is_callable( $test['test'] ) ) {
    126                                         /** This filter is documented in wp-admin/includes/class-wp-site-health.php */
    127                                         $health_check_js_variables['site_status']['direct'][] = apply_filters( 'site_status_test_result', call_user_func( $test['test'] ) );
     125                                        $health_check_js_variables['site_status']['direct'][] = $this->perform_test( $test['test'] );
    128126                                }
    129127                        }
    … …  
    140138
    141139                wp_localize_script( 'site-health', 'SiteHealth', $health_check_js_variables );
     140        }
     141
     142        /**
     143         * Run a Site Health test directly.
     144         *
     145         * @since 5.4.0
     146         *
     147         * @param $callback
     148         *
     149         * @return mixed|void
     150         */
     151        private function perform_test( $callback ) {
     152                /**
     153                 * Filter the output of a finished Site Health test.
     154                 *
     155                 * @since 5.3.0
     156                 *
     157                 * @param array $test_result {
     158                 *     An associated array of test result data.
     159                 *
     160                 *     @param string $label  A label describing the test, and is used as a header in the output.
     161                 *     @param string $status The status of the test, which can be a value of `good`, `recommended` or `critical`.
     162                 *     @param array  $badge {
     163                 *         Tests are put into categories which have an associated badge shown, these can be modified and assigned here.
     164                 *
     165                 *         @param string $label The test label, for example `Performance`.
     166                 *         @param string $color Default `blue`. A string representing a color to use for the label.
     167                 *     }
     168                 *     @param string $description A more descriptive explanation of what the test looks for, and why it is important for the end user.
     169                 *     @param string $actions     An action to direct the user to where they can resolve the issue, if one exists.
     170                 *     @param string $test        The name of the test being ran, used as a reference point.
     171                 * }
     172                 */
     173                return apply_filters( 'site_status_test_result', call_user_func( $callback ) );
    142174        }
    143175
    … …  
    20062038         */
    20072039        public function admin_body_class( $body_class ) {
     2040                $screen = get_current_screen();
     2041                if ( 'site-health' !== $screen->id ) {
     2042                        return $body_class;
     2043                }
     2044
    20082045                $body_class .= ' site-health';
    20092046
    … …  
    21682205                );
    21692206        }
     2207
     2208        /**
     2209         * Create a weekly cron event, if one does not already exist.
     2210         *
     2211         * @since 5.4.0
     2212         */
     2213        public function maybe_create_scheduled_event() {
     2214                if ( ! wp_next_scheduled( 'wp_site_health_scheduled_check' ) && ! wp_installing() ) {
     2215                        wp_schedule_event( time(), 'weekly', 'wp_site_health_scheduled_check' );
     2216                }
     2217        }
     2218
     2219        /**
     2220         * Run our scheduled event to check and update the latest site health status for the website.
     2221         *
     2222         * @since 5.4.0
     2223         */
     2224        public function wp_cron_scheduled_check() {
     2225                // Bootstrap wp-admin, as WP_Cron doesn't do this for us.
     2226                require_once( trailingslashit( ABSPATH ) . 'wp-admin/includes/admin.php' );
     2227
     2228                $tests = WP_Site_Health::get_tests();
     2229
     2230                $results = array();
     2231
     2232                $site_status = array(
     2233                        'good'        => 0,
     2234                        'recommended' => 0,
     2235                        'critical'    => 0,
     2236                );
     2237
     2238                // Don't run https test on localhost
     2239                if ( 'localhost' === preg_replace( '|https?://|', '', get_site_url() ) ) {
     2240                        unset( $tests['direct']['https_status'] );
     2241                }
     2242
     2243                foreach ( $tests['direct'] as $test ) {
     2244
     2245                        if ( is_string( $test['test'] ) ) {
     2246                                $test_function = sprintf(
     2247                                        'get_test_%s',
     2248                                        $test['test']
     2249                                );
     2250
     2251                                if ( method_exists( $this, $test_function ) && is_callable( array( $this, $test_function ) ) ) {
     2252                                        $results[] = $this->perform_test( array( $this, $test_function ) );
     2253                                        continue;
     2254                                }
     2255                        }
     2256
     2257                        if ( is_callable( $test['test'] ) ) {
     2258                                $results[] = $this->perform_test( $test['test'] );
     2259                        }
     2260                }
     2261
     2262                foreach ( $tests['async'] as $test ) {
     2263                        if ( is_string( $test['test'] ) ) {
     2264                                if ( isset( $test['has_rest'] ) && $test['has_rest'] ) {
     2265                                        $result_fetch = wp_remote_post(
     2266                                                rest_url( $test['test'] ),
     2267                                                array(
     2268                                                        'body' => array(
     2269                                                                '_wpnonce' => wp_create_nonce( 'wp_rest' ),
     2270                                                        ),
     2271                                                )
     2272                                        );
     2273                                } else {
     2274                                        $result_fetch = wp_remote_post(
     2275                                                admin_url( 'admin-ajax.php' ),
     2276                                                array(
     2277                                                        'body' => array(
     2278                                                                'action'   => $test['test'],
     2279                                                                '_wpnonce' => wp_create_nonce( 'health-check-site-status' ),
     2280                                                        ),
     2281                                                )
     2282                                        );
     2283                                }
     2284
     2285                                if ( ! is_wp_error( $result_fetch ) ) {
     2286                                        $results[] = json_decode( wp_remote_retrieve_body( $result_fetch ) );
     2287                                } else {
     2288                                        $results[] = array(
     2289                                                'status' => 'recommended',
     2290                                                'label'  => __( 'A test is unavailable' ),
     2291                                        );
     2292                                }
     2293                        }
     2294                }
     2295
     2296                foreach ( $results as $result ) {
     2297                        if ( 'critical' === $result['status'] ) {
     2298                                $site_status['critical']++;
     2299                        } elseif ( 'recommended' === $result['status'] ) {
     2300                                $site_status['recommended']++;
     2301                        } else {
     2302                                $site_status['good']++;
     2303                        }
     2304                }
     2305
     2306                set_transient( 'health-check-site-status-result', wp_json_encode( $site_status ) );
     2307        }
    21702308}
  • trunk/src/wp-admin/includes/dashboard.php

    r47016 r47063  
    4141                add_filter( 'postbox_classes_dashboard_dashboard_php_nag', 'dashboard_php_nag_class' );
    4242                wp_add_dashboard_widget( 'dashboard_php_nag', __( 'PHP Update Required' ), 'wp_dashboard_php_nag' );
     43        }
     44
     45        // Site Health.
     46        if ( current_user_can( 'view_site_health_checks' ) ) {
     47                if ( ! class_exists( 'WP_Site_Health' ) ) {
     48                        require_once( ABSPATH . 'wp-admin/includes/class-wp-site-health.php' );
     49                }
     50
     51                WP_Site_Health::initialize();
     52
     53                wp_enqueue_style( 'site-health' );
     54                wp_enqueue_script( 'site-health' );
     55
     56                wp_add_dashboard_widget( 'dashboard_site_health', __( 'Site Health Status' ), 'wp_dashboard_site_health' );
    4357        }
    4458
    … …  
    17491763
    17501764        return $classes;
     1765}
     1766
     1767/**
     1768 * Displays the Site Health Status widget.
     1769 *
     1770 * @since 5.4.0
     1771 */
     1772function wp_dashboard_site_health() {
     1773        $get_issues = get_transient( 'health-check-site-status-result' );
     1774
     1775        $issue_counts = new stdClass();
     1776
     1777        if ( false !== $get_issues ) {
     1778                $issue_counts = json_decode( $get_issues );
     1779        }
     1780
     1781        if ( ! is_object( $issue_counts ) || empty( $issue_counts ) ) {
     1782                $issue_counts = (object) array(
     1783                        'good'        => 0,
     1784                        'recommended' => 0,
     1785                        'critical'    => 0,
     1786                );
     1787        }
     1788
     1789        $issues_total = $issue_counts->recommended + $issue_counts->critical;
     1790        ?>
     1791        <div class="health-check-title-section site-health-progress-wrapper loading hide-if-no-js">
     1792                <div class="site-health-progress">
     1793                        <svg role="img" aria-hidden="true" focusable="false" width="100%" height="100%" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg">
     1794                                <circle r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
     1795                                <circle id="bar" r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
     1796                        </svg>
     1797                </div>
     1798                <div class="site-health-progress-label">
     1799                        <?php if ( false === $get_issues ) : ?>
     1800                                <?php _e( 'No information yet&hellip;' ); ?>
     1801                        <?php else : ?>
     1802                                <?php _e( 'Results are still loading&hellip;' ); ?>
     1803                        <?php endif; ?>
     1804                </div>
     1805        </div>
     1806
     1807        <?php if ( false === $get_issues ) : ?>
     1808                <p>
     1809                        <?php _e( 'No Site Health information has been gathered yet, you can do so by visiting the Site Health screen, alternatively the checks will run periodically.' ); ?>
     1810                </p>
     1811
     1812                <p>
     1813                        <?php
     1814                        printf(
     1815                                /* translators: %s: URL to Site Health screen. */
     1816                                __( '<a href="%s">Visit the Site Health screen</a> to gather information on about your site.' ),
     1817                                esc_url( admin_url( 'site-health.php' ) )
     1818                        );
     1819                        ?>
     1820                </p>
     1821
     1822        <?php else : ?>
     1823                <p>
     1824                        <?php if ( $issue_counts->critical > 0 ) : ?>
     1825                                <?php _e( 'Your site has critical issues that should be addressed as soon as possible to improve the performance or security of your website.' ); ?>
     1826                        <?php elseif ( $issues_total <= 0 ) : ?>
     1827                                <?php _e( 'Great job! Your site currently passes all site health checks.' ); ?>
     1828                        <?php else : ?>
     1829                                <?php _e( 'Your site health is looking quite good, but there are still some things you can do to improve the performance and security of your website.' ); ?>
     1830                        <?php endif; ?>
     1831                </p>
     1832        <?php endif; ?>
     1833
     1834        <?php if ( $issues_total > 0 && false !== $get_issues ) : ?>
     1835                <p>
     1836                        <?php
     1837                        printf(
     1838                                /* translators: 1: Number of issues. 2: URL to Site Health screen. */
     1839                                __( 'Take a look at the <strong>%1$d items</strong> on the <a href="%2$s">Site Health Status screen</a>.' ),
     1840                                $issues_total,
     1841                                esc_url( admin_url( 'site-health.php' ) )
     1842                        );
     1843                        ?>
     1844                </p>
     1845        <?php endif; ?>
     1846
     1847        <?php
    17511848}
    17521849
  • trunk/src/wp-settings.php

    r47018 r47063  
    352352}
    353353
     354// Create an instance of WP_Site_Health so that Cron events may fire.
     355if ( ! class_exists( 'WP_Site_Health' ) ) {
     356        require_once( ABSPATH . 'wp-admin/includes/class-wp-site-health.php' );
     357}
     358WP_Site_Health::initialize();
     359
    354360// Load active plugins.
    355361foreach ( wp_get_active_and_valid_plugins() as $plugin ) {
Note: See TracChangeset for help on using the changeset viewer.