--- a/wp/wp-admin/js/site-health.js Tue Dec 15 15:52:01 2020 +0100
+++ b/wp/wp-admin/js/site-health.js Wed Sep 21 18:19:35 2022 +0200
@@ -6,13 +6,13 @@
/* global ajaxurl, ClipboardJS, SiteHealth, wp */
-jQuery( document ).ready( function( $ ) {
+jQuery( function( $ ) {
var __ = wp.i18n.__,
_n = wp.i18n._n,
sprintf = wp.i18n.sprintf,
- data,
clipboard = new ClipboardJS( '.site-health-copy-buttons .copy-button' ),
+ isStatusTab = $( '.health-check-body.health-check-status-tab' ).length,
isDebugTab = $( '.health-check-body.health-check-debug-tab' ).length,
pathsSizesSection = $( '#health-check-accordion-block-wp-paths-sizes' ),
successTimeout;
@@ -25,7 +25,7 @@
// Clear the selection and move focus back to the trigger.
e.clearSelection();
// Handle ClipboardJS focus bug, see https://github.com/zenorocha/clipboard.js/issues/680
- triggerElement.focus();
+ triggerElement.trigger( 'focus' );
// Show success visual feedback.
clearTimeout( successTimeout );
@@ -67,6 +67,57 @@
} );
/**
+ * Validates the Site Health test result format.
+ *
+ * @since 5.6.0
+ *
+ * @param {Object} issue
+ *
+ * @return {boolean}
+ */
+ function validateIssueData( issue ) {
+ // Expected minimum format of a valid SiteHealth test response.
+ var minimumExpected = {
+ test: 'string',
+ label: 'string',
+ description: 'string'
+ },
+ passed = true,
+ key, value, subKey, subValue;
+
+ // If the issue passed is not an object, return a `false` state early.
+ if ( 'object' !== typeof( issue ) ) {
+ return false;
+ }
+
+ // Loop over expected data and match the data types.
+ for ( key in minimumExpected ) {
+ value = minimumExpected[ key ];
+
+ if ( 'object' === typeof( value ) ) {
+ for ( subKey in value ) {
+ subValue = value[ subKey ];
+
+ if ( 'undefined' === typeof( issue[ key ] ) ||
+ 'undefined' === typeof( issue[ key ][ subKey ] ) ||
+ subValue !== typeof( issue[ key ][ subKey ] )
+ ) {
+ passed = false;
+ }
+ }
+ } else {
+ if ( 'undefined' === typeof( issue[ key ] ) ||
+ value !== typeof( issue[ key ] )
+ ) {
+ passed = false;
+ }
+ }
+ }
+
+ return passed;
+ }
+
+ /**
* Appends a new issue to the issue list.
*
* @since 5.2.0
@@ -78,11 +129,24 @@
issueWrapper = $( '#health-check-issues-' + issue.status ),
heading,
count;
-
+
+ /*
+ * Validate the issue data format before using it.
+ * If the output is invalid, discard it.
+ */
+ if ( ! validateIssueData( issue ) ) {
+ return false;
+ }
+
SiteHealth.site_status.issues[ issue.status ]++;
count = SiteHealth.site_status.issues[ issue.status ];
+ // If no test name is supplied, append a placeholder for markup references.
+ if ( typeof issue.test === 'undefined' ) {
+ issue.test = issue.status + count;
+ }
+
if ( 'critical' === issue.status ) {
heading = sprintf(
_n( '%s critical issue', '%s critical issues', count ),
@@ -119,10 +183,10 @@
var $progressLabel = $( '.site-health-progress-label', $wrapper );
var $circle = $( '.site-health-progress svg #bar' );
var totalTests = parseInt( SiteHealth.site_status.issues.good, 0 ) +
- parseInt( SiteHealth.site_status.issues.recommended, 0 ) +
- ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 );
+ parseInt( SiteHealth.site_status.issues.recommended, 0 ) +
+ ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 );
var failedTests = ( parseInt( SiteHealth.site_status.issues.recommended, 0 ) * 0.5 ) +
- ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 );
+ ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 );
var val = 100 - Math.ceil( ( failedTests / totalTests ) * 100 );
if ( 0 === totalTests ) {
@@ -142,7 +206,7 @@
val = 100;
}
- pct = ( ( 100 - val ) / 100 ) * c;
+ pct = ( ( 100 - val ) / 100 ) * c + 'px';
$circle.css( { strokeDashoffset: pct } );
@@ -166,7 +230,7 @@
wp.a11y.speak( __( 'All site health tests have finished running. There are items that should be addressed, and the results are now available on the page.' ) );
}
- if ( ! isDebugTab ) {
+ if ( isStatusTab ) {
$.post(
ajaxurl,
{
@@ -206,15 +270,50 @@
this.completed = true;
- $.post(
- ajaxurl,
- data,
- function( response ) {
+ if ( 'undefined' !== typeof( this.has_rest ) && this.has_rest ) {
+ wp.apiRequest( {
+ url: wp.url.addQueryArgs( this.test, { _locale: 'user' } ),
+ headers: this.headers
+ } )
+ .done( function( response ) {
+ /** This filter is documented in wp-admin/includes/class-wp-site-health.php */
+ appendIssue( wp.hooks.applyFilters( 'site_status_test_result', response ) );
+ } )
+ .fail( function( response ) {
+ var description;
+
+ if ( 'undefined' !== typeof( response.responseJSON ) && 'undefined' !== typeof( response.responseJSON.message ) ) {
+ description = response.responseJSON.message;
+ } else {
+ description = __( 'No details available' );
+ }
+
+ addFailedSiteHealthCheckNotice( this.url, description );
+ } )
+ .always( function() {
+ maybeRunNextAsyncTest();
+ } );
+ } else {
+ $.post(
+ ajaxurl,
+ data
+ ).done( function( response ) {
/** This filter is documented in wp-admin/includes/class-wp-site-health.php */
appendIssue( wp.hooks.applyFilters( 'site_status_test_result', response.data ) );
+ } ).fail( function( response ) {
+ var description;
+
+ if ( 'undefined' !== typeof( response.responseJSON ) && 'undefined' !== typeof( response.responseJSON.message ) ) {
+ description = response.responseJSON.message;
+ } else {
+ description = __( 'No details available' );
+ }
+
+ addFailedSiteHealthCheckNotice( this.url, description );
+ } ).always( function() {
maybeRunNextAsyncTest();
- }
- );
+ } );
+ }
return false;
} );
@@ -225,7 +324,30 @@
}
}
- if ( 'undefined' !== typeof SiteHealth && ! isDebugTab ) {
+ /**
+ * Add the details of a failed asynchronous test to the list of test results.
+ *
+ * @since 5.6.0
+ */
+ function addFailedSiteHealthCheckNotice( url, description ) {
+ var issue;
+
+ issue = {
+ 'status': 'recommended',
+ 'label': __( 'A test is unavailable' ),
+ 'badge': {
+ 'color': 'red',
+ 'label': __( 'Unavailable' )
+ },
+ 'description': '<p>' + url + '</p><p>' + description + '</p>',
+ 'actions': ''
+ };
+
+ /** This filter is documented in wp-admin/includes/class-wp-site-health.php */
+ appendIssue( wp.hooks.applyFilters( 'site_status_test_result', issue ) );
+ }
+
+ if ( 'undefined' !== typeof SiteHealth ) {
if ( 0 === SiteHealth.site_status.direct.length && 0 === SiteHealth.site_status.async.length ) {
recalculateProgression();
} else {
@@ -243,32 +365,13 @@
}
if ( 0 < SiteHealth.site_status.async.length ) {
- data = {
- 'action': 'health-check-' + SiteHealth.site_status.async[0].test.replace( '_', '-' ),
- '_wpnonce': SiteHealth.nonce.site_status
- };
-
- SiteHealth.site_status.async[0].completed = true;
-
- $.post(
- ajaxurl,
- data,
- function( response ) {
- appendIssue( response.data );
- maybeRunNextAsyncTest();
- }
- );
+ maybeRunNextAsyncTest();
} else {
recalculateProgression();
}
}
function getDirectorySizes() {
- var data = {
- action: 'health-check-get-sizes',
- _wpnonce: SiteHealth.nonce.site_status_result
- };
-
var timestamp = ( new Date().getTime() );
// After 3 seconds announce that we're still waiting for directory sizes.
@@ -276,20 +379,17 @@
wp.a11y.speak( __( 'Please wait...' ) );
}, 3000 );
- $.post( {
- type: 'POST',
- url: ajaxurl,
- data: data,
- dataType: 'json'
+ wp.apiRequest( {
+ path: '/wp-site-health/v1/directory-sizes'
} ).done( function( response ) {
- updateDirSizes( response.data || {} );
+ updateDirSizes( response || {} );
} ).always( function() {
var delay = ( new Date().getTime() ) - timestamp;
$( '.health-check-wp-paths-sizes.spinner' ).css( 'visibility', 'hidden' );
recalculateProgression();
- if ( delay > 3000 ) {
+ if ( delay > 3000 ) {
/*
* We have announced that we're waiting.
* Announce that we're ready after giving at least 3 seconds
@@ -344,4 +444,9 @@
recalculateProgression();
}
}
+
+ // Trigger a class toggle when the extended menu button is clicked.
+ $( '.health-check-offscreen-nav-wrapper' ).on( 'click', function() {
+ $( this ).toggleClass( 'visible' );
+ } );
} );