Health-Check

This commit is contained in:
Greta Thunberg 2022-12-15 17:42:06 +01:00
parent 1aae9b6ab6
commit 251ede9014
43 changed files with 2813 additions and 5738 deletions

View File

@ -0,0 +1,149 @@
<?php
/**
* Primary class for the Site Health component.
*
* @package WordPress
* @subpackage Site_Health
* @since 5.2.0
*/
class WP_Site_Health {
public function __construct() {
$this->init();
}
public function init() {
add_filter( 'cron_schedules', array( $this, 'cron_schedules' ) );
add_action( 'admin_menu', array( $this, 'action_admin_menu' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) );
add_action( 'site_health_tab_content', array( $this, 'site_health_tab' ) );
}
public function cron_schedules( $schedules ) {
if ( ! isset( $schedules['weekly'] ) ) {
$schedules['weekly'] = array(
'interval' => 7 * DAY_IN_SECONDS,
'display' => __( 'Once weekly', 'health-check' ),
);
}
return $schedules;
}
/**
* Enqueue assets.
*
* Conditionally enqueue our CSS and JavaScript when viewing plugin related pages in wp-admin.
*
* @uses wp_enqueue_style()
* @uses plugins_url()
* @uses wp_enqueue_script()
* @uses wp_localize_script()
* @uses esc_html__()
*
* @return void
*/
public function enqueues() {
$screen = get_current_screen();
// Don't enqueue anything unless we're on the health check page.
if ( 'tools_page_site-health' !== $screen->id ) {
return;
}
wp_enqueue_style( 'health-check', trailingslashit( HEALTH_CHECK_PLUGIN_URL ) . 'build/health-check.css', array(), HEALTH_CHECK_PLUGIN_VERSION );
wp_enqueue_script( 'health-check', trailingslashit( HEALTH_CHECK_PLUGIN_URL ) . 'build/health-check.js', array( 'jquery' ), HEALTH_CHECK_PLUGIN_VERSION );
wp_localize_script(
'health-check',
'HealthCheck',
array(
'nonce' => array(
'rest_api' => wp_create_nonce( 'wp_rest' ),
),
)
);
}
/**
* Add item to the admin menu.
*
* @uses add_dashboard_page()
* @uses __()
*
* @return void
*/
public function action_admin_menu() {
$critical_issues = 0;
$issue_counts = get_transient( 'health-check-site-status-result' );
if ( false !== $issue_counts ) {
$issue_counts = json_decode( $issue_counts );
$critical_issues = absint( $issue_counts->critical );
}
$critical_count = sprintf(
'<span class="update-plugins count-%d"><span class="update-count">%s</span></span>',
esc_attr( $critical_issues ),
sprintf(
'%d<span class="screen-reader-text"> %s</span>',
esc_html( $critical_issues ),
esc_html_x( 'Critical issues', 'Issue counter label for the admin menu', 'health-check' )
)
);
$menu_title =
sprintf(
// translators: %s: Critical issue counter, if any.
_x( 'Site Health %s', 'Menu Title', 'health-check' ),
( ! $issue_counts || $critical_issues < 1 ? '' : $critical_count )
);
add_submenu_page(
'tools.php',
_x( 'Site Health', 'Page title', 'health-check' ),
$menu_title,
'view_site_health_checks',
'site-health',
array( $this, 'render_menu_page' )
);
}
public function render_menu_page() {
require_once HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/site-health-header.php';
$tab = ( isset( $_GET['tab'] ) && ! empty( $_GET['tab'] ) ? $_GET['tab'] : '' );
do_action( 'site_health_tab_content', $tab );
}
public function site_health_tab( $tab ) {
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/site-health-header.php' );
switch ( Health_Check::current_tab() ) {
case 'debug':
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/debug-data.php' );
break;
case 'troubleshoot':
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/troubleshoot.php' );
break;
case 'tools':
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/tools.php' );
break;
case 'site-status':
default:
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/site-status.php' );
}
// Close out the div tag opened as a wrapper in the header.
echo '</div>';
}
}
new WP_Site_Health();

View File

