Make WordPress Core

Changeset 49154


Ignore:
Timestamp:
10/15/2020 01:58:28 AM (6 years ago)
Author:
TimothyBlynJacobs
Message:

Site Health, REST API: Move async tests to REST API endpoints.

This provides more flexibility when writing tests and benefits from running in a front-end context which is necessary for some tests like checking that updates are supported. Additionally, this provides a more robust interface for developers who want to integrate with Site Health tests.

Because the wp/v2 endpoint is reserved for modeling core entities, site health is registered in its own wp-site-health/v1 namespace.

The existing ajax actions have been maintained for backward compatibility.

Props Clorith, chrisvanpatten, afragen, pokhriyal, TimothyBlynJacobs.
Fixes #48105.

Location:
trunk
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/js/_enqueues/admin/site-health.js

    r48301 r49154  
    1212                _n = wp.i18n._n,
    1313                sprintf = wp.i18n.sprintf,
    14                 data,
    1514                clipboard = new ClipboardJS( '.site-health-copy-buttons .copy-button' ),
    1615                isDebugTab = $( '.health-check-body.health-check-debug-tab' ).length,
     
    7978                        heading,
    8079                        count;
    81                
     80
    8281                SiteHealth.site_status.issues[ issue.status ]++;
    8382
    8483                count = SiteHealth.site_status.issues[ issue.status ];
     84
     85                // If no test name is supplied, append a placeholder for markup references.
     86                if ( typeof issue.test === 'undefined' ) {
     87                        issue.test = issue.status + count;
     88                }
    8589
    8690                if ( 'critical' === issue.status ) {
     
    120124                var $circle = $( '.site-health-progress svg #bar' );
    121125                var totalTests = parseInt( SiteHealth.site_status.issues.good, 0 ) +
    122                                 parseInt( SiteHealth.site_status.issues.recommended, 0 ) +
    123                                 ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 );
     126                        parseInt( SiteHealth.site_status.issues.recommended, 0 ) +
     127                        ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 );
    124128                var failedTests = ( parseInt( SiteHealth.site_status.issues.recommended, 0 ) * 0.5 ) +
    125                                 ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 );
     129                        ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 );
    126130                var val = 100 - Math.ceil( ( failedTests / totalTests ) * 100 );
    127131
     
    207211                                this.completed = true;
    208212
    209                                 $.post(
    210                                         ajaxurl,
    211                                         data,
    212                                         function( response ) {
     213                                if ( 'undefined' !== typeof( this.has_rest ) && this.has_rest ) {
     214                                        wp.apiRequest( {
     215                                                url: this.test
     216                                        } )
     217                                                .done( function( response ) {
     218                                                        /** This filter is documented in wp-admin/includes/class-wp-site-health.php */
     219                                                        appendIssue( wp.hooks.applyFilters( 'site_status_test_result', response ) );
     220                                                } )
     221                                                .fail( function( response ) {
     222                                                        var description;
     223
     224                                                        if ( 'undefined' !== typeof( response.responseJSON ) && 'undefined' !== typeof( response.responseJSON.message ) ) {
     225                                                                description = response.responseJSON.message;
     226                                                        } else {
     227                                                                description = __( 'No details available' );
     228                                                        }
     229
     230                                                        addFailedSiteHealthCheckNotice( this.url, description );
     231                                                } )
     232                                                .always( function() {
     233                                                        maybeRunNextAsyncTest();
     234                                                } );
     235                                } else {
     236                                        $.post(
     237                                                ajaxurl,
     238                                                data
     239                                        ).done( function( response ) {
    213240                                                /** This filter is documented in wp-admin/includes/class-wp-site-health.php */
    214241                                                appendIssue( wp.hooks.applyFilters( 'site_status_test_result', response.data ) );
     242                                        } ).fail( function( response ) {
     243                                                var description;
     244
     245                                                if ( 'undefined' !== typeof( response.responseJSON ) && 'undefined' !== typeof( response.responseJSON.message ) ) {
     246                                                        description = response.responseJSON.message;
     247                                                } else {
     248                                                        description = __( 'No details available' );
     249                                                }
     250
     251                                                addFailedSiteHealthCheckNotice( this.url, description );
     252                                        } ).always( function() {
    215253                                                maybeRunNextAsyncTest();
    216                                         }
    217                                 );
     254                                        } );
     255                                }
    218256
    219257                                return false;
     
    224262                        recalculateProgression();
    225263                }
     264        }
     265
     266        /**
     267         * Add the details of a failed asynchronous test to the list of test results.
     268         *
     269         * @since 5.6.0
     270         */
     271        function addFailedSiteHealthCheckNotice( url, description ) {
     272                var issue;
     273
     274                issue = {
     275                        'status': 'recommended',
     276                        'label': __( 'A test is unavailable' ),
     277                        'badge': {
     278                                'color': 'red',
     279                                'label': __( 'Unavailable' )
     280                        },
     281                        'description': '<p>' + url + '</p><p>' + description + '</p>',
     282                        'actions': ''
     283                };
     284
     285                /** This filter is documented in wp-admin/includes/class-wp-site-health.php */
     286                appendIssue( wp.hooks.applyFilters( 'site_status_test_result', issue ) );
    226287        }
    227288
     
    244305
    245306                if ( 0 < SiteHealth.site_status.async.length ) {
    246                         data = {
    247                                 'action': 'health-check-' + SiteHealth.site_status.async[0].test.replace( '_', '-' ),
    248                                 '_wpnonce': SiteHealth.nonce.site_status
    249                         };
    250 
    251                         SiteHealth.site_status.async[0].completed = true;
    252 
    253                         $.post(
    254                                 ajaxurl,
    255                                 data,
    256                                 function( response ) {
    257                                         appendIssue( response.data );
    258                                         maybeRunNextAsyncTest();
    259                                 }
    260                         );
     307                        maybeRunNextAsyncTest();
    261308                } else {
    262309                        recalculateProgression();
     
    265312
    266313        function getDirectorySizes() {
    267                 var data = {
    268                         action: 'health-check-get-sizes',
    269                         _wpnonce: SiteHealth.nonce.site_status_result
    270                 };
    271 
    272314                var timestamp = ( new Date().getTime() );
    273315
     
    277319                }, 3000 );
    278320
    279                 $.post( {
    280                         type: 'POST',
    281                         url: ajaxurl,
    282                         data: data,
    283                         dataType: 'json'
     321                wp.apiRequest( {
     322                        path: '/wp-site-health/v1/directory-sizes'
    284323                } ).done( function( response ) {
    285                         updateDirSizes( response.data || {} );
     324                        updateDirSizes( response || {} );
    286325                } ).always( function() {
    287326                        var delay = ( new Date().getTime() ) - timestamp;
     
    290329                        recalculateProgression();
    291330
    292                         if ( delay > 3000  ) {
     331                        if ( delay > 3000 ) {
    293332                                /*
    294333                                 * We have announced that we're waiting.
  • trunk/src/wp-admin/admin-ajax.php

    r47835 r49154  
    144144
    145145// Deprecated.
    146 $core_actions_post_deprecated = array( 'wp-fullscreen-save-post', 'press-this-save-post', 'press-this-add-category' );
     146$core_actions_post_deprecated = array(
     147        'wp-fullscreen-save-post',
     148        'press-this-save-post',
     149        'press-this-add-category',
     150        'health-check-dotorg-communication',
     151        'health-check-is-in-debug-mode',
     152        'health-check-background-updates',
     153        'health-check-loopback-requests',
     154);
    147155$core_actions_post            = array_merge( $core_actions_post, $core_actions_post_deprecated );
    148156
  • trunk/src/wp-admin/includes/ajax-actions.php

    r49122 r49154  
    51435143 *
    51445144 * @since 5.2.0
     5145 * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::test_dotorg_communication()
     5146 * @see WP_REST_Site_Health_Controller::test_dotorg_communication()
    51455147 */
    51465148function wp_ajax_health_check_dotorg_communication() {
     5149        _doing_it_wrong(
     5150                'wp_ajax_health_check_dotorg_communication',
     5151                sprintf(
     5152                // translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it.
     5153                        __( 'The Site Health check for %1$s has been replaced with %2$s.' ),
     5154                        'wp_ajax_health_check_dotorg_communication',
     5155                        'WP_REST_Site_Health_Controller::test_dotorg_communication'
     5156                ),
     5157                '5.6.0'
     5158        );
     5159
    51475160        check_ajax_referer( 'health-check-site-status' );
    51485161
     
    51635176 *
    51645177 * @since 5.2.0
     5178 * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::test_background_updates()
     5179 * @see WP_REST_Site_Health_Controller::test_background_updates()
    51655180 */
    51665181function wp_ajax_health_check_background_updates() {
     5182        _doing_it_wrong(
     5183                'wp_ajax_health_check_background_updates',
     5184                sprintf(
     5185                // translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it.
     5186                        __( 'The Site Health check for %1$s has been replaced with %2$s.' ),
     5187                        'wp_ajax_health_check_background_updates',
     5188                        'WP_REST_Site_Health_Controller::test_background_updates'
     5189                ),
     5190                '5.6.0'
     5191        );
     5192
    51675193        check_ajax_referer( 'health-check-site-status' );
    51685194
     
    51835209 *
    51845210 * @since 5.2.0
     5211 * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::test_loopback_requests()
     5212 * @see WP_REST_Site_Health_Controller::test_loopback_requests()
    51855213 */
    51865214function wp_ajax_health_check_loopback_requests() {
     5215        _doing_it_wrong(
     5216                'wp_ajax_health_check_loopback_requests',
     5217                sprintf(
     5218                // translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it.
     5219                        __( 'The Site Health check for %1$s has been replaced with %2$s.' ),
     5220                        'wp_ajax_health_check_loopback_requests',
     5221                        'WP_REST_Site_Health_Controller::test_loopback_requests'
     5222                ),
     5223                '5.6.0'
     5224        );
     5225
    51875226        check_ajax_referer( 'health-check-site-status' );
    51885227
     
    52205259 *
    52215260 * @since 5.2.0
     5261 * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::get_directory_sizes()
     5262 * @see WP_REST_Site_Health_Controller::get_directory_sizes()
    52225263 */
    52235264function wp_ajax_health_check_get_sizes() {
     5265        _doing_it_wrong(
     5266                'wp_ajax_health_check_get_sizes',
     5267                sprintf(
     5268                // translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it.
     5269                        __( 'The Site Health check for %1$s has been replaced with %2$s.' ),
     5270                        'wp_ajax_health_check_get_sizes',
     5271                        'WP_REST_Site_Health_Controller::get_directory_sizes'
     5272                ),
     5273                '5.6.0'
     5274        );
     5275
    52245276        check_ajax_referer( 'health-check-site-status-result' );
    52255277
  • trunk/src/wp-admin/includes/class-wp-site-health-auto-updates.php

    r48792 r49154  
    9191         */
    9292        public function test_wp_version_check_attached() {
    93                 if ( ! is_main_site() ) {
    94                         return;
    95                 }
    96 
    97                 $cookies = wp_unslash( $_COOKIE );
    98                 $timeout = 10;
    99                 $headers = array(
    100                         'Cache-Control' => 'no-cache',
    101                 );
    102                 /** This filter is documented in wp-includes/class-wp-http-streams.php */
    103                 $sslverify = apply_filters( 'https_local_ssl_verify', false );
    104 
    105                 // Include Basic auth in loopback requests.
    106                 if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) {
    107                         $headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
    108                 }
    109 
    110                 $url = add_query_arg(
    111                         array(
    112                                 'health-check-test-wp_version_check' => true,
    113                         ),
    114                         admin_url( 'site-health.php' )
    115                 );
    116 
    117                 $test = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout', 'sslverify' ) );
    118 
    119                 if ( is_wp_error( $test ) ) {
    120                         return array(
    121                                 'description' => sprintf(
    122                                         /* translators: %s: Name of the filter used. */
    123                                         __( 'Could not confirm that the %s filter is available.' ),
    124                                         '<code>wp_version_check()</code>'
    125                                 ),
    126                                 'severity'    => 'warning',
    127                         );
    128                 }
    129 
    130                 $response = wp_remote_retrieve_body( $test );
    131 
    132                 if ( 'yes' !== $response ) {
     93                if ( ! has_filter( 'wp_version_check', 'wp_version_check' ) ) {
    13394                        return array(
    13495                                'description' => sprintf(
     
    311272         */
    312273        function test_check_wp_filesystem_method() {
     274                // Make sure the `request_filesystem_credentials` function is available during our REST call.
     275                if ( ! function_exists( 'request_filesystem_credentials' ) ) {
     276                        require_once ABSPATH . '/wp-admin/includes/file.php';
     277                }
     278
    313279                $skin    = new Automatic_Upgrader_Skin;
    314280                $success = $skin->request_filesystem_credentials( false, ABSPATH );
     
    355321                if ( 'direct' !== $wp_filesystem->method ) {
    356322                        return false;
     323                }
     324
     325                // Make sure the `get_core_checksums` function is available during our REST call.
     326                if ( ! function_exists( 'get_core_checksums' ) ) {
     327                        require_once ABSPATH . '/wp-admin/includes/update.php';
    357328                }
    358329
  • trunk/src/wp-admin/includes/class-wp-site-health.php

    r48808 r49154  
    134134                                        $health_check_js_variables['site_status']['async'][] = array(
    135135                                                'test'      => $test['test'],
     136                                                'has_rest'  => ( isset( $test['has_rest'] ) ? $test['has_rest'] : false ),
    136137                                                'completed' => false,
    137138                                        );
     
    20812082         *
    20822083         * @since 5.2.0
     2084         * @since 5.6.0 Added support for `has_rest` and `permissions`.
    20832085         *
    20842086         * @return array The list of tests to run.
     
    21542156                        'async'  => array(
    21552157                                'dotorg_communication' => array(
    2156                                         'label' => __( 'Communication with WordPress.org' ),
    2157                                         'test'  => 'dotorg_communication',
     2158                                        'label'    => __( 'Communication with WordPress.org' ),
     2159                                        'test'     => rest_url( 'wp-site-health/v1/tests/dotorg-communication' ),
     2160                                        'has_rest' => true,
    21582161                                ),
    21592162                                'background_updates'   => array(
    2160                                         'label' => __( 'Background updates' ),
    2161                                         'test'  => 'background_updates',
     2163                                        'label'    => __( 'Background updates' ),
     2164                                        'test'     => rest_url( 'wp-site-health/v1/tests/background-updates' ),
     2165                                        'has_rest' => true,
    21622166                                ),
    21632167                                'loopback_requests'    => array(
    2164                                         'label' => __( 'Loopback request' ),
    2165                                         'test'  => 'loopback_requests',
     2168                                        'label'    => __( 'Loopback request' ),
     2169                                        'test'     => rest_url( 'wp-site-health/v1/tests/loopback-requests' ),
     2170                                        'has_rest' => true,
    21662171                                ),
    21672172                        ),
     
    22002205                 *         to avoid any collisions between tests.
    22012206                 *
    2202                  *         @type string $label A friendly label for your test to identify it by.
    2203                  *         @type mixed  $test  A callable to perform a direct test, or a string Ajax action to be called
    2204                  *                             to perform an async test.
     2207                 *         @type string  $label       A friendly label for your test to identify it by.
     2208                 *         @type mixed   $test        A callable to perform a direct test, or a string AJAX action to be
     2209                 *                                    called to perform an async test.
     2210                 *         @type boolean $has_rest    Optional. Denote if `$test` has a REST API endpoint.
    22052211                 *     }
    22062212                 * }
  • trunk/src/wp-includes/rest-api.php

    r49132 r49154  
    316316        // Block Directory.
    317317        $controller = new WP_REST_Block_Directory_Controller();
     318        $controller->register_routes();
     319
     320        // Site Health
     321        $site_health = WP_Site_Health::get_instance();
     322        $controller = new WP_REST_Site_Health_Controller( $site_health );
    318323        $controller->register_routes();
    319324}
  • trunk/src/wp-includes/script-loader.php

    r49151 r49154  
    12871287                $scripts->set_translations( 'plugin-install' );
    12881288
    1289                 $scripts->add( 'site-health', "/wp-admin/js/site-health$suffix.js", array( 'clipboard', 'jquery', 'wp-util', 'wp-a11y' ), false, 1 );
     1289                $scripts->add( 'site-health', "/wp-admin/js/site-health$suffix.js", array( 'clipboard', 'jquery', 'wp-util', 'wp-a11y', 'wp-api-request' ), false, 1 );
    12901290                $scripts->set_translations( 'site-health' );
    12911291
  • trunk/src/wp-settings.php

    r49143 r49154  
    262262require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-block-directory-controller.php';
    263263require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-application-passwords-controller.php';
     264require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-site-health-controller.php';
    264265require ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-meta-fields.php';
    265266require ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-comment-meta-fields.php';
  • trunk/tests/phpunit/tests/rest-api/rest-schema-setup.php

    r49109 r49154  
    133133                        '/wp/v2/plugins/(?P<plugin>[^.\/]+(?:\/[^.\/]+)?)',
    134134                        '/wp/v2/block-directory/search',
     135                        '/wp-site-health/v1',
     136                        '/wp-site-health/v1/tests/background-updates',
     137                        '/wp-site-health/v1/tests/loopback-requests',
     138                        '/wp-site-health/v1/tests/dotorg-communication',
     139                        '/wp-site-health/v1/directory-sizes',
    135140                );
    136141
     
    142147                        '/' === $route ||
    143148                        preg_match( '#^/oembed/1\.0(/.+)?$#', $route ) ||
    144                         preg_match( '#^/wp/v2(/.+)?$#', $route )
     149                        preg_match( '#^/wp/v2(/.+)?$#', $route ) ||
     150                        preg_match( '#^/wp-site-health/v1(/.+)?$#', $route )
    145151                );
    146152        }
  • trunk/tests/qunit/fixtures/wp-api-generated.js

    r49132 r49154  
    1515    "namespaces": [
    1616        "oembed/1.0",
    17         "wp/v2"
     17        "wp/v2",
     18        "wp-site-health/v1"
    1819    ],
    1920    "authentication": [],
     
    50565057                    {
    50575058                        "href": "http://example.org/index.php?rest_route=/wp/v2/block-directory/search"
     5059                    }
     5060                ]
     5061            }
     5062        },
     5063        "/wp-site-health/v1": {
     5064            "namespace": "wp-site-health/v1",
     5065            "methods": [
     5066                "GET"
     5067            ],
     5068            "endpoints": [
     5069                {
     5070                    "methods": [
     5071                        "GET"
     5072                    ],
     5073                    "args": {
     5074                        "namespace": {
     5075                            "required": false,
     5076                            "default": "wp-site-health/v1"
     5077                        },
     5078                        "context": {
     5079                            "required": false,
     5080                            "default": "view"
     5081                        }
     5082                    }
     5083                }
     5084            ],
     5085            "_links": {
     5086                "self": [
     5087                    {
     5088                        "href": "http://example.org/index.php?rest_route=/wp-site-health/v1"
     5089                    }
     5090                ]
     5091            }
     5092        },
     5093        "/wp-site-health/v1/tests/background-updates": {
     5094            "namespace": "wp-site-health/v1",
     5095            "methods": [
     5096                "GET"
     5097            ],
     5098            "endpoints": [
     5099                {
     5100                    "methods": [
     5101                        "GET"
     5102                    ],
     5103                    "args": []
     5104                }
     5105            ],
     5106            "_links": {
     5107                "self": [
     5108                    {
     5109                        "href": "http://example.org/index.php?rest_route=/wp-site-health/v1/tests/background-updates"
     5110                    }
     5111                ]
     5112            }
     5113        },
     5114        "/wp-site-health/v1/tests/loopback-requests": {
     5115            "namespace": "wp-site-health/v1",
     5116            "methods": [
     5117                "GET"
     5118            ],
     5119            "endpoints": [
     5120                {
     5121                    "methods": [
     5122                        "GET"
     5123                    ],
     5124                    "args": []
     5125                }
     5126            ],
     5127            "_links": {
     5128                "self": [
     5129                    {
     5130                        "href": "http://example.org/index.php?rest_route=/wp-site-health/v1/tests/loopback-requests"
     5131                    }
     5132                ]
     5133            }
     5134        },
     5135        "/wp-site-health/v1/tests/dotorg-communication": {
     5136            "namespace": "wp-site-health/v1",
     5137            "methods": [
     5138                "GET"
     5139            ],
     5140            "endpoints": [
     5141                {
     5142                    "methods": [
     5143                        "GET"
     5144                    ],
     5145                    "args": []
     5146                }
     5147            ],
     5148            "_links": {
     5149                "self": [
     5150                    {
     5151                        "href": "http://example.org/index.php?rest_route=/wp-site-health/v1/tests/dotorg-communication"
     5152                    }
     5153                ]
     5154            }
     5155        },
     5156        "/wp-site-health/v1/directory-sizes": {
     5157            "namespace": "wp-site-health/v1",
     5158            "methods": [
     5159                "GET"
     5160            ],
     5161            "endpoints": [
     5162                {
     5163                    "methods": [
     5164                        "GET"
     5165                    ],
     5166                    "args": []
     5167                }
     5168            ],
     5169            "_links": {
     5170                "self": [
     5171                    {
     5172                        "href": "http://example.org/index.php?rest_route=/wp-site-health/v1/directory-sizes"
    50585173                    }
    50595174                ]
Note: See TracChangeset for help on using the changeset viewer.