@ -48,8 +48,8 @@ class Health_Check_Mail_Check extends Health_Check_Tool {
$email_message = sanitize_text_field( $_POST['email_message'] );
$wp_address = get_bloginfo( 'url' );
$wp_name = get_bloginfo( 'name' );
$date = date_i18n( get_option( 'date_format' ), current_time( 'timestamp' ) );
$time = date_i18n( get_option( 'time_format' ), current_time( 'timestamp' ) );
$date = date_i18n( get_option( 'date_format' ), current_time( 'timestamp' ) ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
$time = date_i18n( get_option( 'time_format' ), current_time( 'timestamp' ) ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
// translators: %s: website url.
$email_subject = sprintf( esc_html__( 'Health Check Test Message from %s', 'health-check' ), $wp_address );

View File

@ -0,0 +1,87 @@
<?php
/**
* Provide a means to access extended phpinfo details.
*
* @package Health Check
*/
// Make sure the file is not directly accessible.
if ( ! defined( 'ABSPATH' ) ) {
die( 'We\'re sorry, but you can not directly access this file.' );
}
/**
* Class PhpInfo
*/
class Health_Check_Phpinfo extends Health_Check_Tool {
public function __construct() {
$this->label = __( 'PHP Info', 'health-check' );
if ( ! function_exists( 'phpinfo' ) ) {
$this->description = __( 'The phpinfo() function has been disabled by your host. Please contact the host if you need more information about your setup.', 'health-check' );
} else {
$this->description = __( 'Some scenarios require you to look up more detailed server configurations than what is normally required. The PHP Info page allows you to view all available configuration options for your PHP setup. Please be advised that WordPress does not guarantee that any information shown on that page may not be considered sensitive.', 'health-check' );
}
add_action( 'site_health_tab_content', array( $this, 'add_site_health_tab_content' ) );
parent::__construct();
}
/**
* Render the PHP Info tab content.
*
* @param string $tab The slug of the tab being requested.
* @return void
*/
public function add_site_health_tab_content( $tab ) {
// If the host has disabled `phpinfo()`, do not try to load the page..
if ( ! function_exists( 'phpinfo' ) ) {
return;
}
if ( 'phpinfo' === $tab ) {
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/phpinfo.php' );
}
}
/**
* Render the PHP Info tab content.
*
* @return void
*/
public function tab_content() {
// If the host has disabled `phpinfo()`, do not offer a button alternative.
if ( ! function_exists( 'phpinfo' ) ) {
return;
}
$phpinfo_url = add_query_arg( array( 'tab' => 'phpinfo' ), admin_url( 'site-health.php' ) );
if ( defined( 'HEALTH_CHECK_BACKCOMPAT_LOADED' ) && HEALTH_CHECK_BACKCOMPAT_LOADED ) {
$phpinfo_url = add_query_arg(
array(
'page' => 'site-health',
'tab' => 'phpinfo',
),
admin_url( 'tools.php' )
);
}
?>
<div class="site-health-view-more">
<?php
printf(
'<a href="%s" class="button button-primary">%s</a>',
esc_url( $phpinfo_url ),
__( 'View extended PHP information', 'health-check' )
);
?>
</div>
<?php
}
}
new Health_Check_Phpinfo();

View File

@ -1,131 +1,155 @@
<?php
class Health_Check_Plugin_Compatibility extends Health_Check_Tool {
public function __construct() {
$this->label = __( 'Plugin compatibility', 'health-check' );
$this->description = sprintf(
'%s<br>%s',
__( 'Attempt to identify the compatibility of your plugins before upgrading PHP, note that a compatibility check may not always be accurate, and you may want to contact the plugin author to confirm that things will continue working.', 'health-check' ),
__( 'The compatibility check will need to send requests to the <a href="https://wptide.org">WPTide</a> project to fetch the test results for each of your plugins.', 'health-check' )
);
add_action( 'wp_ajax_health-check-tools-plugin-compat', array( $this, 'check_plugin_version' ) );
parent::__construct();
}
public function tab_content() {
?>
<table class="wp-list-table widefat fixed striped" id="health-check-tool-plugin-compat-list">
<thead>
<tr>
<th><?php _e( 'Plugin', 'health-check' ); ?></th>
<th><?php _e( 'Version', 'health-check' ); ?></th>
<th><?php _e( 'Minimum PHP', 'health-check' ); ?></th>
<th><?php _e( 'Highest supported PHP', 'health-check' ); ?></th>
</tr>
</thead>
<tbody>
<?php
$plugins = get_plugins();
foreach ( $plugins as $slug => $plugin ) {
printf(
'<tr data-plugin-slug="%s" data-plugin-version="%s" data-plugin-checked="false"><td>%s</td><td>%s</td><td>%s</td><td class="supported-version">%s</td></tr>',
esc_attr( $slug ),
esc_attr( $plugin['Version'] ),
$plugin['Name'],
$plugin['Version'],
( isset( $plugin['RequiresPHP'] ) && ! empty( $plugin['RequiresPHP'] ) ? $plugin['RequiresPHP'] : '&mdash;' ),
'<span class="spinner"></span>'
);
}
?>
</tbody>
</table>
<p>
<button type="button" class="button button-primary" id="health-check-tool-plugin-compat">
<?php _e( 'Check plugins', 'health-check' ); ?>
</button>
</p>
<?php
}
function check_plugin_version() {
check_ajax_referer( 'health-check-tools-plugin-compat' );
if ( ! current_user_can( 'view_site_health_checks' ) ) {
wp_send_json_error();
}
$response = array(
'version' => $this->get_highest_supported_php( $_POST['slug'], $_POST['version'] ),
);
wp_send_json_success( $response );
wp_die();
}
function get_highest_supported_php( $slug, $version ) {
$versions = $this->get_supported_php( $slug, $version );
if ( empty( $versions ) ) {
return __( 'Could not be determined', 'health-check' );
}
$highest = 0;
foreach ( $versions as $version ) {
if ( $highest < $version ) {
$highest = $version;
}
}
return $highest;
}
function get_supported_php( $slug, $version ) {
// Clean up the slug, in case it's got more details
if ( stristr( $slug, '/' ) ) {
$parts = explode( '/', $slug );
$slug = $parts[0];
}
$transient_name = sprintf(
'health-check-tide-%s-%s',
$slug,
$version
);
$tide_versions = get_transient( $transient_name );
if ( false === $tide_versions ) {
$tide_api_respone = wp_remote_get(
sprintf(
'https://wptide.org/api/tide/v1/audit/wporg/plugin/%s',
$slug
)
);
$tide_response = wp_remote_retrieve_body( $tide_api_respone );
$json = json_decode( $tide_response );
if ( empty( $json ) ) {
$tide_versions = array();
} else {
$tide_versions = $json[0]->reports->phpcs_phpcompatibility->compatible_versions;
}
set_transient( $transient_name, $tide_versions, 1 * WEEK_IN_SECONDS );
}
return $tide_versions;
}
}
new Health_Check_Plugin_Compatibility();
<?php
class Health_Check_Plugin_Compatibility extends Health_Check_Tool {
public function __construct() {
$this->label = __( 'Plugin compatibility', 'health-check' );
$this->description = sprintf(
'%s<br>%s',
__( 'Attempt to identify the compatibility of your plugins before upgrading PHP, note that a compatibility check may not always be accurate, and you may want to contact the plugin author to confirm that things will continue working.', 'health-check' ),
__( 'The compatibility check will need to send requests to the <a href="https://wptide.org">WPTide</a> project to fetch the test results for each of your plugins.', 'health-check' )
);
add_action( 'rest_api_init', array( $this, 'register_plugin_compat_rest_route' ) );
parent::__construct();
}
public function register_plugin_compat_rest_route() {
register_rest_route(
'health-check/v1',
'plugin-compat',
array(
'methods' => 'POST',
'callback' => array( $this, 'check_plugin_version' ),
'permission_callback' => function() {
return current_user_can( 'view_site_health_checks' );
},
)
);
}
public function tab_content() {
?>
<table class="wp-list-table widefat fixed striped" id="health-check-tool-plugin-compat-list">
<thead>
<tr>
<th><?php _e( 'Plugin', 'health-check' ); ?></th>
<th><?php _e( 'Version', 'health-check' ); ?></th>
<th><?php _e( 'Minimum PHP', 'health-check' ); ?></th>
<th><?php _e( 'Highest supported PHP', 'health-check' ); ?></th>
</tr>
</thead>
<tbody>
<?php
$plugins = get_plugins();
foreach ( $plugins as $slug => $plugin ) {
printf(
'<tr data-plugin-slug="%s" data-plugin-version="%s" data-plugin-checked="false"><td>%s</td><td>%s</td><td>%s</td><td class="supported-version">%s</td></tr>',
esc_attr( $slug ),
esc_attr( $plugin['Version'] ),
$plugin['Name'],
$plugin['Version'],
( isset( $plugin['RequiresPHP'] ) && ! empty( $plugin['RequiresPHP'] ) ? $plugin['RequiresPHP'] : '&mdash;' ),
'<span class="spinner"></span>'
);
}
?>
</tbody>
</table>
<p>
<button type="button" class="button button-primary" id="health-check-tool-plugin-compat">
<?php _e( 'Check plugins', 'health-check' ); ?>
</button>
</p>
<?php
}
function check_plugin_version( $request ) {
if ( ! $request->has_param( 'slug' ) || ! $request->has_param( 'version' ) ) {
return new WP_Error( 'missing_arg', __( 'The slug, or version, is missing from the request.', 'health-check' ) );
}
$slug = $request->get_param( 'slug' );
$version = $request->get_param( 'version' );
/*
* Override for the Health Check plugin, which has back-compat code we are aware
* of and can account for early on. It should not become a habit to add exceptions for
* plugins in this field, this is rather to avoid confusion and concern in users of this plugin specifically.
*/
if ( 'health-check/health-check.php' === $slug ) {
$response = array(
'version' => '7.4',
);
} else {
$response = array(
'version' => $this->get_highest_supported_php( $slug, $version ),
);
}
return new WP_REST_Response( $response, 200 );
}
function get_highest_supported_php( $slug, $version ) {
$versions = $this->get_supported_php( $slug, $version );
if ( empty( $versions ) ) {
return __( 'Could not be determined', 'health-check' );
}
$highest = 0;
foreach ( $versions as $version ) {
if ( $highest < $version ) {
$highest = $version;
}
}
return $highest;
}
function get_supported_php( $slug, $version ) {
// Clean up the slug, in case it's got more details
if ( stristr( $slug, '/' ) ) {
$parts = explode( '/', $slug );
$slug = $parts[0];
}
$transient_name = sprintf(
'health-check-tide-%s-%s',
$slug,
$version
);
$tide_versions = get_transient( $transient_name );
if ( false === $tide_versions ) {
$tide_api_respone = wp_remote_get(
sprintf(
'https://wptide.org/api/tide/v1/audit/wporg/plugin/%s',
$slug
)
);
$tide_response = wp_remote_retrieve_body( $tide_api_respone );
$json = json_decode( $tide_response );
if ( empty( $json ) ) {
$tide_versions = array();
} else {
$tide_versions = $json[0]->reports->phpcs_phpcompatibility->compatible_versions;
}
set_transient( $transient_name, $tide_versions, 1 * WEEK_IN_SECONDS );
}
return $tide_versions;
}
}
new Health_Check_Plugin_Compatibility();

View File

@ -1,42 +1,16 @@
<?php
/**
* WP-CLI Commands for the Health Check plugin
*
* @package Health Check
*/
use WP_CLI\Utils;
namespace HealthCheck\WP_CLI;
// Make sure the file is not directly accessible.
if ( ! defined( 'ABSPATH' ) ) {
die( 'We\'re sorry, but you can not directly access this file.' );
}
class Status {
/**
* Class Health_Check_WP_CLI
*/
class Health_Check_WP_CLI {
/**
* See the sites status based on best practices and WordPress recommendations.
*
* ## EXAMPLES
*
* wp health-check status
*
* ## OPTIONS
*
* [--format=<format>]
* : Render the output in a particular format.
* ---
* default: table
* options:
* - table
* - csv
* - json
* - yaml
* ---
*/
public function status( $args, $assoc_args ) {
private $format;
public function __construct( $format ) {
$this->format = $format;
}
public function run() {
global $health_check_site_status;
$all_tests = $health_check_site_status::get_tests();
@ -62,16 +36,15 @@ class Health_Check_WP_CLI {
);
}
if ( WP_CLI\Utils\get_flag_value( $assoc_args, 'format' ) === 'json' ) {
if ( 'json' === $this->format ) {
WP_CLI\Utils\format_items( 'json', $test_result, array( 'test', 'type', 'result' ) );
} elseif ( WP_CLI\Utils\get_flag_value( $assoc_args, 'format' ) === 'csv' ) {
} elseif ( 'csv' === $this->format ) {
WP_CLI\Utils\format_items( 'csv', $test_result, array( 'test', 'type', 'result' ) );
} elseif ( WP_CLI\Utils\get_flag_value( $assoc_args, 'format' ) === 'yaml' ) {
} elseif ( 'yaml' === $this->format ) {
WP_CLI\Utils\format_items( 'yaml', $test_result, array( 'test', 'type', 'result' ) );
} else {
WP_CLI\Utils\format_items( 'table', $test_result, array( 'test', 'type', 'result' ) );
}
}
}
WP_CLI::add_command( 'health-check', 'Health_Check_WP_CLI' );
}

View File

@ -0,0 +1,50 @@
<?php
/**
* WP-CLI Commands for the Health Check plugin
*
* @package Health Check
*/
namespace HealthCheck;
use HealthCheck\WP_CLI\Status;
use WP_CLI;
use WP_CLI\Utils;
// Make sure the file is not directly accessible.
if ( ! defined( 'ABSPATH' ) ) {
die( 'We\'re sorry, but you can not directly access this file.' );
}
/**
* Class Health_Check_CLI
*/
class CLI {
/**
* See the sites status based on best practices and WordPress recommendations.
*
* ## EXAMPLES
*
* wp health-check status
*
* ## OPTIONS
*
* [--format=<format>]
* : Render the output in a particular format.
* ---
* default: table
* options:
* - table
* - csv
* - json
* - yaml
* ---
*/
public function status( $args, $assoc_args ) {
$runner = new Status( WP_CLI\Utils\get_flag_value( $assoc_args, 'format' ) );
$runner->run();
}
}
WP_CLI::add_command( 'health-check', __NAMESPACE__ . '\\CLI' );

View File

@ -101,7 +101,7 @@ class Health_Check_Troubleshoot {
}
// Copy the must-use plugin to the local directory.
if ( ! $wp_filesystem->copy( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'assets/mu-plugin/health-check-troubleshooting-mode.php', trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-troubleshooting-mode.php' ) ) {
if ( ! $wp_filesystem->copy( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'mu-plugin/health-check-troubleshooting-mode.php', trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-troubleshooting-mode.php' ) ) {
Health_Check::display_notice( esc_html__( 'We were unable to copy the plugin file required to enable the Troubleshooting Mode.', 'health-check' ), 'error' );
return false;
}
@ -136,7 +136,7 @@ class Health_Check_Troubleshoot {
return false;
}
$current = get_plugin_data( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'assets/mu-plugin/health-check-troubleshooting-mode.php' );
$current = get_plugin_data( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'mu-plugin/health-check-troubleshooting-mode.php' );
$active = get_plugin_data( trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-troubleshooting-mode.php' );
$current_version = ( isset( $current['Version'] ) ? $current['Version'] : '0.0' );
@ -145,7 +145,7 @@ class Health_Check_Troubleshoot {
if ( version_compare( $current_version, $active_version, '>' ) ) {
global $wp_filesystem;
if ( ! $wp_filesystem->copy( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'assets/mu-plugin/health-check-troubleshooting-mode.php', trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-troubleshooting-mode.php', true ) ) {
if ( ! $wp_filesystem->copy( trailingslashit( HEALTH_CHECK_PLUGIN_DIRECTORY ) . 'mu-plugin/health-check-troubleshooting-mode.php', trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-troubleshooting-mode.php', true ) ) {
Health_Check::display_notice( esc_html__( 'We were unable to replace the plugin file required to enable the Troubleshooting Mode.', 'health-check' ), 'error' );
return false;
}

View File

@ -48,8 +48,6 @@ class Health_Check {
public function init() {
add_action( 'plugins_loaded', array( $this, 'load_i18n' ) );
add_action( 'admin_menu', array( $this, 'action_admin_menu' ) );
add_filter( 'plugin_action_links', array( $this, 'troubleshoot_plugin_action' ), 20, 4 );
add_filter( 'plugin_action_links_' . plugin_basename( HEALTH_CHECK_PLUGIN_FILE ), array( $this, 'page_plugin_action' ) );
@ -63,11 +61,24 @@ class Health_Check {
add_action( 'wp_ajax_health-check-loopback-no-plugins', array( 'Health_Check_Loopback', 'loopback_no_plugins' ) );
add_action( 'wp_ajax_health-check-loopback-individual-plugins', array( 'Health_Check_Loopback', 'loopback_test_individual_plugins' ) );
add_action( 'wp_ajax_health-check-loopback-default-theme', array( 'Health_Check_Loopback', 'loopback_test_default_theme' ) );
add_action( 'wp_ajax_health-check-get-sizes', array( 'Health_Check_Debug_Data', 'ajax_get_sizes' ) );
add_filter( 'cron_schedules', array( $this, 'cron_schedules' ) );
add_filter( 'user_has_cap', array( $this, 'maybe_grant_site_health_caps' ), 1, 4 );
add_filter( 'site_health_navigation_tabs', array( $this, 'add_site_health_navigation_tabs' ) );
add_action( 'site_health_tab_content', array( $this, 'add_site_health_tab_content' ) );
add_action( 'init', array( $this, 'maybe_remove_old_scheduled_events' ) );
}
/**
* Disable scheduled events previously used by the plugin, but now part of WordPress core.
*
* @return void
*/
public function maybe_remove_old_scheduled_events() {
if ( wp_next_scheduled( 'health-check-scheduled-site-status-check' ) ) {
wp_clear_scheduled_hook( 'health-check-scheduled-site-status-check' );
}
}
/**
@ -217,176 +228,42 @@ class Health_Check {
$screen = get_current_screen();
// Don't enqueue anything unless we're on the health check page.
if ( ( ! isset( $_GET['page'] ) || 'health-check' !== $_GET['page'] ) && 'dashboard' !== $screen->base ) {
if ( 'tools_page_site-health' !== $screen->id && 'site-health' !== $screen->id ) {
return;
}
$health_check_js_variables = array(
'string' => array(
'please_wait' => esc_html__( 'Please wait...', 'health-check' ),
'copied' => esc_html__( 'Copied', 'health-check' ),
'running_tests' => esc_html__( 'Currently being tested...', 'health-check' ),
'site_health_complete' => esc_html__( 'All site health tests have finished running.', 'health-check' ),
'site_health_complete_pass_sr' => esc_html__( 'All site health tests have finished running. Your site is looking good, and the results are now available on the page.', 'health-check' ),
'site_health_complete_fail_sr' => esc_html__( 'All site health tests have finished running. There are items that should be addressed, and the results are now available on the page.', 'health-check' ),
'site_health_complete_pass' => esc_html__( 'Good', 'health-check' ),
'site_health_complete_fail' => esc_html__( 'Should be improved', 'health-check' ),
'site_info_copied' => esc_html__( 'Site information has been added to your clipboard.', 'health-check' ),
// translators: %s: Amount of critical issues.
'site_info_heading_critical_single' => esc_html__( '%s Critical issue', 'health-check' ),
// translators: %s: Amount of critical issues.
'site_info_heading_critical_plural' => esc_html__( '%s Critical issues', 'health-check' ),
// translators: %s: Amount of recommended issues.
'site_info_heading_recommended_single' => esc_html__( '%s Recommended improvement', 'health-check' ),
// translators: %s: Amount of recommended issues.
'site_info_heading_recommended_plural' => esc_html__( '%s Recommended improvements', 'health-check' ),
// translators: %s: Amount of passed tests.
'site_info_heading_good_single' => esc_html__( '%s Item with no issues detected', 'health-check' ),
// translators: %s: Amount of passed tests.
'site_info_heading_good_plural' => esc_html__( '%s Items with no issues detected', 'health-check' ),
),
'nonce' => array(
'loopback_no_plugins' => wp_create_nonce( 'health-check-loopback-no-plugins' ),
'loopback_individual_plugins' => wp_create_nonce( 'health-check-loopback-individual-plugins' ),
'loopback_default_theme' => wp_create_nonce( 'health-check-loopback-default-theme' ),
'files_integrity_check' => wp_create_nonce( 'health-check-files-integrity-check' ),
'view_file_diff' => wp_create_nonce( 'health-check-view-file-diff' ),
'mail_check' => wp_create_nonce( 'health-check-mail-check' ),
'site_status' => wp_create_nonce( 'health-check-site-status' ),
'site_status_result' => wp_create_nonce( 'health-check-site-status-result' ),
'tools_plugin_compat' => wp_create_nonce( 'health-check-tools-plugin-compat' ),
),
'site_status' => array(
'direct' => array(),
'async' => array(),
'issues' => array(
'good' => 0,
'recommended' => 0,
'critical' => 0,
),
),
);
wp_enqueue_style( 'health-check', trailingslashit( HEALTH_CHECK_PLUGIN_URL ) . 'build/health-check.css', array(), HEALTH_CHECK_PLUGIN_VERSION );
$issue_counts = get_transient( 'health-check-site-status-result' );
if ( false !== $issue_counts ) {
$issue_counts = json_decode( $issue_counts );
$health_check_js_variables['site_status']['issues'] = $issue_counts;
}
if ( 'dashboard' !== $screen->base && ( ! isset( $_GET['tab'] ) || ( isset( $_GET['tab'] ) && 'site-status' === $_GET['tab'] ) ) ) {
$tests = Health_Check_Site_Status::get_tests();
// Don't run https test on localhost
if ( 'localhost' === preg_replace( '|https?://|', '', get_site_url() ) ) {
unset( $tests['direct']['https_status'] );
}
foreach ( $tests['direct'] as $test ) {
if ( is_string( $test['test'] ) ) {
$test_function = sprintf(
'get_test_%s',
$test['test']
);
if ( method_exists( $this, $test_function ) && is_callable( array( $this, $test_function ) ) ) {
/**
* Filter the output of a finished Site Health test.
*
* @since 5.3.0
*
* @param array $test_result {
* An associated array of test result data.
*
* @param string $label A label describing the test, and is used as a header in the output.
* @param string $status The status of the test, which can be a value of `good`, `recommended` or `critical`.
* @param array $badge {
* Tests are put into categories which have an associated badge shown, these can be modified and assigned here.
*
* @param string $label The test label, for example `Performance`.
* @param string $color Default `blue`. A string representing a color to use for the label.
* }
* @param string $description A more descriptive explanation of what the test looks for, and why it is important for the end user.
* @param string $actions An action to direct the user to where they can resolve the issue, if one exists.
* @param string $test The name of the test being ran, used as a reference point.
* }
*/
$health_check_js_variables['site_status']['direct'][] = apply_filters( 'site_status_test_result', call_user_func( array( $this, $test_function ) ) );
continue;
}
}
if ( is_callable( $test['test'] ) ) {
$health_check_js_variables['site_status']['direct'][] = apply_filters( 'site_status_test_result', call_user_func( $test['test'] ) );
}
}
foreach ( $tests['async'] as $test ) {
if ( is_string( $test['test'] ) ) {
$health_check_js_variables['site_status']['async'][] = array(
'test' => $test['test'],
'completed' => false,
);
}
}
}
if ( ! wp_script_is( 'clipboard', 'registered' ) ) {
wp_register_script( 'clipboard', trailingslashit( HEALTH_CHECK_PLUGIN_URL ) . 'assets/javascript/clipboard.min.js', array(), '2.0.4' );
}
wp_enqueue_style( 'health-check', trailingslashit( HEALTH_CHECK_PLUGIN_URL ) . 'assets/css/health-check.css', array(), HEALTH_CHECK_PLUGIN_VERSION );
wp_enqueue_script( 'health-check', trailingslashit( HEALTH_CHECK_PLUGIN_URL ) . 'assets/javascript/health-check.js', array( 'jquery', 'wp-a11y', 'clipboard', 'wp-util' ), HEALTH_CHECK_PLUGIN_VERSION, true );
wp_localize_script( 'health-check', 'SiteHealth', $health_check_js_variables );
}
/**
* Add item to the admin menu.
*
* @uses add_dashboard_page()
* @uses __()
*
* @return void
*/
public function action_admin_menu() {
$critical_issues = 0;
$issue_counts = get_transient( 'health-check-site-status-result' );
if ( false !== $issue_counts ) {
$issue_counts = json_decode( $issue_counts );
$critical_issues = absint( $issue_counts->critical );
}
$critical_count = sprintf(
'<span class="update-plugins count-%d"><span class="update-count">%s</span></span>',
esc_attr( $critical_issues ),
sprintf(
'%d<span class="screen-reader-text"> %s</span>',
esc_html( $critical_issues ),
esc_html_x( 'Critical issues', 'Issue counter label for the admin menu', 'health-check' )
)
);
$menu_title =
sprintf(
// translators: %s: Critical issue counter, if any.
_x( 'Site Health %s', 'Menu Title', 'health-check' ),
( ! $issue_counts || $critical_issues < 1 ? '' : $critical_count )
// If the WordPress 5.2+ version of Site Health is used, do some extra checks to not mess with core scripts and styles.
if ( 'site-health' === $screen->id ) {
$plugin_tabs = array(
'tools',
'troubleshoot',
);
remove_submenu_page( 'tools.php', 'site-health.php' );
if ( ! isset( $_GET['tab'] ) || ! in_array( $_GET['tab'], $plugin_tabs, true ) ) {
return;
}
}
add_submenu_page(
'tools.php',
_x( 'Site Health', 'Page Title', 'health-check' ),
$menu_title,
'view_site_health_checks',
'health-check',
array( $this, 'dashboard_page' )
wp_enqueue_script( 'health-check-tools', trailingslashit( HEALTH_CHECK_PLUGIN_URL ) . 'build/health-check-tools.js', array( 'jquery' ), HEALTH_CHECK_PLUGIN_VERSION );
wp_localize_script(
'health-check-tools',
'HealthCheck',
array(
'rest_api' => array(
'tools' => array(
'plugin_compat' => rest_url( 'health-check/v1/plugin-compat' ),
),
),
'nonce' => array(
'rest_api' => wp_create_nonce( 'wp_rest' ),
'files_integrity_check' => wp_create_nonce( 'health-check-files-integrity-check' ),
'view_file_diff' => wp_create_nonce( 'health-check-view-file-diff' ),
'mail_check' => wp_create_nonce( 'health-check-mail-check' ),
),
)
);
}
@ -454,50 +331,34 @@ class Health_Check {
return $actions;
}
/**
* Render our admin page.
*
* @uses _e()
* @uses esc_html__()
* @uses printf()
* @uses sprintf()
* @uses menu_page_url()
* @uses dirname()
*
* @return void
*/
public function dashboard_page() {
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/site-health-header.php' );
static function tabs() {
return array(
'' => esc_html__( 'Status', 'health-check' ), // The status tab is the front page, and therefore has no tab key relation.
'debug' => esc_html__( 'Info', 'health-check' ),
'troubleshoot' => esc_html__( 'Troubleshooting', 'health-check' ),
'tools' => esc_html__( 'Tools', 'health-check' ),
);
}
switch ( Health_Check::current_tab() ) {
case 'debug':
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/debug-data.php' );
break;
case 'phpinfo':
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/phpinfo.php' );
break;
public function add_site_health_navigation_tabs( $tabs ) {
return array_merge(
$tabs,
array(
'troubleshoot' => esc_html__( 'Troubleshooting', 'health-check' ),
'tools' => esc_html__( 'Tools', 'health-check' ),
)
);
}
public function add_site_health_tab_content( $tab ) {
switch ( $tab ) {
case 'troubleshoot':
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/troubleshoot.php' );
break;
case 'tools':
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/tools.php' );
break;
case 'site-status':
default:
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/pages/site-status.php' );
}
// Close out the div tag opened as a wrapper in the header.
echo '</div>';
}
static function tabs() {
return array(
'site-status' => esc_html__( 'Status', 'health-check' ),
'debug' => esc_html__( 'Info', 'health-check' ),
'troubleshoot' => esc_html__( 'Troubleshooting', 'health-check' ),
'tools' => esc_html__( 'Tools', 'health-check' ),
);
}
static function current_tab() {
@ -537,18 +398,6 @@ class Health_Check {
}
}
public function cron_schedules( $schedules ) {
if ( ! isset( $schedules['weekly'] ) ) {
$schedules['weekly'] = array(
'interval' => 7 * DAY_IN_SECONDS,
'display' => __( 'Once weekly', 'health-check' ),
);
}
return $schedules;
}
/**
* Conditionally show a form for providing filesystem credentials when introducing our troubleshooting mode plugin.
*
@ -584,14 +433,4 @@ class Health_Check {
return true;
}
public static function plugin_activation() {
if ( ! wp_next_scheduled( 'health-check-scheduled-site-status-check' ) ) {
wp_schedule_event( time(), 'weekly', 'health-check-scheduled-site-status-check' );
}
}
public static function plugin_deactivation() {
wp_clear_scheduled_hook( 'health-check-scheduled-site-status-check' );
}
}

View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,28 @@
# Health Check
![Build Status](https://github.com/WordPress/health-check/workflows/Build%20Status/badge.svg)
Health Check is a WordPress plugin that will perform a number of checks on your WordPress install to detect common configuration errors and known issues.
It currently checks your PHP and MySQL versions, some extensions which are needed or may improve WordPress, and that the WordPress.org services are accessible to you.
The debug section, which allows you to gather information about your WordPress and server configuration that you may easily share with support representatives for themes, plugins or on the official WordPress.org support forums.
Troubleshooting allows you to have a vanilla WordPress session, where all plugins are disabled, and a default theme is used, but only for your user.
For a more extensive example of how to efficiently use the Health Check plugin, check out the [WordPress.org support team handbook page about this plugin](https://make.wordpress.org/support/handbook/appendix/troubleshooting-using-the-health-check/).
In the future we may introduce more checks, and welcome feedback both through the [WordPress.org forums](https://wordpress.org/support/plugin/health-check), and the [GitHub project page](https://github.com/WordPress/health-check).
## Installation
1. Upload to your plugins folder, usually `wp-content/plugins/`
2. Activate the plugin on the plugin screen.
3. Once activated the plugin will appear under your `Dashboard` menu.
## Contributing
Contributions are more than welcome, both through issues, and pull requests. Ideas and thoughts may also be discussed in the [#core-site-health](https://wordpress.slack.com/messages/core-site-health/) channel
on the [Making WordPress Slack](https://make.wordpress.org/chat) team.
For further information about contributing, see our [guide on contributing](https://github.com/WordPress/health-check/blob/master/.github/CONTRIBUTING.md).

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=11)}({11:function(e,t,n){"use strict";n.r(t);n(12)},12:function(e,t){jQuery(document).ready((function(e){e(".show-remaining").click((function(){e(".hidden",e(this).closest("ul")).removeClass("hidden")}))}))}});

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => 'ecf8e9136e1f6b75ecdf');

View File

@ -0,0 +1 @@
(()=>{var e={629:()=>{jQuery(document).ready((function(e){e("#health-check-file-integrity").on("submit",(function(t){const c={action:"health-check-files-integrity-check",_wpnonce:HealthCheck.nonce.files_integrity_check};t.preventDefault(),e("#tools-file-integrity-response-holder").html('<span class="spinner"></span>'),e("#tools-file-integrity-response-holder .spinner").addClass("is-active"),e.post(ajaxurl,c,(function(t){e("#tools-file-integrity-response-holder .spinner").removeClass("is-active"),e("#tools-file-integrity-response-holder").parent().css("height","auto"),e("#tools-file-integrity-response-holder").html(t.data.message)}))})),e("#tools-file-integrity-response-holder").on("click",'a[href="#health-check-diff"]',(function(t){const c=e(this).data("file");t.preventDefault(),e("#health-check-diff-modal").toggle(),e("#health-check-diff-modal #health-check-diff-modal-content .spinner").addClass("is-active");const l={action:"health-check-view-file-diff",file:c,_wpnonce:HealthCheck.nonce.view_file_diff};e.post(ajaxurl,l,(function(t){e("#health-check-diff-modal #health-check-diff-modal-diff").html(t.data.message),e("#health-check-diff-modal #health-check-diff-modal-content h3").html(c),e("#health-check-diff-modal #health-check-diff-modal-content .spinner").removeClass("is-active")}))}))}))},593:()=>{jQuery(document).ready((function(e){e("#health-check-diff-modal").on("click",'a[href="#health-check-diff-modal-close"]',(function(t){t.preventDefault(),e("#health-check-diff-modal").toggle(),e("#health-check-diff-modal #health-check-diff-modal-diff").html(""),e("#health-check-diff-modal #health-check-diff-modal-content h3").html("")})),e(document).on("keyup",(function(t){27===t.which&&(e("#health-check-diff-modal").css("display","none"),e("#health-check-diff-modal #health-check-diff-modal-diff").html(""),e("#health-check-diff-modal #health-check-diff-modal-content h3").html(""))}))}))},433:()=>{jQuery(document).ready((function(e){e("#health-check-mail-check").on("submit",(function(t){const c=e("#health-check-mail-check #email").val(),l=e("#health-check-mail-check #email_message").val();t.preventDefault(),e("#tools-mail-check-response-holder").html('<span class="spinner"></span>'),e("#tools-mail-check-response-holder .spinner").addClass("is-active");const a={action:"health-check-mail-check",email:c,email_message:l,_wpnonce:HealthCheck.nonce.mail_check};e.post(ajaxurl,a,(function(t){e("#tools-mail-check-response-holder .spinner").removeClass("is-active"),e("#tools-mail-check-response-holder").parent().css("height","auto"),e("#tools-mail-check-response-holder").html(t.data.message)}))}))}))},188:()=>{jQuery(document).ready((function(e){function t(){const c=e('[data-plugin-checked="false"]',"#health-check-tool-plugin-compat-list");if(c.length<=0)return;const l=e(c[0]);l.attr("data-plugin-checked","true");const a={slug:l.data("plugin-slug"),version:l.data("plugin-version"),_wpnonce:HealthCheck.nonce.rest_api};e.post(HealthCheck.rest_api.tools.plugin_compat,a,(function(c){e(".spinner",l).removeClass("is-active"),e(".supported-version",l).append(c.version),t()}))}e("#health-check-tool-plugin-compat").on("click",(function(){e("tr","#health-check-tool-plugin-compat-list").data("plugin-checked",!1),e(".spinner","#health-check-tool-plugin-compat-list").addClass("is-active"),e(this).attr("disabled",!0),t()}))}))}},t={};function c(l){var a=t[l];if(void 0!==a)return a.exports;var o=t[l]={exports:{}};return e[l](o,o.exports,c),o.exports}c.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return c.d(t,{a:t}),t},c.d=(e,t)=>{for(var l in t)c.o(t,l)&&!c.o(e,l)&&Object.defineProperty(e,l,{enumerable:!0,get:t[l]})},c.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";c(629),c(593),c(433),c(188)})()})();

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => '1c4d8753a5d2f87f548e');

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
(()=>{var t={368:()=>{jQuery(document).ready((function(t){t(".health-check-accordion").on("click",".health-check-accordion-trigger",(function(){"true"===t(this).attr("aria-expanded")?(t(this).attr("aria-expanded","false"),t("#"+t(this).attr("aria-controls")).attr("hidden",!0)):(t(this).attr("aria-expanded","true"),t("#"+t(this).attr("aria-controls")).attr("hidden",!1))}))}))}},r={};function e(a){var o=r[a];if(void 0!==o)return o.exports;var n=r[a]={exports:{}};return t[a](n,n.exports,e),n.exports}e.n=t=>{var r=t&&t.__esModule?()=>t.default:()=>t;return e.d(r,{a:r}),r},e.d=(t,r)=>{for(var a in r)e.o(r,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:r[a]})},e.o=(t,r)=>Object.prototype.hasOwnProperty.call(t,r),(()=>{"use strict";e(368)})()})();

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => '9fb4d8aebf14252d8925');

View File

@ -0,0 +1 @@
(()=>{var e={407:()=>{jQuery(document).ready((function(e){e(".show-remaining").click((function(){e(".hidden",e(this).closest("ul")).removeClass("hidden")}))}))}},r={};function t(o){var n=r[o];if(void 0!==n)return n.exports;var i=r[o]={exports:{}};return e[o](i,i.exports,t),i.exports}t.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return t.d(r,{a:r}),r},t.d=(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),(()=>{"use strict";t(407)})()})();

View File

@ -3,6 +3,90 @@
// Manually include the versions file as we can't always rely on `get_bloginfo()` to fetch versions.
include ABSPATH . WPINC . '/version.php';
if ( ! function_exists( 'wp_timezone_string' ) ) {
/**
* Fallback function for replicating core behavior from WordPress 5.3.0 to get a timezone string
*
* @return string PHP timezone string or a ±HH:MM offset.
*/
function wp_timezone_string() {
$timezone_string = get_option( 'timezone_string' );
if ( $timezone_string ) {
return $timezone_string;
}
$offset = (float) get_option( 'gmt_offset' );
$hours = (int) $offset;
$minutes = ( $offset - $hours );
$sign = ( $offset < 0 ) ? '-' : '+';
$abs_hour = abs( $hours );
$abs_mins = abs( $minutes * 60 );
$tz_offset = sprintf( '%s%02d:%02d', $sign, $abs_hour, $abs_mins );
return $tz_offset;
}
}
if ( ! function_exists( 'wp_get_environment_type' ) ) {
/**
* Fallback function replicating core behavior from WordPress 5.5.0 to get the current environment used.
*
* @return string The current environment type.
*/
function wp_get_environment_type() {
static $current_env = '';
if ( $current_env ) {
return $current_env;
}
$wp_environments = array(
'local',
'development',
'staging',
'production',
);
// Add a note about the deprecated WP_ENVIRONMENT_TYPES constant.
if ( defined( 'WP_ENVIRONMENT_TYPES' ) && function_exists( '_deprecated_argument' ) ) {
if ( function_exists( '__' ) ) {
/* translators: %s: WP_ENVIRONMENT_TYPES */
$message = sprintf( __( 'The %s constant is no longer supported.' ), 'WP_ENVIRONMENT_TYPES' );
} else {
$message = sprintf( 'The %s constant is no longer supported.', 'WP_ENVIRONMENT_TYPES' );
}
_deprecated_argument(
'define()',
'5.5.1',
$message
);
}
// Check if the environment variable has been set, if `getenv` is available on the system.
if ( function_exists( 'getenv' ) ) {
$has_env = getenv( 'WP_ENVIRONMENT_TYPE' );
if ( false !== $has_env ) {
$current_env = $has_env;
}
}
// Fetch the environment from a constant, this overrides the global system variable.
if ( defined( 'WP_ENVIRONMENT_TYPE' ) ) {
$current_env = WP_ENVIRONMENT_TYPE;
}
// Make sure the environment is an allowed one, and not accidentally set to an invalid value.
if ( ! in_array( $current_env, $wp_environments, true ) ) {
$current_env = 'production';
}
return $current_env;
}
}
if ( ! function_exists( 'wp_check_php_version' ) && version_compare( '5.1', $wp_version, '>' ) ) {
/**
* Fallback function replicating core behavior from WordPress 5.1.0 to check PHP versions.

View File

@ -9,33 +9,22 @@
* Plugin URI: https://wordpress.org/plugins/health-check/
* Description: Checks the health of your WordPress install.
* Author: The WordPress.org community
* Version: 1.4.5
* Version: 1.5.1
* Author URI: https://wordpress.org/plugins/health-check/
* Text Domain: health-check
*/
namespace HealthCheck;
// Check that the file is not accessed directly.
use Health_Check;
if ( ! defined( 'ABSPATH' ) ) {
die( 'We\'re sorry, but you can not directly access this file.' );
}
// Set the minimum PHP version WordPress supports.
define( 'HEALTH_CHECK_PHP_MIN_VERSION', '5.2.4' );
// Set the lowest PHP version still receiving security updates.
define( 'HEALTH_CHECK_PHP_SUPPORTED_VERSION', '5.6' );
// Set the PHP version WordPress recommends.
define( 'HEALTH_CHECK_PHP_REC_VERSION', '7.2' );
// Set the minimum MySQL version WordPress supports.
define( 'HEALTH_CHECK_MYSQL_MIN_VERSION', '5.0' );
// Set the MySQL version WordPress recommends.
define( 'HEALTH_CHECK_MYSQL_REC_VERSION', '5.6' );
// Set the plugin version.
define( 'HEALTH_CHECK_PLUGIN_VERSION', '1.4.5' );
define( 'HEALTH_CHECK_PLUGIN_VERSION', '1.5.1' );
// Set the plugin file.
define( 'HEALTH_CHECK_PLUGIN_FILE', __FILE__ );
@ -46,42 +35,44 @@ define( 'HEALTH_CHECK_PLUGIN_DIRECTORY', plugin_dir_path( __FILE__ ) );
// Set the plugin URL root.
define( 'HEALTH_CHECK_PLUGIN_URL', plugins_url( '/', __FILE__ ) );
// Set the current cURL version.
define( 'HEALTH_CHECK_CURL_VERSION', '7.58' );
// Set the minimum cURL version that we've tested that core works with.
define( 'HEALTH_CHECK_CURL_MIN_VERSION', '7.38' );
// Always include our compatibility file first.
require_once( dirname( __FILE__ ) . '/includes/compat.php' );
require_once( dirname( __FILE__ ) . '/compat.php' );
// Backwards compatible pull in of extra resources
if ( ! class_exists( 'WP_Debug_Data' ) ) {
$original_paths = array(
'class-wp-site-health.php' => ABSPATH . '/wp-admin/includes/class-wp-site-health.php',
'class-wp-debug-data.php' => ABSPATH . '/wp-admin/includes/class-wp-debug-data.php',
);
foreach ( $original_paths as $filename => $original_path ) {
if ( file_exists( $original_path ) ) {
require_once $original_path;
} else {
require_once __DIR__ . '/HealthCheck/BackCompat/' . $filename;
if ( ! defined( 'HEALTH_CHECK_BACKCOMPAT_LOADED' ) ) {
define( 'HEALTH_CHECK_BACKCOMPAT_LOADED', true );
}
}
}
}
// Include class-files used by our plugin.
require_once( dirname( __FILE__ ) . '/includes/class-health-check.php' );
require_once( dirname( __FILE__ ) . '/includes/class-health-check-auto-updates.php' );
require_once( dirname( __FILE__ ) . '/includes/class-health-check-wp-cron.php' );
require_once( dirname( __FILE__ ) . '/includes/class-health-check-debug-data.php' );
require_once( dirname( __FILE__ ) . '/includes/class-health-check-loopback.php' );
require_once( dirname( __FILE__ ) . '/includes/class-health-check-troubleshoot.php' );
require_once( dirname( __FILE__ ) . '/includes/class-health-check-site-status.php' );
require_once( dirname( __FILE__ ) . '/includes/class-health-check-updates.php' );
require_once( dirname( __FILE__ ) . '/includes/class-health-check-dashboard-widget.php' );
require_once( dirname( __FILE__ ) . '/HealthCheck/class-health-check.php' );
require_once( dirname( __FILE__ ) . '/HealthCheck/class-health-check-loopback.php' );
require_once( dirname( __FILE__ ) . '/HealthCheck/class-health-check-troubleshoot.php' );
// Tools section.
require_once( dirname( __FILE__ ) . '/includes/tools/class-health-check-tool.php' );
require_once( dirname( __FILE__ ) . '/includes/tools/class-health-check-files-integrity.php' );
require_once( dirname( __FILE__ ) . '/includes/tools/class-health-check-mail-check.php' );
require_once( dirname( __FILE__ ) . '/includes/tools/class-health-check-plugin-compatibility.php' );
require_once( dirname( __FILE__ ) . '/HealthCheck/Tools/class-health-check-tool.php' );
require_once( dirname( __FILE__ ) . '/HealthCheck/Tools/class-health-check-files-integrity.php' );
require_once( dirname( __FILE__ ) . '/HealthCheck/Tools/class-health-check-mail-check.php' );
require_once( dirname( __FILE__ ) . '/HealthCheck/Tools/class-health-check-plugin-compatibility.php' );
require_once( dirname( __FILE__ ) . '/HealthCheck/Tools/class-health-check-phpinfo.php' );
// Initialize our plugin.
new Health_Check();
// Initialize the dashboard widget.
new Health_Check_Dashboard_Widget();
// Setup up scheduled events.
register_activation_hook( __FILE__, array( 'Health_Check', 'plugin_activation' ) );
register_deactivation_hook( __FILE__, array( 'Health_Check', 'plugin_deactivation' ) );
if ( defined( 'WP_CLI' ) && WP_CLI ) {
require_once( dirname( __FILE__ ) . '/includes/class-health-check-wp-cli.php' );
require_once( dirname( __FILE__ ) . '/HealthCheck/class-cli.php' );
}

View File

@ -1,453 +0,0 @@
<?php
/**
* Class for testing automatic updates in the WordPress code.
*
* @package Health Check
*/
// Make sure the file is not directly accessible.
if ( ! defined( 'ABSPATH' ) ) {
die( 'We\'re sorry, but you can not directly access this file.' );
}
/**
* Class Health_Check_Auto_Updates
*/
class Health_Check_Auto_Updates {
/**
* WP_Site_Health_Auto_Updates constructor.
* @since 5.2.0
*/
public function __construct() {
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
}
public function run_tests() {
$tests = array();
foreach ( get_class_methods( $this ) as $method ) {
if ( 'test_' !== substr( $method, 0, 5 ) ) {
continue;
}
$result = call_user_func( array( $this, $method ) );
if ( false === $result || null === $result ) {
continue;
}
$result = (object) $result;
if ( empty( $result->severity ) ) {
$result->severity = 'warning';
}
$tests[ $method ] = $result;
}
return $tests;
}
public function test_contant_DISALLOW_FILE_MODS() {
return $this->check_constants( 'DISALLOW_FILE_MODS', false );
}
public function test_contant_AUTOMATIC_UPDATER_DISABLED() {
return $this->check_constants( 'AUTOMATIC_UPDATER_DISABLED', false );
}
public function test_contant_WP_AUTO_UPDATE_CORE() {
return $this->check_constants( 'WP_AUTO_UPDATE_CORE', true );
}
/**
* Test if auto-updates related constants are set correctly.
*
* @since 5.2.0
*
* @param string $constant The name of the constant to check.
* @param bool $value The value that the constant should be, if set.
* @return array The test results.
*/
public function check_constants( $constant, $value ) {
if ( defined( $constant ) && constant( $constant ) != $value ) {
return array(
'description' => sprintf(
/* translators: %s: Name of the constant used. */
__( 'The %s constant is defined and enabled.', 'health-check' ),
"<code>$constant</code>"
),
'severity' => 'fail',
);
}
}
/**
* Check if updates are intercepted by a filter.
*
* @since 5.2.0
*
* @return array The test results.
*/
public function test_wp_version_check_attached() {
if ( ! is_main_site() ) {
return;
}
$cookies = wp_unslash( $_COOKIE );
$timeout = 10;
$headers = array(
'Cache-Control' => 'no-cache',
);
// Include Basic auth in loopback requests.
if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) {
$headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
}
$url = add_query_arg(
array(
'health-check-test-wp_version_check' => true,
),
admin_url( '' )
);
$test = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout' ) );
if ( is_wp_error( $test ) ) {
return array(
'description' => sprintf(
/* translators: %s: Name of the filter used. */
__( 'Could not confirm that the %s filter is available.', 'health-check' ),
'<code>wp_version_check()</code>'
),
'severity' => 'warning',
);
}
$response = wp_remote_retrieve_body( $test );
if ( 'yes' !== $response ) {
return array(
'description' => sprintf(
/* translators: %s: Name of the filter used. */
__( 'A plugin has prevented updates by disabling %s.', 'health-check' ),
'<code>wp_version_check()</code>'
),
'severity' => 'fail',
);
}
}
/**
* Check if automatic updates are disabled by a filter.
*
* @since 5.2.0
*
* @return array The test results.
*/
public function test_filters_automatic_updater_disabled() {
if ( apply_filters( 'automatic_updater_disabled', false ) ) {
return array(
'description' => sprintf(
/* translators: %s: Name of the filter used. */
__( 'The %s filter is enabled.', 'health-check' ),
'<code>automatic_updater_disabled</code>'
),
'severity' => 'fail',
);
}
}
/**
* Check if automatic updates have tried to run, but failed, previously.
*
* @since 5.2.0
*
* @return array|bool The test results. false if the auto updates failed.
*/
function test_if_failed_update() {
$failed = get_site_option( 'auto_core_update_failed' );
if ( ! $failed ) {
return false;
}
if ( ! empty( $failed['critical'] ) ) {
$description = __( 'A previous automatic background update ended with a critical failure, so updates are now disabled.', 'health-check' );
$description .= ' ' . __( 'You would have received an email because of this.', 'health-check' );
$description .= ' ' . __( "When you've been able to update using the \"Update Now\" button on Dashboard > Updates, we'll clear this error for future update attempts.", 'health-check' );
$description .= ' ' . sprintf(
/* translators: %s: Code of error shown. */
__( 'The error code was %s.', 'health-check' ),
'<code>' . $failed['error_code'] . '</code>'
);
return array(
'description' => $description,
'severity' => 'warning',
);
}
$description = __( 'A previous automatic background update could not occur.', 'health-check' );
if ( empty( $failed['retry'] ) ) {
$description .= ' ' . __( 'You would have received an email because of this.', 'health-check' );
}
$description .= ' ' . __( "We'll try again with the next release.", 'health-check' );
$description .= ' ' . sprintf(
/* translators: %s: Code of error shown. */
__( 'The error code was %s.', 'health-check' ),
'<code>' . $failed['error_code'] . '</code>'
);
return array(
'description' => $description,
'severity' => 'warning',
);
}
/**
* Check if WordPress is controlled by a VCS (Git, Subversion etc).
*
* @since 5.2.0
*
* @return array The test results.
*/
public function test_vcs_abspath() {
$context_dirs = array( ABSPATH );
$vcs_dirs = array( '.svn', '.git', '.hg', '.bzr' );
$check_dirs = array();
foreach ( $context_dirs as $context_dir ) {
// Walk up from $context_dir to the root.
do {
$check_dirs[] = $context_dir;
// Once we've hit '/' or 'C:\', we need to stop. dirname will keep returning the input here.
if ( dirname( $context_dir ) == $context_dir ) {
break;
}
// Continue one level at a time.
} while ( $context_dir = dirname( $context_dir ) );
}
$check_dirs = array_unique( $check_dirs );
// Search all directories we've found for evidence of version control.
foreach ( $vcs_dirs as $vcs_dir ) {
foreach ( $check_dirs as $check_dir ) {
// phpcs:ignore
if ( $checkout = @is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" ) ) {
break 2;
}
}
}
if ( $checkout && ! apply_filters( 'automatic_updates_is_vcs_checkout', true, ABSPATH ) ) {
return array(
'description' => sprintf(
// translators: 1: Folder name. 2: Version control directory. 3: Filter name.
__( 'The folder %1$s was detected as being under version control (%2$s), but the %3$s filter is allowing updates.', 'health-check' ),
'<code>' . $check_dir . '</code>',
"<code>$vcs_dir</code>",
'<code>automatic_updates_is_vcs_checkout</code>'
),
'severity' => 'info',
);
}
if ( $checkout ) {
return array(
'description' => sprintf(
// translators: 1: Folder name. 2: Version control directory.
__( 'The folder %1$s was detected as being under version control (%2$s).', 'health-check' ),
'<code>' . $check_dir . '</code>',
"<code>$vcs_dir</code>"
),
'severity' => 'fail',
);
}
return array(
'description' => __( 'No version control systems were detected.', 'health-check' ),
'severity' => 'pass',
);
}
/**
* Check if we can access files without providing credentials.
*
* @since 5.2.0
*
* @return array The test results.
*/
function test_check_wp_filesystem_method() {
$skin = new Automatic_Upgrader_Skin;
$success = $skin->request_filesystem_credentials( false, ABSPATH );
if ( ! $success ) {
$description = __( 'Your installation of WordPress prompts for FTP credentials to perform updates.', 'health-check' );
$description .= ' ' . __( '(Your site is performing updates over FTP due to file ownership. Talk to your hosting company.)', 'health-check' );
return array(
'description' => $description,
'severity' => 'fail',
);
}
return array(
'description' => __( "Your installation of WordPress doesn't require FTP credentials to perform updates.", 'health-check' ),
'severity' => 'pass',
);
}
/**
* Check if core files are writable by the web user/group.
*
* @since 5.2.0
*
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
*
* @return array|bool The test results. false if they're not writeable.
*/
function test_all_files_writable() {
global $wp_filesystem;
include ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
$skin = new Automatic_Upgrader_Skin;
$success = $skin->request_filesystem_credentials( false, ABSPATH );
if ( ! $success ) {
return false;
}
WP_Filesystem();
if ( 'direct' != $wp_filesystem->method ) {
return false;
}
$checksums = get_core_checksums( $wp_version, 'en_US' );
$dev = ( false !== strpos( $wp_version, '-' ) );
// Get the last stable version's files and test against that
if ( ! $checksums && $dev ) {
$checksums = get_core_checksums( (float) $wp_version - 0.1, 'en_US' );
}
// There aren't always checksums for development releases, so just skip the test if we still can't find any
if ( ! $checksums && $dev ) {
return false;
}
if ( ! $checksums ) {
$description = sprintf(
// translators: %s: WordPress version
__( "Couldn't retrieve a list of the checksums for WordPress %s.", 'health-check' ),
$wp_version
);
$description .= ' ' . __( 'This could mean that connections are failing to WordPress.org.', 'health-check' );
return array(
'description' => $description,
'severity' => 'warning',
);
}
$unwritable_files = array();
foreach ( array_keys( $checksums ) as $file ) {
if ( 'wp-content' == substr( $file, 0, 10 ) ) {
continue;
}
if ( ! file_exists( ABSPATH . $file ) ) {
continue;
}
if ( ! is_writable( ABSPATH . $file ) ) {
$unwritable_files[] = $file;
}
}
if ( $unwritable_files ) {
if ( count( $unwritable_files ) > 20 ) {
$unwritable_files = array_slice( $unwritable_files, 0, 20 );
$unwritable_files[] = '...';
}
return array(
'description' => __( 'Some files are not writable by WordPress:', 'health-check' ) . ' <ul><li>' . implode( '</li><li>', $unwritable_files ) . '</li></ul>',
'severity' => 'fail',
);
} else {
return array(
'description' => __( 'All of your WordPress files are writable.', 'health-check' ),
'severity' => 'pass',
);
}
}
/**
* Check if the install is using a development branch and can use nightly packages.
*
* @since 5.2.0
*
* @return array|bool The test results. false if it isn't a development version.
*/
function test_accepts_dev_updates() {
include ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
// Only for dev versions
if ( false === strpos( $wp_version, '-' ) ) {
return false;
}
if ( defined( 'WP_AUTO_UPDATE_CORE' ) && ( 'minor' === WP_AUTO_UPDATE_CORE || false === WP_AUTO_UPDATE_CORE ) ) {
return array(
'description' => sprintf(
/* translators: %s: Name of the constant used. */
__( 'WordPress development updates are blocked by the %s constant.', 'health-check' ),
'<code>WP_AUTO_UPDATE_CORE</code>'
),
'severity' => 'fail',
);
}
if ( ! apply_filters( 'allow_dev_auto_core_updates', $wp_version ) ) {
return array(
'description' => sprintf(
/* translators: %s: Name of the filter used. */
__( 'WordPress development updates are blocked by the %s filter.', 'health-check' ),
'<code>allow_dev_auto_core_updates</code>'
),
'severity' => 'fail',
);
}
}
/**
* Check if the site supports automatic minor updates.
*
* @since 5.2.0
*
* @return array The test results.
*/
function test_accepts_minor_updates() {
if ( defined( 'WP_AUTO_UPDATE_CORE' ) && false === WP_AUTO_UPDATE_CORE ) {
return array(
'description' => sprintf(
/* translators: %s: Name of the constant used. */
__( 'WordPress security and maintenance releases are blocked by %s.', 'health-check' ),
"<code>define( 'WP_AUTO_UPDATE_CORE', false );</code>"
),
'severity' => 'fail',
);
}
if ( ! apply_filters( 'allow_minor_auto_core_updates', true ) ) {
return array(
'description' => sprintf(
/* translators: %s: Name of the filter used. */
__( 'WordPress security and maintenance releases are blocked by the %s filter.', 'health-check' ),
'<code>allow_minor_auto_core_updates</code>'
),
'severity' => 'fail',
);
}
}
}

View File

@ -1,101 +0,0 @@
<?php
// Check that the file is not accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
die( 'We\'re sorry, but you can not directly access this file.' );
}
class Health_Check_Dashboard_Widget {
public function __construct() {
add_action( 'wp_dashboard_setup', array( $this, 'dashboard_setup' ) );
}
function dashboard_setup() {
global $wp_meta_boxes;
if ( ! isset( $wp_meta_boxes['dashboard']['normal']['core']['dashboard_site_health'] ) ) {
wp_add_dashboard_widget(
'dashboard_site_health',
__( 'Site Health Status', 'health-check' ),
array( $this, 'widget_render' )
);
} else {
$wp_meta_boxes['dashboard']['normal']['core']['dashboard_site_health']['callback'] = array( $this, 'widget_render' );
}
}
function widget_render() {
$get_issues = get_transient( 'health-check-site-status-result' );
if ( false !== $get_issues ) {
$issue_counts = json_decode( $get_issues );
} else {
$issue_counts = (object) array(
'good' => 0,
'recommended' => 0,
'critical' => 0,
);
}
$issues_total = $issue_counts->recommended + $issue_counts->critical;
?>
<div class="health-check-title-section site-health-progress-wrapper loading hide-if-no-js">
<div class="site-health-progress">
<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">
<circle r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
<circle id="bar" r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
</svg>
</div>
<div class="site-health-progress-label">
<?php if ( false === $get_issues ) : ?>
<?php _e( 'No information yet&hellip;', 'health-check' ); ?>
<?php else : ?>
<?php _e( 'Results are still loading&hellip;', 'health-check' ); ?>
<?php endif; ?>
</div>
</div>
<?php if ( false === $get_issues ) : ?>
<p>
<?php _e( 'No Site Health information has been gathered yet, you can do so by visiting the Site Health page, alternatively the checks will run automatically once every week.', 'health-check' ); ?>
</p>
<p>
<?php
printf(
// translators: %s: URL for the Site Health page.
__( '<a href="%s">Visit the Site Health page</a> to gather information on about your site..', 'health-check' ),
esc_url( admin_url( 'tools.php?page=health-check' ) )
);
?>
</p>
<?php else : ?>
<p>
<?php if ( $issue_counts->critical > 0 ) : ?>
<?php _e( 'Your site has critical issues that should be addressed as soon as possible to improve the performance or security of your website.', 'health-check' ); ?>
<?php elseif ( $issues_total <= 0 ) : ?>
<?php _e( 'Great job! Your site currently passes all site health checks.', 'health-check' ); ?>
<?php else : ?>
<?php _e( 'Your site scores pretty well on the Health Check, but there are still some things you can do to improve the performance and security of your website.', 'health-check' ); ?>
<?php endif; ?>
</p>
<?php endif; ?>
<?php if ( $issues_total > 0 && false !== $get_issues ) : ?>
<p>
<?php
printf(
// translators: 1: Count of issues. 2: URL for the Site Health page.
__( 'Take a look at the <strong>%1$d items</strong> on the <a href="%2$s">Site Health Check status page</a>.', 'health-check' ),
$issues_total,
esc_url( admin_url( 'tools.php?page=health-check' ) )
);
?>
</p>
<?php endif; ?>
<?php
}
}

View File

@ -1,592 +0,0 @@
<?php
/**
* Class for testing plugin/theme updates in the WordPress code.
*
* @package Health Check
*/
// Make sure the file is not directly accessible.
if ( ! defined( 'ABSPATH' ) ) {
die( 'We\'re sorry, but you can not directly access this file.' );
}
/**
* Class Health_Check_Updates
*/
class Health_Check_Updates {
private $plugins_before;
private $plugins_after;
private static $plugins_blocked;
private $themes_before;
private $themes_after;
private static $themes_blocked;
/**
* Health_Check_Updates constructor.
*
* @uses Health_Check_Updates::init()
*
* @return void
*/
public function __construct() {
$this->init();
}
/**
* Initiate the plugin class.
*
* @return void
*/
public function init() {
$this->plugins_before = (array) array();
$this->plugins_after = (array) array();
self::$plugins_blocked = (bool) false;
$this->themes_before = (array) array();
$this->themes_after = (array) array();
self::$themes_blocked = (bool) false;
}
/**
* Run tests to determine if auto-updates can run.
*
* @uses get_class_methods()
* @uses substr()
* @uses call_user_func()
*
* @return array
*/
public function run_tests() {
$tests = array();
foreach ( get_class_methods( $this ) as $method ) {
if ( 'test_' !== substr( $method, 0, 5 ) ) {
continue;
}
$result = call_user_func( array( $this, $method ) );
if ( false === $result || null === $result ) {
continue;
}
$result = (object) $result;
if ( empty( $result->severity ) ) {
$result->severity = 'warning';
}
$tests[ $method ] = $result;
}
return $tests;
}
/**
* Check if plugin updates have been tampered with.
*
* @uses Health_Check_Updates::check_plugin_update_hooks()
* @uses esc_html__()
* @uses Health_Check_Updates::check_plugin_update_pre_request()
* @uses Health_Check_Updates::check_plugin_update_request_args()
*
* @return array
*/
function test_plugin_updates() {
// Check if any update hooks have been removed.
$hooks = $this->check_plugin_update_hooks();
if ( ! $hooks ) {
return array(
'desc' => esc_html__( 'Plugin update hooks have been removed.', 'health-check' ),
'severity' => 'fail',
);
}
// Check if update requests are being blocked.
$blocked = $this->check_plugin_update_pre_request();
if ( true === $blocked ) {
return array(
'desc' => esc_html__( 'Plugin update requests have been blocked.', 'health-check' ),
'severity' => 'fail',
);
}
// Check if plugins have been removed from the update requests.
$diff = (array) $this->check_plugin_update_request_args();
if ( 0 !== count( $diff ) ) {
return array(
'desc' => sprintf(
/* translators: %s: List of plugin names. */
esc_html__( 'The following Plugins have been removed from update checks: %s.', 'health-check' ),
implode( ',', $diff )
),
'severity' => 'warning',
);
}
return array(
'desc' => esc_html__( 'Plugin updates should be working as expected.', 'health-check' ),
'severity' => 'pass',
);
}
/**
* Check if any plugin update hooks have been removed.
*
* @uses has_filter()
* @uses wp_next_scheduled()
*
* @return array
*/
function check_plugin_update_hooks() {
$test1 = has_filter( 'load-plugins.php', 'wp_update_plugins' );
$test2 = has_filter( 'load-update.php', 'wp_update_plugins' );
$test3 = has_filter( 'load-update-core.php', 'wp_update_plugins' );
$test4 = has_filter( 'wp_update_plugins', 'wp_update_plugins' );
$test5 = has_filter( 'admin_init', '_maybe_update_plugins' );
$test6 = wp_next_scheduled( 'wp_update_plugins' );
return $test1 && $test2 && $test3 && $test4 && $test5 && $test6;
}
/**
* Check if plugin update request checks are being tampered with at the 'pre_http_request' filter.
*
* @uses add_action()
* @uses Health_Check_Updates::wp_plugin_update_fake_request()
* @uses esc_html__()
*
* @return array
*/
function check_plugin_update_pre_request() {
add_action( 'pre_http_request', array( $this, 'plugin_pre_request_check' ), PHP_INT_MAX, 3 );
add_action( 'pre_http_request', array( $this, 'block_fake_request' ), PHP_INT_MAX, 3 );
$this->plugin_update_fake_request();
remove_action( 'pre_http_request', array( $this, 'plugin_pre_request_check' ), PHP_INT_MAX );
remove_action( 'pre_http_request', array( $this, 'block_fake_request' ), PHP_INT_MAX );
return self::$plugins_blocked;
}
/**
* Check plugin update requests to see if they are being blocked.
*
* @param bool $pre If not false, request cancelled.
* @param array $r Request parameters.
* @param string $url Request URL.
* @return bool
*/
function plugin_pre_request_check( $pre, $r, $url ) {
$check_url = 'api.wordpress.org/plugins/update-check/1.1/';
if ( 0 !== substr_compare( $url, $check_url, -strlen( $check_url ) ) ) {
return $pre; // Not a plugin update request.
}
// If not false something is blocking update checks
if ( false !== $pre ) {
self::$plugins_blocked = (bool) true;
}
return $pre;
}
/**
* Check if plugins are being removed at the 'http_request_args' filter.
*
* @uses add_action()
* @uses Health_Check_Updates::wp_plugin_update_fake_request()
* @uses remove_action()
*
* @return array
*/
function check_plugin_update_request_args() {
add_action( 'http_request_args', array( $this, 'plugin_request_args_before' ), 1, 2 );
add_action( 'http_request_args', array( $this, 'plugin_request_args_after' ), PHP_INT_MAX, 2 );
add_action( 'pre_http_request', array( $this, 'block_fake_request' ), PHP_INT_MAX, 3 );
$this->plugin_update_fake_request();
remove_action( 'http_request_args', array( $this, 'plugin_request_args_before' ), 1 );
remove_action( 'http_request_args', array( $this, 'plugin_request_args_after' ), PHP_INT_MAX );
remove_action( 'pre_http_request', array( $this, 'block_fake_request' ), PHP_INT_MAX );
$diff = array_diff_key( $this->plugins_before['plugins'], $this->plugins_after['plugins'] );
$titles = array();
foreach ( $diff as $item ) {
$titles[] = $item['Title'];
}
return $titles;
}
/**
* Record the list of plugins from plugin update requests at the start of filtering.
*
* @param array $r Request parameters.
* @param string $url Request URL.
* @return array
*/
function plugin_request_args_before( $r, $url ) {
$check_url = 'api.wordpress.org/plugins/update-check/1.1/';
if ( 0 !== substr_compare( $url, $check_url, -strlen( $check_url ) ) ) {
return $r; // Not a plugin update request.
}
$this->plugins_before = (array) json_decode( $r['body']['plugins'], true );
return $r;
}
/**
* Record the list of plugins from plugin update requests at the end of filtering.
*
* @param array $r Request parameters.
* @param string $url Request URL.
* @return array
*/
function plugin_request_args_after( $r, $url ) {
$check_url = 'api.wordpress.org/plugins/update-check/1.1/';
if ( 0 !== substr_compare( $url, $check_url, -strlen( $check_url ) ) ) {
return $r; // Not a plugin update request.
}
$this->plugins_after = (array) json_decode( $r['body']['plugins'], true );
return $r;
}
/**
* Create and trigger a fake plugin update check request.
*
* @uses get_plugins()
* @uses get_option()
* @uses wp_get_installed_translations()
* @uses apply_filters()
* @uses wp_json_encode()
* @uses get_bloginfo()
* @uses home_url()
* @uses wp_http_supports()
* @uses set_url_scheme()
* @uses wp_remote_post()
*
* @return void
*/
function plugin_update_fake_request() {
if ( ! function_exists( 'get_plugins' ) ) {
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
// Prepare data for the request.
$plugins = get_plugins();
$active = get_option( 'active_plugins', array() );
$to_send = compact( 'plugins', 'active' );
$translations = wp_get_installed_translations( 'plugins' );
$locales = array_values( get_available_languages() );
$locales = (array) apply_filters( 'plugins_update_check_locales', $locales );
$locales = array_unique( $locales );
$timeout = 3 + (int) ( count( $plugins ) / 10 );
// Setup the request options.
if ( function_exists( 'wp_json_encode' ) ) {
$options = array(
'timeout' => $timeout,
'body' => array(
'plugins' => wp_json_encode( $to_send ),
'translations' => wp_json_encode( $translations ),
'locale' => wp_json_encode( $locales ),
'all' => wp_json_encode( true ),
),
'user-agent' => 'WordPress/' . get_bloginfo( 'version' ) . '; ' . home_url( '/' ),
);
} else {
$options = array(
'timeout' => $timeout,
'body' => array(
'plugins' => json_encode( $to_send ),
'translations' => json_encode( $translations ),
'locale' => json_encode( $locales ),
'all' => json_encode( true ),
),
'user-agent' => 'WordPress/' . get_bloginfo( 'version' ) . '; ' . home_url( '/' ),
);
}
// Set the URL
$http_url = 'http://api.wordpress.org/plugins/update-check/1.1/';
$url = wp_http_supports( array( 'ssl' ) ) ? set_url_scheme( $http_url, 'https' ) : $http_url;
// Ignore the response. Just need the hooks to fire.
wp_remote_post( $url, $options );
}
/**
* Check if theme updates have been tampered with.
*
* @uses Health_Check_Updates::check_theme_update_hooks()
* @uses esc_html__()
* @uses Health_Check_Updates::check_theme_update_pre_request()
* @uses Health_Check_Updates::check_theme_update_request_args()
*
* @return array
*/
function test_constant_theme_updates() {
// Check if any update hooks have been removed.
$hooks = $this->check_theme_update_hooks();
if ( ! $hooks ) {
return array(
'desc' => esc_html__( 'Theme update hooks have been removed.', 'health-check' ),
'severity' => 'fail',
);
}
// Check if update requests are being blocked.
$blocked = $this->check_theme_update_pre_request();
if ( true === $blocked ) {
return array(
'desc' => esc_html__( 'Theme update requests have been blocked.', 'health-check' ),
'severity' => 'fail',
);
}
// Check if themes have been removed from the update requests.
$diff = (array) $this->check_theme_update_request_args();
if ( 0 !== count( $diff ) ) {
return array(
'desc' => sprintf(
/* translators: %s: List of theme names. */
esc_html__( 'The following Themes have been removed from update checks: %s.', 'health-check' ),
implode( ',', $diff )
),
'severity' => 'warning',
);
}
return array(
'desc' => esc_html__( 'Theme updates should be working as expected.', 'health-check' ),
'severity' => 'pass',
);
}
/**
* Check if any theme update hooks have been removed.
*
* @uses has_filter()
* @uses wp_next_scheduled()
*
* @return array
*/
function check_theme_update_hooks() {
$test1 = has_filter( 'load-themes.php', 'wp_update_themes' );
$test2 = has_filter( 'load-update.php', 'wp_update_themes' );
$test3 = has_filter( 'load-update-core.php', 'wp_update_themes' );
$test4 = has_filter( 'wp_update_themes', 'wp_update_themes' );
$test5 = has_filter( 'admin_init', '_maybe_update_themes' );
$test6 = wp_next_scheduled( 'wp_update_themes' );
return $test1 && $test2 && $test3 && $test4 && $test5 && $test6;
}
/**
* Check if theme update request checks are being tampered with at the 'pre_http_request' filter.
*
* @uses add_action()
* @uses Health_Check_Updates::wp_theme_update_fake_request()
* @uses esc_html__()
*
* @return array
*/
function check_theme_update_pre_request() {
add_action( 'pre_http_request', array( $this, 'theme_pre_request_check' ), PHP_INT_MAX, 3 );
add_action( 'pre_http_request', array( $this, 'block_fake_request' ), PHP_INT_MAX, 3 );
$this->theme_update_fake_request();
remove_action( 'pre_http_request', array( $this, 'theme_pre_request_check' ), PHP_INT_MAX );
remove_action( 'pre_http_request', array( $this, 'block_fake_request' ), PHP_INT_MAX );
return self::$themes_blocked;
}
/**
* Check theme update requests to see if they are being blocked.
*
* @param bool $pre If not false, request cancelled.
* @param array $r Request parameters.
* @param string $url Request URL.
* @return bool
*/
function theme_pre_request_check( $pre, $r, $url ) {
$check_url = 'api.wordpress.org/themes/update-check/1.1/';
if ( 0 !== substr_compare( $url, $check_url, -strlen( $check_url ) ) ) {
return $pre; // Not a theme update request.
}
// If not false something is blocking update checks
if ( false !== $pre ) {
self::$themes_blocked = (bool) true;
}
return $pre;
}
/**
* Check if themes are being removed at the 'http_request_args' filter.
*
* @uses add_action()
* @uses Health_Check_Updates::wp_theme_update_fake_request()
* @uses remove_action()
*
* @return array
*/
function check_theme_update_request_args() {
add_action( 'http_request_args', array( $this, 'theme_request_args_before' ), 1, 2 );
add_action( 'http_request_args', array( $this, 'theme_request_args_after' ), PHP_INT_MAX, 2 );
add_action( 'pre_http_request', array( $this, 'block_fake_request' ), PHP_INT_MAX, 3 );
$this->theme_update_fake_request();
remove_action( 'http_request_args', array( $this, 'theme_request_args_before' ), 1 );
remove_action( 'http_request_args', array( $this, 'theme_request_args_after' ), PHP_INT_MAX );
remove_action( 'pre_http_request', array( $this, 'block_fake_request' ), PHP_INT_MAX );
$diff = array_diff_key( $this->themes_before['themes'], $this->themes_after['themes'] );
$titles = array();
foreach ( $diff as $item ) {
$titles[] = $item['Title'];
}
return $titles;
}
/**
* Record the list of themes from theme update requests at the start of filtering.
*
* @param array $r Request parameters.
* @param string $url Request URL.
* @return array
*/
function theme_request_args_before( $r, $url ) {
$check_url = 'api.wordpress.org/themes/update-check/1.1/';
if ( 0 !== substr_compare( $url, $check_url, -strlen( $check_url ) ) ) {
return $r; // Not a theme update request.
}
$this->themes_before = (array) json_decode( $r['body']['themes'], true );
return $r;
}
/**
* Record the list of themes from theme update requests at the end of filtering.
*
* @param array $r Request parameters.
* @param string $url Request URL.
* @return array
*/
function theme_request_args_after( $r, $url ) {
$check_url = 'api.wordpress.org/themes/update-check/1.1/';
if ( 0 !== substr_compare( $url, $check_url, -strlen( $check_url ) ) ) {
return $r; // Not a theme update request.
}
$this->themes_after = (array) json_decode( $r['body']['themes'], true );
return $r;
}
/**
* Create and trigger a fake theme update check request.
*
* @uses wp_get_themes()
* @uses wp_get_installed_translations()
* @uses get_option()
* @uses get_available_languages()
* @uses wp_json_encode()
* @uses get_bloginfo()
* @uses home_url()
* @uses wp_http_supports()
* @uses set_url_scheme()
* @uses wp_remote_post()
*
* @return void
*/
function theme_update_fake_request() {
$themes = array();
$checked = array();
$request = array();
$installed_themes = wp_get_themes();
$translations = wp_get_installed_translations( 'themes' );
$request['active'] = get_option( 'stylesheet' );
foreach ( $installed_themes as $theme ) {
$checked[ $theme->get_stylesheet() ] = $theme->get( 'Version' );
$themes[ $theme->get_stylesheet() ] = array(
'Name' => $theme->get( 'Name' ),
'Title' => $theme->get( 'Name' ),
'Version' => $theme->get( 'Version' ),
'Author' => $theme->get( 'Author' ),
'Author URI' => $theme->get( 'AuthorURI' ),
'Template' => $theme->get_template(),
'Stylesheet' => $theme->get_stylesheet(),
);
}
$request['themes'] = $themes;
$locales = array_values( get_available_languages() );
$timeout = 3 + (int) ( count( $themes ) / 10 );
if ( function_exists( 'wp_json_encode' ) ) {
$options = array(
'timeout' => $timeout,
'body' => array(
'themes' => wp_json_encode( $request ),
'translations' => wp_json_encode( $translations ),
'locale' => wp_json_encode( $locales ),
),
'user-agent' => 'WordPress/' . get_bloginfo( 'version' ) . '; ' . home_url( '/' ),
);
} else {
$options = array(
'timeout' => $timeout,
'body' => array(
'themes' => json_encode( $request ),
'translations' => json_encode( $translations ),
'locale' => json_encode( $locales ),
),
'user-agent' => 'WordPress/' . get_bloginfo( 'version' ) . '; ' . home_url( '/' ),
);
}
// Set the URL
$http_url = 'http://api.wordpress.org/themes/update-check/1.1/';
$url = wp_http_supports( array( 'ssl' ) ) ? set_url_scheme( $http_url, 'https' ) : $http_url;
// Ignore the response. Just need the hooks to fire.
wp_remote_post( $url, $options );
}
/**
* Blocks the fake update requests, ensuring they do not slow down page loads.
*
* @param bool $pre If not false, request cancelled.
* @param array $r Request parameters.
* @param string $url Request URL.
* @return bool
*/
function block_fake_request( $pre, $r, $url ) {
switch ( $url ) {
case 'https://api.wordpress.org/plugins/update-check/1.1/':
return 'block_request';
case 'https://api.wordpress.org/themes/update-check/1.1/':
return 'block_request';
default:
return $pre;
}
}
}

View File

@ -1,143 +0,0 @@
<?php
/**
* Perform tests to see if WP_Cron is operating as it should.
*
* @package Health Check
*/
// Make sure the file is not directly accessible.
if ( ! defined( 'ABSPATH' ) ) {
die( 'We\'re sorry, but you can not directly access this file.' );
}
/**
* Class Health_Check_WP_Cron
*/
class Health_Check_WP_Cron {
public $schedules;
public $crons;
public $last_missed_cron = null;
public $last_late_cron = null;
private $timeout_missed_cron = null;
private $timeout_late_cron = null;
/**
* Health_Check_WP_Cron constructor.
*/
public function __construct() {
$this->init();
$this->timeout_late_cron = 0;
$this->timeout_missed_cron = - 5 * MINUTE_IN_SECONDS;
if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) {
$this->timeout_late_cron = - 15 * MINUTE_IN_SECONDS;
$this->timeout_missed_cron = - 1 * HOUR_IN_SECONDS;
}
}
/**
* Initiate the class
*
* @uses wp_get_schedules()
* @uses Health_Check_WP_Cron::get_cron_tasks()
*
* @return void
*/
public function init() {
$this->schedules = wp_get_schedules();
$this->get_cron_tasks();
}
/**
* Populate our list of cron events and store them to a class-wide variable.
*
* Derived from `get_cron_events()` in WP Crontrol (https://plugins.svn.wordpress.org/wp-crontrol)
* by John Blackburn.
*
* @uses _get_cron_array()
* @uses WP_Error
*
* @return void
*/
private function get_cron_tasks() {
$cron_tasks = _get_cron_array();
if ( empty( $cron_tasks ) ) {
$this->crons = new WP_Error( 'no_tasks', __( 'No scheduled events exist on this site.', 'health-check' ) );
return;
}
$this->crons = array();
foreach ( $cron_tasks as $time => $cron ) {
foreach ( $cron as $hook => $dings ) {
foreach ( $dings as $sig => $data ) {
$this->crons[ "$hook-$sig-$time" ] = (object) array(
'hook' => $hook,
'time' => $time,
'sig' => $sig,
'args' => $data['args'],
'schedule' => $data['schedule'],
'interval' => isset( $data['interval'] ) ? $data['interval'] : null,
);
}
}
}
}
/**
* Check if any scheduled tasks have been missed.
*
* Returns a boolean value of `true` if a scheduled task has been missed and ends processing.
* If the list of crons is an instance of WP_Error, return the instance instead of a boolean value.
*
* @uses is_wp_error()
* @uses time()
*
* @return bool|WP_Error
*/
public function has_missed_cron() {
if ( is_wp_error( $this->crons ) ) {
return $this->crons;
}
foreach ( $this->crons as $id => $cron ) {
if ( ( $cron->time - time() ) < $this->timeout_missed_cron ) {
$this->last_missed_cron = $cron->hook;
return true;
}
}
return false;
}
/**
* Check if any scheduled tasks are late.
*
* Returns a boolean value of `true` if a scheduled task is late and ends processing. If the list of
* crons is an instance of WP_Error, return the instance instead of a boolean value.
*
* @return bool|WP_Error true if a cron is late, false if it wasn't. WP_Error if the cron is set to that.
*/
public function has_late_cron() {
if ( is_wp_error( $this->crons ) ) {
return $this->crons;
}
foreach ( $this->crons as $id => $cron ) {
$cron_offset = $cron->time - time();
if (
$cron_offset >= $this->timeout_missed_cron &&
$cron_offset < $this->timeout_late_cron
) {
$this->last_late_cron = $cron->hook;
return true;
}
}
return false;
}
}

View File

@ -1,17 +0,0 @@
<?php
// Make sure the file is not directly accessible.
if ( ! defined( 'ABSPATH' ) ) {
die( 'We\'re sorry, but you can not directly access this file.' );
}
?>
<div class="health-check-modal" data-modal-action="" data-parent-field="">
<div class="modal-content">
<span class="modal-close">&times;</span>
<div id="dynamic-content">
&nbsp;
</div>
</div>
</div>

View File

@ -2,7 +2,7 @@
/*
Plugin Name: Health Check Troubleshooting Mode
Description: Conditionally disabled themes or plugins on your site for a given session, used to rule out conflicts during troubleshooting.
Version: 1.7.2
Version: 1.8.1
*/
if ( ! defined( 'ABSPATH' ) ) {
@ -10,7 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) {
}
// Set the MU plugin version.
define( 'HEALTH_CHECK_TROUBLESHOOTING_MODE_PLUGIN_VERSION', '1.7.2' );
define( 'HEALTH_CHECK_TROUBLESHOOTING_MODE_PLUGIN_VERSION', '1.8.1' );
class Health_Check_Troubleshooting_MU {
private $disable_hash = null;
@ -29,9 +29,14 @@ class Health_Check_Troubleshooting_MU {
'health-check-change-active-theme',
'health-check-troubleshoot-enable-plugin',
'health-check-troubleshoot-disable-plugin',
'health-check-plugin-force-enable',
'health-check-plugin-force-disable',
'health-check-theme-force-switch',
);
private $default_themes = array(
'twentytwentytwo',
'twentytwentyone',
'twentytwenty',
'twentynineteen',
'twentyseventeen',
@ -57,41 +62,51 @@ class Health_Check_Troubleshooting_MU {
* @return void
*/
public function init() {
add_action( 'admin_bar_menu', array( $this, 'health_check_troubleshoot_menu_bar' ), 999 );
add_filter( 'option_active_plugins', array( $this, 'health_check_loopback_test_disable_plugins' ) );
add_filter( 'option_active_sitewide_plugins', array( $this, 'health_check_loopback_test_disable_plugins' ) );
add_filter( 'pre_option_template', array( $this, 'health_check_troubleshoot_theme_template' ) );
add_filter( 'pre_option_stylesheet', array( $this, 'health_check_troubleshoot_theme_stylesheet' ) );
add_filter( 'wp_fatal_error_handler_enabled', array( $this, 'wp_fatal_error_handler_enabled' ) );
add_filter( 'bulk_actions-plugins', array( $this, 'remove_plugin_bulk_actions' ) );
add_filter( 'handle_bulk_actions-plugins', array( $this, 'handle_plugin_bulk_actions' ), 10, 3 );
add_action( 'admin_notices', array( $this, 'prompt_install_default_theme' ) );
add_filter( 'user_has_cap', array( $this, 'remove_plugin_theme_install' ) );
add_action( 'plugin_action_links', array( $this, 'plugin_actions' ), 50, 4 );
add_action( 'admin_notices', array( $this, 'display_dashboard_widget' ) );
add_action( 'admin_footer', array( $this, 'dashboard_widget_scripts' ) );
add_action( 'wp_logout', array( $this, 'health_check_troubleshooter_mode_logout' ) );
add_action( 'init', array( $this, 'health_check_troubleshoot_get_captures' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
/*
* Plugin activations can be forced by other tools in things like themes, so let's
* attempt to work around that by forcing plugin lists back and forth.
*
* This is not an ideal scenario, but one we must accept as reality.
*/
add_action( 'activated_plugin', array( $this, 'plugin_activated' ) );
$this->load_options();
// If troubleshooting mode is enabled, add special filters and actions.
if ( $this->is_troubleshooting() ) {
// Attempt to avoid cache entries from a troubleshooting session.
wp_suspend_cache_addition( true );
// Add nocache headers for browser caches.
add_action( 'init', 'nocache_headers' );
add_action( 'admin_init', 'nocache_headers' );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
add_action( 'admin_bar_menu', array( $this, 'health_check_troubleshoot_menu_bar' ), 999 );
add_filter( 'wp_fatal_error_handler_enabled', '__return_false' );
add_action( 'admin_notices', array( $this, 'prompt_install_default_theme' ) );
add_filter( 'user_has_cap', array( $this, 'remove_plugin_theme_install' ) );
add_action( 'plugin_action_links', array( $this, 'plugin_actions' ), 50, 4 );
add_action( 'admin_notices', array( $this, 'display_dashboard_widget' ) );
add_action( 'admin_footer', array( $this, 'dashboard_widget_scripts' ) );
add_action( 'wp_logout', array( $this, 'health_check_troubleshooter_mode_logout' ) );
add_action( 'init', array( $this, 'health_check_troubleshoot_get_captures' ) );
/*
* Plugin activations can be forced by other tools in things like themes, so let's
* attempt to work around that by forcing plugin lists back and forth.
*
* This is not an ideal scenario, but one we must accept as reality.
*/
add_action( 'activated_plugin', array( $this, 'plugin_activated' ) );
}
}
/**
@ -113,35 +128,17 @@ class Health_Check_Troubleshooting_MU {
* @return void
*/
public function enqueue_assets() {
if ( ! $this->is_troubleshooting() || ! is_admin() ) {
if ( ! is_admin() ) {
return;
}
wp_enqueue_style( 'health-check', plugins_url( '/health-check/assets/css/health-check.css' ), array(), HEALTH_CHECK_TROUBLESHOOTING_MODE_PLUGIN_VERSION );
wp_enqueue_style( 'health-check', plugins_url( '/health-check/build/health-check.css' ), array(), HEALTH_CHECK_TROUBLESHOOTING_MODE_PLUGIN_VERSION );
if ( ! wp_script_is( 'site-health', 'registered' ) ) {
wp_enqueue_script( 'site-health', plugins_url( '/health-check/assets/javascript/health-check.js' ), array( 'jquery', 'wp-a11y', 'wp-util' ), HEALTH_CHECK_TROUBLESHOOTING_MODE_PLUGIN_VERSION, true );
wp_enqueue_script( 'site-health', plugins_url( '/health-check/build/health-check.js' ), array( 'jquery', 'wp-a11y', 'wp-util' ), HEALTH_CHECK_TROUBLESHOOTING_MODE_PLUGIN_VERSION, true );
}
wp_enqueue_script( 'health-check', plugins_url( '/health-check/assets/javascript/troubleshooting-mode.js' ), array( 'site-health' ), HEALTH_CHECK_TROUBLESHOOTING_MODE_PLUGIN_VERSION, true );
}
/**
* Allow troubleshooting Mode to override the WSOD protection introduced in WordPress 5.2.0
*
* This will prevent incorrect reporting of errors while testing sites, without touching the
* settings put in by site admins in regular scenarios.
*
* @param bool $enabled
*
* @return bool
*/
public function wp_fatal_error_handler_enabled( $enabled ) {
if ( ! $this->is_troubleshooting() ) {
return $enabled;
}
return false;
wp_enqueue_script( 'health-check', plugins_url( '/health-check/build/troubleshooting-mode.js' ), array( 'site-health' ), HEALTH_CHECK_TROUBLESHOOTING_MODE_PLUGIN_VERSION, true );
}
/**
@ -154,7 +151,7 @@ class Health_Check_Troubleshooting_MU {
* @return void
*/
public function prompt_install_default_theme() {
if ( ! $this->is_troubleshooting() || $this->has_default_theme() ) {
if ( $this->has_default_theme() ) {
return;
}
@ -185,10 +182,6 @@ class Health_Check_Troubleshooting_MU {
* @return array
*/
public function remove_plugin_theme_install( $caps ) {
if ( ! $this->is_troubleshooting() ) {
return $caps;
}
$caps['switch_themes'] = false;
/*
@ -214,10 +207,6 @@ class Health_Check_Troubleshooting_MU {
* @return void
*/
public function plugin_activated() {
if ( ! $this->is_troubleshooting() ) {
return;
}
// Force the database entry for active plugins if someone tried changing plugins while in Troubleshooting Mode.
update_option( 'active_plugins', $this->active_plugins );
}
@ -335,10 +324,6 @@ class Health_Check_Troubleshooting_MU {
* @return array
*/
public function plugin_actions( $actions, $plugin_file, $plugin_data, $context ) {
if ( ! $this->is_troubleshooting() ) {
return $actions;
}
if ( 'mustuse' === $context ) {
return $actions;
}
@ -601,10 +586,6 @@ class Health_Check_Troubleshooting_MU {
* @return void
*/
function health_check_troubleshooter_mode_logout() {
if ( ! $this->is_troubleshooting() ) {
return;
}
if ( isset( $_COOKIE['wp-health-check-disable-plugins'] ) ) {
$this->disable_troubleshooting_mode();
}
@ -629,10 +610,6 @@ class Health_Check_Troubleshooting_MU {
* @return void
*/
function health_check_troubleshoot_get_captures() {
if ( ! $this->is_troubleshooting() ) {
return;
}
// Disable Troubleshooting Mode.
if ( isset( $_GET['health-check-disable-troubleshooting'] ) ) {
$this->disable_troubleshooting_mode();
@ -657,16 +634,48 @@ class Health_Check_Troubleshooting_MU {
update_option( 'health-check-allowed-plugins', $this->allowed_plugins );
if ( ! $this->test_site_state() ) {
if ( isset( $_GET['health-check-plugin-force-enable'] ) ) {
$this->add_dashboard_notice(
sprintf(
// translators: %s: The plugin slug.
'The %s plugin was forcefully enabled.',
$_GET['health-check-troubleshoot-enable-plugin']
),
'info'
);
}
if ( ! $this->test_site_state() && ! isset( $_GET['health-check-plugin-force-enable'] ) ) {
$this->allowed_plugins = $old_allowed_plugins;
update_option( 'health-check-allowed-plugins', $old_allowed_plugins );
$this->add_dashboard_notice(
$notice = sprintf(
// Translators: %1$s: The link-button markup to force enable the plugin. %2$s: The force-enable link markup.
__( 'When enabling the plugin, %1$s, a site failure occurred. Because of this the change was automatically reverted. %2$s', 'health-check' ),
$_GET['health-check-troubleshoot-enable-plugin'],
sprintf(
// translators: %s: The plugin slug that was enabled.
__( 'When enabling the plugin, %s, a site failure occurred. Because of this the change was automatically reverted.', 'health-check' ),
$_GET['health-check-troubleshoot-enable-plugin']
),
'<a href="%s" aria-label="%s">%s</a>',
esc_url(
add_query_arg(
array(
'health-check-troubleshoot-enable-plugin' => $_GET['health-check-troubleshoot-enable-plugin'],
'health-check-plugin-force-enable' => 'true',
)
)
),
esc_attr(
sprintf(
// translators: %s: Plugin name.
__( 'Force-enable the plugin, %s, even though the loopback checks failed.', 'health-check' ),
$_GET['health-check-troubleshoot-enable-plugin']
)
),
__( 'Enable anyway', 'health-check' )
)
);
$this->add_dashboard_notice(
$notice,
'warning'
);
}
@ -683,16 +692,48 @@ class Health_Check_Troubleshooting_MU {
update_option( 'health-check-allowed-plugins', $this->allowed_plugins );
if ( ! $this->test_site_state() ) {
if ( isset( $_GET['health-check-plugin-force-disable'] ) ) {
$this->add_dashboard_notice(
sprintf(
// translators: %s: The plugin slug.
'The %s plugin was forcefully disabled.',
$_GET['health-check-troubleshoot-disable-plugin']
),
'info'
);
}
if ( ! $this->test_site_state() && ! isset( $_GET['health-check-plugin-force-disable'] ) ) {
$this->allowed_plugins = $old_allowed_plugins;
update_option( 'health-check-allowed-plugins', $old_allowed_plugins );
$this->add_dashboard_notice(
$notice = sprintf(
// Translators: %1$s: The plugin slug that was disabled. %2$s: The force-disable link markup.
__( 'When disabling the plugin, %1$s, a site failure occurred. Because of this the change was automatically reverted. %2$s', 'health-check' ),
$_GET['health-check-troubleshoot-disable-plugin'],
sprintf(
// translators: %s: The plugin slug that was disabled.
__( 'When disabling the plugin, %s, a site failure occurred. Because of this the change was automatically reverted.', 'health-check' ),
$_GET['health-check-troubleshoot-disable-plugin']
),
'<a href="%1$s" aria-label="%2$s">%3$s</a>',
esc_url(
add_query_arg(
array(
'health-check-troubleshoot-disable-plugin' => $_GET['health-check-troubleshoot-disable-plugin'],
'health-check-plugin-force-disable' => 'true',
)
)
),
esc_attr(
sprintf(
// translators: %s: Plugin name.
__( 'Force-disable the plugin, %s, even though the loopback checks failed.', 'health-check' ),
$_GET['health-check-troubleshoot-disable-plugin']
)
),
__( 'Disable anyway', 'health-check' )
)
);
$this->add_dashboard_notice(
$notice,
'warning'
);
}
@ -707,15 +748,47 @@ class Health_Check_Troubleshooting_MU {
update_option( 'health-check-current-theme', $_GET['health-check-change-active-theme'] );
if ( ! $this->test_site_state() ) {
update_option( 'health-check-current-theme', $old_theme );
if ( isset( $_GET['health-check-theme-force-switch'] ) ) {
$this->add_dashboard_notice(
sprintf(
// translators: %s: The theme slug that was switched to.
__( 'When switching the active theme to %s, a site failure occurred. Because of this we reverted the theme to the one you used previously.', 'health-check' ),
// translators: %s: The theme slug.
'The theme was forcefully switched to %s.',
$_GET['health-check-change-active-theme']
),
'info'
);
}
if ( ! $this->test_site_state() && ! isset( $_GET['health-check-theme-force-switch'] ) ) {
update_option( 'health-check-current-theme', $old_theme );
$notice = sprintf(
// Translators: %1$s: The theme slug that was switched to.. %2$s: The force-enable link markup.
__( 'When switching the active theme to %1$s, a site failure occurred. Because of this we reverted the theme to the one you used previously. %2$s', 'health-check' ),
$_GET['health-check-change-active-theme'],
sprintf(
'<a href="%s" aria-label="%s">%s</a>',
esc_url(
add_query_arg(
array(
'health-check-change-active-theme' => $_GET['health-check-change-active-theme'],
'health-check-theme-force-switch' => 'true',
)
)
),
esc_attr(
sprintf(
// translators: %s: Plugin name.
__( 'Force-switch to the %s theme, even though the loopback checks failed.', 'health-check' ),
$_GET['health-check-change-active-theme']
)
),
__( 'Switch anyway', 'health-check' )
)
);
$this->add_dashboard_notice(
$notice,
'warning'
);
}
@ -749,10 +822,6 @@ class Health_Check_Troubleshooting_MU {
* @return void
*/
function health_check_troubleshoot_menu_bar( $wp_menu ) {
if ( ! $this->is_troubleshooting() ) {
return;
}
// We need some admin functions to make this a better user experience, so include that file.
if ( ! is_admin() ) {
require_once( trailingslashit( ABSPATH ) . 'wp-admin/includes/plugin.php' );
@ -760,8 +829,8 @@ class Health_Check_Troubleshooting_MU {
// Make sure the updater tools are available since WordPress 5.5.0 auto-updates were introduced.
if ( ! function_exists( 'wp_is_auto_update_enabled_for_type' ) ) {
require_once( trailingslashit( ABSPATH ) . 'wp-admin/includes/update.php' );
}
require_once( trailingslashit( ABSPATH ) . 'wp-admin/includes/update.php' );
}
// Ensure the theme functions are available to us on every page.
include_once( trailingslashit( ABSPATH ) . 'wp-admin/includes/theme.php' );
@ -916,7 +985,7 @@ class Health_Check_Troubleshooting_MU {
// Make sure the Health_Check_Loopback class is available to us, in case the primary plugin is disabled.
if ( ! method_exists( 'Health_Check_Loopback', 'can_perform_loopback' ) ) {
$plugin_file = trailingslashit( WP_PLUGIN_DIR ) . 'health-check/includes/class-health-check-loopback.php';
$plugin_file = trailingslashit( WP_PLUGIN_DIR ) . 'health-check/HealthCheck/class-health-check-loopback.php';
// Make sure the file exists, in case someone deleted the plugin manually, we don't want any errors.
if ( ! file_exists( $plugin_file ) ) {
@ -938,10 +1007,6 @@ class Health_Check_Troubleshooting_MU {
}
public function dashboard_widget_scripts() {
if ( ! $this->is_troubleshooting() ) {
return;
}
// Check that it's the dashboard page, we don't want to disturb any other pages.
$screen = get_current_screen();
if ( 'dashboard' !== $screen->id && 'plugins' !== $screen->id ) {
@ -950,10 +1015,6 @@ class Health_Check_Troubleshooting_MU {
}
public function display_dashboard_widget() {
if ( ! $this->is_troubleshooting() ) {
return;
}
// Check that it's the dashboard page, we don't want to disturb any other pages.
$screen = get_current_screen();
if ( 'dashboard' !== $screen->id && 'plugins' !== $screen->id ) {
@ -1005,6 +1066,10 @@ class Health_Check_Troubleshooting_MU {
<p>
<?php _e( 'Here you can enable individual plugins or themes, helping you to find out what might be causing strange behaviors on your site. Do note that <strong>any changes you make to settings will be kept</strong> when you disable Troubleshooting Mode.', 'health-check' ); ?>
</p>
<p>
<?php _e( 'The Health Check plugin will attempt to disable cache solutions on your site, but if you are using a custom caching solution, you may need to disable it manually when troubleshooting.', 'health-check' ); ?>
</p>
</div>
</div>
@ -1089,7 +1154,12 @@ class Health_Check_Troubleshooting_MU {
'<li><button type="button" class="show-remaining button button-link">%s</button></li>',
sprintf(
// translators: %d: Amount of hidden plugins.
__( 'Show %d remaining plugins', 'health-check' ),
_n(
'Show %d remaining plugin',
'Show %d remaining plugins',
( is_countable( $this->active_plugins ) ? ( count( $this->active_plugins ) - 5 ) : 0 ),
'health-check'
),
( is_countable( $this->active_plugins ) ? ( count( $this->active_plugins ) - 5 ) : 0 )
)
);
@ -1168,7 +1238,12 @@ class Health_Check_Troubleshooting_MU {
'<li><button type="button" class="show-remaining button button-link">%s</button></li>',
sprintf(
// translators: %d: Amount of hidden themes.
__( 'Show %d remaining themes', 'health-check' ),
_n(
'Show %d remaining theme',
'Show %d remaining themes',
( is_countable( $themes ) ? ( count( $themes ) - 5 ) : 0 ),
'health-check'
),
( is_countable( $themes ) ? ( count( $themes ) - 5 ) : 0 )
)
);
@ -1220,7 +1295,16 @@ class Health_Check_Troubleshooting_MU {
printf(
'<div class="notice notice-%s inline"><p>%s</p></div>',
esc_attr( $notice['severity'] ),
esc_html( $notice['message'] )
wp_kses(
$notice['message'],
array(
'a' => array(
'class' => true,
'href' => true,
'aria-label' => true,
),
)
)
);
}
?>

View File

@ -0,0 +1,59 @@
{
"author": "The WordPress Community",
"bugs": {
"url": "https://github.com/WordPress/health-check/issues"
},
"description": "WordPress site health tester, and troubleshooting tools for end users and anyone providing support",
"devDependencies": {
"@wordpress/scripts": "~23.7.0",
"@wordpress/env": "~5.2.0",
"@wordpress/stylelint-config": "~20.0.2",
"postcss-scss": "~4.0.4"
},
"dependencies": {
"clipboard": "~2.0.11"
},
"engines": {
"node": ">=16"
},
"keywords": [
"support",
"wordpress"
],
"homepage": "https://github.com/WordPress/health-check",
"license": "GPL-2.0+",
"name": "health-check",
"repository": {
"type": "git",
"url": "https://github.com/WordPress/health-check"
},
"version": "0.1.0",
"scripts": {
"build": "wp-scripts build",
"lint:css": "wp-scripts lint-style './src/styles/**/*.scss'",
"lint:js": "wp-scripts lint-js ./src/javascript/**/*.js",
"watch": "wp-scripts start",
"wp-env": "wp-env",
"plugin-zip": "wp-scripts plugin-zip"
},
"stylelint": {
"extends": "@wordpress/stylelint-config",
"customSyntax": "postcss-scss",
"rules": {
"no-descending-specificity": null,
"no-invalid-position-at-import-rule": null
}
},
"files": [
"mu-plugin/**",
"HealthCheck/**",
"modals/**",
"pages/**",
"build/**",
"compat.php",
"health-check.php",
"uninstall.php",
"changelog.txt",
"readme.txt"
]
}

View File

@ -10,117 +10,120 @@ if ( ! defined( 'ABSPATH' ) ) {
die( 'We\'re sorry, but you can not directly access this file.' );
}
Health_Check_Debug_Data::check_for_updates();
WP_Debug_Data::check_for_updates();
$info = Health_Check_Debug_Data::debug_data();
$info = WP_Debug_Data::debug_data();
?>
<h2>
<?php esc_html_e( 'Site Health Info', 'health-check' ); ?>
</h2>
<p>
<?php
printf(
/* translators: %s: URL to Site Health Status page */
__( 'This page can show you every detail about the configuration of your WordPress website. For any improvements that could be made, see the <a href="%s">Site Health Status</a> page.', 'health-check' ),
esc_url( admin_url( 'site-health.php' ) )
);
?>
</p>
<p>
<?php _e( 'If you want to export a handy list of all the information on this page, you can use the button below to copy it to the clipboard. You can then paste it in a text file and save it to your device, or paste it in an email exchange with a support engineer or theme/plugin developer for example.', 'health-check' ); ?>
</p>
<div class="site-health-copy-buttons">
<div class="copy-button-wrapper">
<button type="button" class="button copy-button" data-clipboard-text="<?php echo esc_attr( Health_Check_Debug_Data::format( $info, 'debug' ) ); ?>">
<?php _e( 'Copy site info to clipboard', 'health-check' ); ?>
</button>
<span class="success" aria-hidden="true"><?php _e( 'Copied!', 'health-check' ); ?></span>
</div>
<div class="notice notice-error hide-if-js">
<p><?php _e( 'The Site Health check requires JavaScript.' ); ?></p>
</div>
<div id="health-check-debug" class="health-check-accordion">
<div class="health-check-body health-check-debug-tab hide-if-no-js">
<?php
<?php
$sizes_fields = array( 'uploads_size', 'themes_size', 'plugins_size', 'wordpress_size', 'database_size', 'total_size' );
WP_Debug_Data::check_for_updates();
$info = WP_Debug_Data::debug_data();
foreach ( $info as $section => $details ) {
if ( ! isset( $details['fields'] ) || empty( $details['fields'] ) ) {
continue;
}
?>
<h3 class="health-check-accordion-heading">
<button aria-expanded="false" class="health-check-accordion-trigger" aria-controls="health-check-accordion-block-<?php echo esc_attr( $section ); ?>" type="button">
<span class="title">
<?php echo esc_html( $details['label'] ); ?>
<?php
if ( isset( $details['show_count'] ) && $details['show_count'] ) {
printf( '(%d)', count( $details['fields'] ) );
}
<h2>
<?php _e( 'Site Health Info' ); ?>
</h2>
?>
</span>
<?php
<p>
<?php
/* translators: %s: URL to Site Health Status page. */
printf( __( 'This page can show you every detail about the configuration of your WordPress website. For any improvements that could be made, see the <a href="%s">Site Health Status</a> page.' ), esc_url( admin_url( 'site-health.php' ) ) );
?>
</p>
<p>
<?php _e( 'If you want to export a handy list of all the information on this page, you can use the button below to copy it to the clipboard. You can then paste it in a text file and save it to your device, or paste it in an email exchange with a support engineer or theme/plugin developer for example.' ); ?>
</p>
if ( 'wp-paths-sizes' === $section ) {
?>
<span class="health-check-wp-paths-sizes spinner"></span>
<?php
}
<div class="site-health-copy-buttons">
<div class="copy-button-wrapper">
<button type="button" class="button copy-button" data-clipboard-text="<?php echo esc_attr( WP_Debug_Data::format( $info, 'debug' ) ); ?>">
<?php _e( 'Copy site info to clipboard' ); ?>
</button>
<span class="success hidden" aria-hidden="true"><?php _e( 'Copied!' ); ?></span>
</div>
</div>
?>
<span class="icon"></span>
</button>
</h3>
<div id="health-check-debug" class="health-check-accordion">
<div id="health-check-accordion-block-<?php echo esc_attr( $section ); ?>" class="health-check-accordion-panel" hidden="hidden">
<?php
if ( isset( $details['description'] ) && ! empty( $details['description'] ) ) {
printf( '<p>%s</p>', $details['description'] );
}
$sizes_fields = array( 'uploads_size', 'themes_size', 'plugins_size', 'wordpress_size', 'database_size', 'total_size' );
?>
<table class="widefat striped health-check-table" role="presentation">
<tbody>
<?php
foreach ( $details['fields'] as $field_name => $field ) {
if ( is_array( $field['value'] ) ) {
$values = '<ul>';
foreach ( $field['value'] as $name => $value ) {
$values .= sprintf( '<li>%s: %s</li>', esc_html( $name ), esc_html( $value ) );
}
$values .= '</ul>';
} else {
$values = esc_html( $field['value'] );
}
if ( in_array( $field_name, $sizes_fields, true ) ) {
printf( '<tr><td>%s</td><td class="%s">%s</td></tr>', esc_html( $field['label'] ), esc_attr( $field_name ), $values );
} else {
printf( '<tr><td>%s</td><td>%s</td></tr>', esc_html( $field['label'] ), $values );
}
foreach ( $info as $section => $details ) {
if ( ! isset( $details['fields'] ) || empty( $details['fields'] ) ) {
continue;
}
?>
</tbody>
</table>
</div>
<?php } ?>
</div>
<h3 class="health-check-accordion-heading">
<button aria-expanded="false" class="health-check-accordion-trigger" aria-controls="health-check-accordion-block-<?php echo esc_attr( $section ); ?>" type="button">
<span class="title">
<?php echo esc_html( $details['label'] ); ?>
<?php
<div class="site-health-view-more">
<?php
printf(
'<a href="%s" class="button button-primary">%s</a>',
esc_url( admin_url( 'tools.php?page=health-check&tab=phpinfo' ) ),
esc_html__( 'View extended PHP information', 'health-check' )
);
?>
if ( isset( $details['show_count'] ) && $details['show_count'] ) {
printf( '(%d)', count( $details['fields'] ) );
}
?>
</span>
<?php
if ( 'wp-paths-sizes' === $section ) {
?>
<span class="health-check-wp-paths-sizes spinner"></span>
<?php
}
?>
<span class="icon"></span>
</button>
</h3>
<div id="health-check-accordion-block-<?php echo esc_attr( $section ); ?>" class="health-check-accordion-panel" hidden="hidden">
<?php
if ( isset( $details['description'] ) && ! empty( $details['description'] ) ) {
printf( '<p>%s</p>', $details['description'] );
}
?>
<table class="widefat striped health-check-table" role="presentation">
<tbody>
<?php
foreach ( $details['fields'] as $field_name => $field ) {
if ( is_array( $field['value'] ) ) {
$values = '<ul>';
foreach ( $field['value'] as $name => $value ) {
$values .= sprintf( '<li>%s: %s</li>', esc_html( $name ), esc_html( $value ) );
}
$values .= '</ul>';
} else {
$values = esc_html( $field['value'] );
}
if ( in_array( $field_name, $sizes_fields, true ) ) {
printf( '<tr><td>%s</td><td class="%s">%s</td></tr>', esc_html( $field['label'] ), esc_attr( $field_name ), $values );
} else {
printf( '<tr><td>%s</td><td>%s</td></tr>', esc_html( $field['label'] ), $values );
}
}
?>
</tbody>
</table>
</div>
<?php } ?>
</div>
</div>

View File

@ -11,6 +11,8 @@ if ( ! defined( 'ABSPATH' ) ) {
}
?>
<div class="health-check-body">
<h2>
<?php esc_html_e( 'Extended PHP Information', 'health-check' ); ?>
</h2>
@ -25,15 +27,8 @@ if ( ! function_exists( 'phpinfo' ) ) {
</p>
</div>
<?php } else { ?>
<div class="notice notice-warning inline">
<p>
<?php esc_html_e( 'Some scenarios require you to look up more detailed server configurations than what is normally required. This page allows you to view all available configuration options for your PHP setup. Please be advised that WordPress does not guarantee that any information shown on this page may not be considered private.', 'health-check' ); ?>
</p>
</div>
<?php
} else {
ob_start();
phpinfo();
$phpinfo_raw = ob_get_clean();
@ -65,3 +60,5 @@ if ( ! function_exists( 'phpinfo' ) ) {
<?php
}
?>
</div>

View File

@ -18,31 +18,27 @@ if ( ! defined( 'ABSPATH' ) ) {
</h1>
</div>
<div class="health-check-title-section site-health-progress-wrapper loading hide-if-no-js">
<div class="site-health-progress">
<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">
<circle r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
<circle id="bar" r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
</svg>
</div>
<div class="site-health-progress-label">
<?php _e( 'Results are still loading&hellip;', 'health-check' ); ?>
</div>
</div>
<nav class="health-check-tabs-wrapper hide-if-no-js" aria-label="<?php esc_attr_e( 'Secondary menu', 'health-check' ); ?>">
<?php
$tabs = Health_Check::tabs();
$current_tab = Health_Check::current_tab();
foreach ( $tabs as $tab => $label ) {
if ( ! empty( $tab ) ) {
$url = add_query_arg(
array(
'page' => 'site-health',
'tab' => $tab,
),
admin_url( 'tools.php?page=site-health' )
);
} else {
$url = admin_url( 'tools.php?page=site-health' );
}
printf(
'<a href="%s" class="health-check-tab health-check-%s-tab %s"%s>%s</a>',
sprintf(
'%s&tab=%s',
menu_page_url( 'health-check', false ),
$tab
),
esc_url( $url ),
esc_attr( $tab ),
( $current_tab === $tab ? 'active' : '' ),
( $current_tab === $tab ? ' aria-current="true"' : '' ),

View File

@ -9,87 +9,36 @@
if ( ! defined( 'ABSPATH' ) ) {
die( 'We\'re sorry, but you can not directly access this file.' );
}
global $health_check_site_status;
?>
<div class="site-status-all-clear hide">
<p class="icon">
<span class="dashicons dashicons-yes"></span>
<div class="site-status-all-clear">
<p class="icon wp-logo">
<span class="dashicons dashicons-wordpress"></span>
</p>
<p class="encouragement">
<?php _e( 'Great job!', 'health-check' ); ?>
</p>
<p>
<?php _e( 'Everything is running smoothly here.', 'health-check' ); ?>
</p>
</div>
<div class="site-status-has-issues">
<h2>
<?php _e( 'Site Health Status', 'health-check' ); ?>
<h2 class="encouragement">
<?php _e( 'WordPress update needed!', 'health-check' ); ?>
</h2>
<p><?php _e( 'The site health check shows critical information about your WordPress configuration and items that require your attention.', 'health-check' ); ?></p>
<div class="site-health-issues-wrapper" id="health-check-issues-critical">
<h3 class="site-health-issue-count-title">
<?php
/* translators: %s: number of critical issues found */
printf( _n( '%s Critical issue', '%s Critical issues', 0, 'health-check' ), '<span class="issue-count">0</span>' );
?>
</h3>
<div id="health-check-site-status-critical" class="health-check-accordion issues"></div>
</div>
<div class="site-health-issues-wrapper" id="health-check-issues-recommended">
<h3 class="site-health-issue-count-title">
<?php
/* translators: %s: number of recommended improvements */
printf( _n( '%s Recommended improvement', '%s Recommended improvements', 0, 'health-check' ), '<span class="issue-count">0</span>' );
?>
</h3>
<div id="health-check-site-status-recommended" class="health-check-accordion issues"></div>
</div>
</div>
<div class="site-health-view-more">
<button type="button" class="button site-health-view-passed" aria-expanded="false" aria-controls="health-check-issues-good">
<?php _e( 'Passed tests', 'health-check' ); ?>
<span class="icon"></span>
</button>
</div>
<div class="site-health-issues-wrapper hidden" id="health-check-issues-good">
<h3 class="site-health-issue-count-title">
<p>
<?php
/* translators: %s: number of items with no issues */
printf( _n( '%s Item with no issues detected', '%s Items with no issues detected', 0, 'health-check' ), '<span class="issue-count">0</span>' );
printf(
// translators: %s: The current WordPress version used on this site.
__( 'You are running an older version of WordPress, version %s. The Site Health features from this plugin were added to version 5.2 of WordPress.', 'health-check' ),
get_bloginfo( 'version' )
);
?>
</h3>
</p>
<div id="health-check-site-status-good" class="health-check-accordion issues"></div>
<br>
<p>
<?php _e( 'Due to this, some functionality has been removed from the plugin, you can find these features in a more recent version of WordPress it self.', 'health-check' ); ?>
</p>
<br>
<p>
<?php _e( 'The plugin itself still offers you the ability to troubleshoot issues with your installation, and various tools associated with this functionality.', 'health-check' ); ?>
</p>
</div>
<script id="tmpl-health-check-issue" type="text/template">
<h4 class="health-check-accordion-heading">
<button aria-expanded="false" class="health-check-accordion-trigger" aria-controls="health-check-accordion-block-{{ data.test }}" type="button">
<span class="title">{{ data.label }}</span>
<span class="badge {{ data.badge.color }}">{{ data.badge.label }}</span>
<span class="icon"></span>
</button>
</h4>
<div id="health-check-accordion-block-{{ data.test }}" class="health-check-accordion-panel" hidden="hidden">
{{{ data.description }}}
<div class="actions">
<p class="button-container">{{{ data.actions }}}</p>
</div>
</div>
</script>
<?php
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/modals/js-result-warnings.php' );

View File

@ -12,51 +12,52 @@ if ( ! defined( 'ABSPATH' ) ) {
?>
<h2>
<?php esc_html_e( 'Tools', 'health-check' ); ?>
</h2>
<div class="health-check-body">
<h2>
<?php esc_html_e( 'Tools', 'health-check' ); ?>
</h2>
<div id="health-check-tools" role="presentation" class="health-check-accordion">
<?php
/**
* Filter the features available under the Tools tab.
*
* You may introduce your own, or modify the behavior of existing tools here,
* although we recommend not modifying anything provided by the plugin it self.
*
* Any interactive elements should be introduced using JavaScript and/or CSS, either
* inline, or by enqueueing them via the appropriate actions.
*
* @param array $args {
* An unassociated array of tabs, listed in the order they are registered.
*
* @type array $tab {
* An associated array containing the tab title, and content.
*
* @type string $label A pre-escaped string used to label your tool section.
* @type string $content The content of your tool tab, with any code you may need.
* }
* }
*/
$tabs = apply_filters( 'health_check_tools_tab', array() );
<div id="health-check-tools" role="presentation" class="health-check-accordion">
<?php
/**
* Filter the features available under the Tools tab.
*
* You may introduce your own, or modify the behavior of existing tools here,
* although we recommend not modifying anything provided by the plugin it self.
*
* Any interactive elements should be introduced using JavaScript and/or CSS, either
* inline, or by enqueueing them via the appropriate actions.
*
* @param array $args {
* An unassociated array of tabs, listed in the order they are registered.
*
* @type array $tab {
* An associated array containing the tab title, and content.
*
* @type string $label A pre-escaped string used to label your tool section.
* @type string $content The content of your tool tab, with any code you may need.
* }
* }
*/
$tabs = apply_filters( 'health_check_tools_tab', array() );
foreach ( $tabs as $count => $tab ) :
?>
foreach ( $tabs as $count => $tab ) :
?>
<h3 class="health-check-accordion-heading">
<button aria-expanded="false" class="health-check-accordion-trigger" aria-controls="health-check-accordion-block-<?php echo esc_attr( $count ); ?>" type="button">
<span class="title">
<?php echo $tab['label']; ?>
</span>
<span class="icon"></span>
</button>
</h3>
<div id="health-check-accordion-block-<?php echo esc_attr( $count ); ?>" class="health-check-accordion-panel" hidden="hidden">
<?php echo $tab['content']; ?>
<h3 class="health-check-accordion-heading">
<button aria-expanded="false" class="health-check-accordion-trigger" aria-controls="health-check-accordion-block-<?php echo esc_attr( $count ); ?>" type="button">
<span class="title">
<?php echo $tab['label']; ?>
</span>
<span class="icon"></span>
</button>
</h3>
<div id="health-check-accordion-block-<?php echo esc_attr( $count ); ?>" class="health-check-accordion-panel" hidden="hidden">
<?php echo $tab['content']; ?>
</div>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
<?php include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/modals/diff.php' ); ?>
</div>
<?php
include_once( HEALTH_CHECK_PLUGIN_DIRECTORY . '/modals/diff.php' );

View File

@ -12,26 +12,27 @@ if ( ! defined( 'ABSPATH' ) ) {
?>
<h2>
<?php esc_html_e( 'Troubleshooting mode', 'health-check' ); ?>
</h2>
<div class="health-check-body">
<h2>
<?php esc_html_e( 'Troubleshooting mode', 'health-check' ); ?>
</h2>
<p>
<?php esc_html_e( 'When troubleshooting issues on your site, you are likely to be told to disable all plugins and switch to the default theme.', 'health-check' ); ?>
<?php esc_html_e( 'Understandably, you do not wish to do so as it may affect your site visitors, leaving them with lost functionality.', 'health-check' ); ?>
</p>
<p>
<?php esc_html_e( 'When troubleshooting issues on your site, you are likely to be told to disable all plugins and switch to the default theme.', 'health-check' ); ?>
<?php esc_html_e( 'Understandably, you do not wish to do so as it may affect your site visitors, leaving them with lost functionality.', 'health-check' ); ?>
</p>
<p>
<?php esc_html_e( 'By enabling the Troubleshooting Mode, all plugins will appear inactive and your site will switch to the default theme only for you. All other users will see your site as usual.', 'health-check' ); ?>
</p>
<p>
<?php esc_html_e( 'By enabling the Troubleshooting Mode, all plugins will appear inactive and your site will switch to the default theme only for you. All other users will see your site as usual.', 'health-check' ); ?>
</p>
<p>
<?php esc_html_e( 'A Troubleshooting Mode menu is added to your admin bar, which will allow you to enable plugins individually, switch back to your current theme, and disable Troubleshooting Mode.', 'health-check' ); ?>
</p>
<p>
<?php esc_html_e( 'A Troubleshooting Mode menu is added to your admin bar, which will allow you to enable plugins individually, switch back to your current theme, and disable Troubleshooting Mode.', 'health-check' ); ?>
</p>
<p>
<?php esc_html_e( 'Please note, that due to how Must Use plugins work, any such plugin will not be disabled for the troubleshooting session.', 'health-check' ); ?>
</p>
<p>
<?php esc_html_e( 'Please note, that due to how Must Use plugins work, any such plugin will not be disabled for the troubleshooting session.', 'health-check' ); ?>
</p>
<?php
Health_Check_Troubleshoot::show_enable_troubleshoot_form();
<?php Health_Check_Troubleshoot::show_enable_troubleshoot_form(); ?>
</div>

View File

@ -1,97 +1,110 @@
=== Health Check & Troubleshooting ===
Tags: health check
Contributors: wordpressdotorg, westi, pento, Clorith
Requires at least: 4.0
Requires PHP: 5.2
Tested up to: 5.5
Stable tag: 1.4.5
License: GPLv2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Health Check identifies common problems, and helps you troubleshoot plugin and theme conflicts.
== Description ==
This plugin will perform a number of checks on your WordPress installation to detect common configuration errors and known issues, and also allows plugins and themes to add their own checks.
The debug section, which allows you to gather information about your WordPress and server configuration that you may easily share with support representatives for themes, plugins or on the official WordPress.org support forums.
Troubleshooting allows you to have a clean WordPress session, where all plugins are disabled, and a default theme is used, but only for your user until you disable it or log out.
The Tools section allows you to check that WordPress files have not been tampered with, that emails can be sent, and if your plugins are compatible with any PHP version updates in the future.
For a more extensive example of how to efficiently use the Health Check plugin, check out the [WordPress.org support team handbook page about this plugin](https://make.wordpress.org/support/handbook/appendix/troubleshooting-using-the-health-check/).
Feedback is welcome both through the [WordPress.org forums](https://wordpress.org/support/plugin/health-check), the [GitHub project page](https://github.com/WordPress/health-check), or on [Slack](https://make.wordpress.org/chat) in either [#forums](https://wordpress.slack.com/messages/forums/) or [#core-site-health](https://wordpress.slack.com/messages/core-site-health/).
== Frequently Asked Questions ==
= I am unable to access my site after enabling troubleshooting =
If you should find your self stuck in Troubleshooting Mode for any reason, you can easily disable it by clearing your cookies.
Are you unfamiliar with how to clear your cookies? No worries, you may also close all your browser windows, or perform a computer restart and it will clear this specific cookie automatically.
= The PHP compatibility says this plugin only work with PHP version X? =
The plugin is made to be a support tool for as many users as possible, this means it needs code that is written for older sites as well.
Tools that check for PHP compatibility do not know how to separate this code from the real code, so it will give a false positive response.
At this time, the plugin has been tested with every version of PHP from 5.2 through 7.3, and works with all of these.
== Screenshots ==
1. The health check screen after the automated tests have gone over the system.
2. The debug information, with the copy and paste field expanded.
3. A selection of tools that can be ran on your site.
4. Troubleshooting mode enabled, showing your website Dashboard
== Changelog ==
= v1.4.5 =
* Fix Troubleshooting Mode throwing errors in frontend on WordPress 5.5
= v1.4.4 =
* Fixed hidden JavaScript warning when using troubleshooting mode on the Dashboard
* Fixed plugin and theme lists staying hidden in troubleshooting mode on the Dashboard
= v1.4.3 =
* Compatibility with WordPress 5.4
= v1.4.2 =
* Fix missing headers for a loopback request in the debug section
= v1.4.1 =
* Fixed SQL version checks for various MariaDB installs.
* Fixed a warning being generated in logfiles for first-time users with no existing Site Health history.
* Added missing translation function for the new PHP compatibility tool.
= v1.4.0 =
* Fix a bug when viewing the Site Health page if enabling the Health Check plugin in troubleshooting mode.
* Fix an inconsistency with how database versions are checked.
* Fix the file comparison view on Windows systems if there are modified core files.
* Fix a bug where some premium plugins could not be enabled in troubleshooting mode
* Improved styles for older browsers.
* Improved the PHP module checks to allow for constant checks as well. Should help with some edge case tests.
* Improved the core file integrity checker.
* Improved testing of WP_cron, now works properly for those running a "real cron" outside of WordPress.
* Improved the htaccess rule test to only run if using an Apache server that supports these.
* Modify the Site Health grading indicator.
* Modified strings to make them clearer.
* Added server headers to the Debug information.
* Added polyfills for core features from WordPress 5.2 so they work for older sites.
* Added a link to the Site Health page from the plugin overview.
* Added a custom capability, `view_site_health_checks` for the plugin.
* Added support for parent/child theme output in the Debug screen.
* Added system user information to the Debug information.
* Added a Site Health test for timezone localization.
* Added `mbstring` and `json` (again) as requirements to the list of PHP extensions.
* Added a missing toggle to the list of plugins/themes to the troubleshooting dashboard widget.
* Added bulk actions to enable or disable plugins when troubleshooting, or to initiate troubleshooting mode.
* Added plugin compatibility checker ot the tools section.
* Added a dashboard widget to show your Site Health status at a glance when logging in.
* Added filters for Site Health test results.
* Added WP-CLI support, you can now run `wp health-check status` for a list of test and their status.
* Moved compatibility functions out of primary files and into a `compat.php` so they can be conditionally loaded.
* Disable the Fatal Error (WSOD) protection in WordPress while in troubleshooting mode.
=== Health Check & Troubleshooting ===
Tags: health check
Contributors: wordpressdotorg, westi, pento, Clorith
Requires at least: 4.4
Requires PHP: 5.6
Tested up to: 6.1
Stable tag: 1.5.1
License: GPLv2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Health Check identifies common problems, and helps you troubleshoot plugin and theme conflicts.
== Description ==
This plugin will perform a number of checks on your WordPress installation to detect common configuration errors and known issues, and also allows plugins and themes to add their own checks.
The debug section, which allows you to gather information about your WordPress and server configuration that you may easily share with support representatives for themes, plugins or on the official WordPress.org support forums.
Troubleshooting allows you to have a clean WordPress session, where all plugins are disabled, and a default theme is used, but only for your user until you disable it or log out.
The Tools section allows you to check that WordPress files have not been tampered with, that emails can be sent, and if your plugins are compatible with any PHP version updates in the future.
For a more extensive example of how to efficiently use the Health Check plugin, check out the [WordPress.org support team handbook page about this plugin](https://make.wordpress.org/support/handbook/appendix/troubleshooting-using-the-health-check/).
Feedback is welcome both through the [WordPress.org forums](https://wordpress.org/support/plugin/health-check), the [GitHub project page](https://github.com/WordPress/health-check), or on [Slack](https://make.wordpress.org/chat) in either [#forums](https://wordpress.slack.com/messages/forums/) or [#core-site-health](https://wordpress.slack.com/messages/core-site-health/).
== Frequently Asked Questions ==
= I am unable to access my site after enabling troubleshooting =
If you should find your self stuck in Troubleshooting Mode for any reason, you can easily disable it by clearing your cookies.
Are you unfamiliar with how to clear your cookies? No worries, you may also close all your browser windows, or perform a computer restart and it will clear this specific cookie automatically.
= The PHP compatibility says this plugin only work with PHP version X? =
The plugin is made to be a support tool for as many users as possible, this means it needs code that is written for older sites as well.
Tools that check for PHP compatibility do not know how to separate this code from the real code, so it will give a false positive response.
At this time, the plugin has been tested with every version of PHP from 5.2 through 7.3, and works with all of these.
== Screenshots ==
1. The health check screen after the automated tests have gone over the system.
2. The debug information, with the copy and paste field expanded.
3. A selection of tools that can be ran on your site.
4. Troubleshooting mode enabled, showing your website Dashboard
== Changelog ==
= v1.5.1 (2022-11-02) =
* Fixed a bug where if Health Check was disabled during troubleshooting, you would need to force-enable/disable other plugins or themes.
= v1.5.0 (2022-09-10) =
* Added a custom filter for the Health Check plugin PHP Compatibility check.
* Added functions which will try to disable cache solutions during troubleshooting.
* Added ability to force changes if loopbacks fail during troubleshooting.
* Changed how JavaScript is built and bundled in the plugin.
* Changed the location of the `phpinfo()` check to the Tools section.
* Changed how troubleshooting mode implements its conditional actions and filters when enabled.
* Fixed styling issues for troubleshooting mode in WordPress 5.9.
* Removed Site Health Status from the plugin, as they were implemented in WordPress 5.2.
= v1.4.5 =
* Fix Troubleshooting Mode throwing errors in frontend on WordPress 5.5
= v1.4.4 =
* Fixed hidden JavaScript warning when using troubleshooting mode on the Dashboard
* Fixed plugin and theme lists staying hidden in troubleshooting mode on the Dashboard
= v1.4.3 =
* Compatibility with WordPress 5.4
= v1.4.2 =
* Fix missing headers for a loopback request in the debug section
= v1.4.1 =
* Fixed SQL version checks for various MariaDB installs.
* Fixed a warning being generated in logfiles for first-time users with no existing Site Health history.
* Added missing translation function for the new PHP compatibility tool.
= v1.4.0 =
* Fix a bug when viewing the Site Health page if enabling the Health Check plugin in troubleshooting mode.
* Fix an inconsistency with how database versions are checked.
* Fix the file comparison view on Windows systems if there are modified core files.
* Fix a bug where some premium plugins could not be enabled in troubleshooting mode
* Improved styles for older browsers.
* Improved the PHP module checks to allow for constant checks as well. Should help with some edge case tests.
* Improved the core file integrity checker.
* Improved testing of WP_cron, now works properly for those running a "real cron" outside of WordPress.
* Improved the htaccess rule test to only run if using an Apache server that supports these.
* Modify the Site Health grading indicator.
* Modified strings to make them clearer.
* Added server headers to the Debug information.
* Added polyfills for core features from WordPress 5.2 so they work for older sites.
* Added a link to the Site Health page from the plugin overview.
* Added a custom capability, `view_site_health_checks` for the plugin.
* Added support for parent/child theme output in the Debug screen.
* Added system user information to the Debug information.
* Added a Site Health test for timezone localization.
* Added `mbstring` and `json` (again) as requirements to the list of PHP extensions.
* Added a missing toggle to the list of plugins/themes to the troubleshooting dashboard widget.
* Added bulk actions to enable or disable plugins when troubleshooting, or to initiate troubleshooting mode.
* Added plugin compatibility checker ot the tools section.
* Added a dashboard widget to show your Site Health status at a glance when logging in.
* Added filters for Site Health test results.
* Added WP-CLI support, you can now run `wp health-check status` for a list of test and their status.
* Moved compatibility functions out of primary files and into a `compat.php` so they can be conditionally loaded.
* Disable the Fatal Error (WSOD) protection in WordPress while in troubleshooting mode.

View File

@ -30,7 +30,7 @@ $wpdb->delete(
);
// Remove any transients and similar which the plugin may have left behind.
$wpdb->query( "DELETE FROM {$wpdb->options} WHERE `option_name` LIKE '_transient_%_health-check%'" );
$wpdb->query( "DELETE FROM {$wpdb->options} WHERE `option_name` LIKE '_transient_health-check%'" );
// Remove the old Must-Use plugin if it was implemented.
if ( file_exists( trailingslashit( WPMU_PLUGIN_DIR ) . 'health-check-disable-plugins.php' ) ) {