2021-01-02 14:53:24 +01:00
< ? php
/*
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 .
2022-12-15 19:05:44 +01:00
Version : 1.8 . 1
2021-01-02 14:53:24 +01:00
*/
if ( ! defined ( 'ABSPATH' ) ) {
die ( 'We\'re sorry, but you can not directly access this file.' );
}
// Set the MU plugin version.
2022-12-15 19:05:44 +01:00
define ( 'HEALTH_CHECK_TROUBLESHOOTING_MODE_PLUGIN_VERSION' , '1.8.1' );
2021-01-02 14:53:24 +01:00
class Health_Check_Troubleshooting_MU {
private $disable_hash = null ;
private $override_active = true ;
private $default_theme = true ;
private $active_plugins = array ();
private $allowed_plugins = array ();
private $current_theme ;
private $current_theme_details ;
private $self_fetching_theme = false ;
private $available_query_args = array (
'wp-health-check-disable-plugins' ,
'health-check-disable-plugins-hash' ,
'health-check-disable-troubleshooting' ,
'health-check-change-active-theme' ,
'health-check-troubleshoot-enable-plugin' ,
'health-check-troubleshoot-disable-plugin' ,
2022-12-15 19:05:44 +01:00
'health-check-plugin-force-enable' ,
'health-check-plugin-force-disable' ,
'health-check-theme-force-switch' ,
2021-01-02 14:53:24 +01:00
);
private $default_themes = array (
2022-12-15 19:05:44 +01:00
'twentytwentytwo' ,
'twentytwentyone' ,
2021-01-02 14:53:24 +01:00
'twentytwenty' ,
'twentynineteen' ,
'twentyseventeen' ,
'twentysixteen' ,
'twentyfifteen' ,
'twentyfourteen' ,
'twentythirteen' ,
'twentytwelve' ,
'twentyeleven' ,
'twentyten' ,
);
/**
* Health_Check_Troubleshooting_MU constructor .
*/
public function __construct () {
$this -> init ();
}
/**
* Actually initiation of the plugin .
*
* @ return void
*/
public function init () {
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 ( 'bulk_actions-plugins' , array ( $this , 'remove_plugin_bulk_actions' ) );
add_filter ( 'handle_bulk_actions-plugins' , array ( $this , 'handle_plugin_bulk_actions' ), 10 , 3 );
2022-12-15 19:05:44 +01:00
$this -> load_options ();
2021-01-02 14:53:24 +01:00
2022-12-15 19:05:44 +01:00
// 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 );
2021-01-02 14:53:24 +01:00
2022-12-15 19:05:44 +01:00
// Add nocache headers for browser caches.
add_action ( 'init' , 'nocache_headers' );
add_action ( 'admin_init' , 'nocache_headers' );
2021-01-02 14:53:24 +01:00
2022-12-15 19:05:44 +01:00
add_action ( 'admin_enqueue_scripts' , array ( $this , 'enqueue_assets' ) );
2021-01-02 14:53:24 +01:00
2022-12-15 19:05:44 +01:00
add_action ( 'admin_bar_menu' , array ( $this , 'health_check_troubleshoot_menu_bar' ), 999 );
2021-01-02 14:53:24 +01:00
2022-12-15 19:05:44 +01:00
add_filter ( 'wp_fatal_error_handler_enabled' , '__return_false' );
2021-01-02 14:53:24 +01:00
2022-12-15 19:05:44 +01:00
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' ) );
}
2021-01-02 14:53:24 +01:00
}
/**
* Set up the class variables based on option table entries .
*
* @ return void
*/
public function load_options () {
$this -> disable_hash = get_option ( 'health-check-disable-plugin-hash' , null );
$this -> allowed_plugins = get_option ( 'health-check-allowed-plugins' , array () );
$this -> default_theme = ( 'yes' === get_option ( 'health-check-default-theme' , 'yes' ) ? true : false );
$this -> active_plugins = $this -> get_unfiltered_plugin_list ();
$this -> current_theme = get_option ( 'health-check-current-theme' , false );
}
/**
* Enqueue styles and scripts used by the MU plugin if applicable .
*
* @ return void
*/
public function enqueue_assets () {
2022-12-15 19:05:44 +01:00
if ( ! is_admin () ) {
2021-01-02 14:53:24 +01:00
return ;
}
2022-12-15 19:05:44 +01:00
wp_enqueue_style ( 'health-check' , plugins_url ( '/health-check/build/health-check.css' ), array (), HEALTH_CHECK_TROUBLESHOOTING_MODE_PLUGIN_VERSION );
2021-01-02 14:53:24 +01:00
if ( ! wp_script_is ( 'site-health' , 'registered' ) ) {
2022-12-15 19:05:44 +01:00
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 );
2021-01-02 14:53:24 +01:00
}
2022-12-15 19:05:44 +01:00
wp_enqueue_script ( 'health-check' , plugins_url ( '/health-check/build/troubleshooting-mode.js' ), array ( 'site-health' ), HEALTH_CHECK_TROUBLESHOOTING_MODE_PLUGIN_VERSION , true );
2021-01-02 14:53:24 +01:00
}
/**
* Add a prompt to install a default theme .
*
* If no default theme exists , we can ' t reliably assert if an issue is
* caused by the theme . In these cases we should provide an easy step
* to get to , and install , one of the default themes .
*
* @ return void
*/
public function prompt_install_default_theme () {
2022-12-15 19:05:44 +01:00
if ( $this -> has_default_theme () ) {
2021-01-02 14:53:24 +01:00
return ;
}
printf (
'<div class="notice notice-warning dismissable"><p>%s</p><p><a href="%s" class="button button-primary">%s</a></p></div>' ,
esc_html__ ( 'You don\'t have any of the default themes installed. A default theme helps you determine if your current theme is causing conflicts.' , 'health-check' ),
esc_url (
admin_url (
sprintf (
'theme-install.php?theme=%s' ,
$this -> default_themes [ 0 ]
)
)
),
esc_html__ ( 'Install a default theme' , 'health-check' )
);
}
/**
* Remove the `Add` option for plugins and themes .
*
* When troubleshooting , adding or changing themes and plugins can
* lead to unexpected results . Remove these menu items to make it less
* likely that a user breaks their site through these .
*
* @ param array $caps Array containing the current users capabilities .
*
* @ return array
*/
public function remove_plugin_theme_install ( $caps ) {
$caps [ 'switch_themes' ] = false ;
/*
* This is to early for `get_current_screen()` , so we have to do it the
* old fashioned way with `$_SERVER` .
*/
if ( 'plugin-install.php' === substr ( $_SERVER [ 'REQUEST_URI' ], - 18 ) ) {
$caps [ 'activate_plugins' ] = false ;
}
return $caps ;
}
/**
* Fire on plugin activation .
*
* When in Troubleshooting Mode , plugin activations
* will clear out the DB entry for `active_plugins` , this is bad .
*
* We fix this by re - setting the DB entry if anything tries
* to modify it during troubleshooting .
*
* @ return void
*/
public function plugin_activated () {
// Force the database entry for active plugins if someone tried changing plugins while in Troubleshooting Mode.
update_option ( 'active_plugins' , $this -> active_plugins );
}
public function handle_plugin_bulk_actions ( $sendback , $action , $plugins ) {
if ( ! $this -> is_troubleshooting () && 'health-check-troubleshoot' !== $action ) {
return $sendback ;
}
$sendback = self_admin_url ( 'plugins.php' );
if ( 'health-check-troubleshoot' === $action ) {
foreach ( $plugins as $single_plugin ) {
$plugin_slug = explode ( '/' , $single_plugin );
$plugin_slug = $plugin_slug [ 0 ];
if ( in_array ( $single_plugin , $this -> active_plugins , true ) ) {
$this -> allowed_plugins [ $plugin_slug ] = $plugin_slug ;
}
}
Health_Check_Troubleshoot :: initiate_troubleshooting_mode ( $this -> allowed_plugins );
if ( ! $this -> test_site_state () ) {
$this -> allowed_plugins = array ();
update_option ( 'health-check-allowed-plugins' , $this -> allowed_plugins );
$this -> add_dashboard_notice (
__ ( 'When enabling troubleshooting on the selected plugins, a site failure occurred. Because of this the selected plugins were kept disabled while troubleshooting mode started.' , 'health-check' ),
'warning'
);
}
}
if ( 'health-check-enable' === $action ) {
$old_allowed_plugins = $this -> allowed_plugins ;
foreach ( $plugins as $single_plugin ) {
$plugin_slug = explode ( '/' , $single_plugin );
$plugin_slug = $plugin_slug [ 0 ];
if ( in_array ( $single_plugin , $this -> active_plugins , true ) ) {
$this -> allowed_plugins [ $plugin_slug ] = $plugin_slug ;
}
}
update_option ( 'health-check-allowed-plugins' , $this -> allowed_plugins );
if ( ! $this -> test_site_state () ) {
$this -> allowed_plugins = $old_allowed_plugins ;
update_option ( 'health-check-allowed-plugins' , $old_allowed_plugins );
$this -> add_dashboard_notice (
__ ( 'When bulk-enabling plugins, a site failure occurred. Because of this the change was automatically reverted.' , 'health-check' ),
'warning'
);
}
}
if ( 'health-check-disable' === $action ) {
$old_allowed_plugins = $this -> allowed_plugins ;
foreach ( $plugins as $single_plugin ) {
$plugin_slug = explode ( '/' , $single_plugin );
$plugin_slug = $plugin_slug [ 0 ];
if ( in_array ( $single_plugin , $this -> active_plugins , true ) ) {
unset ( $this -> allowed_plugins [ $plugin_slug ] );
}
}
update_option ( 'health-check-allowed-plugins' , $this -> allowed_plugins );
if ( ! $this -> test_site_state () ) {
$this -> allowed_plugins = $old_allowed_plugins ;
update_option ( 'health-check-allowed-plugins' , $old_allowed_plugins );
$this -> add_dashboard_notice (
__ ( 'When bulk-disabling plugins, a site failure occurred. Because of this the change was automatically reverted.' , 'health-check' ),
'warning'
);
}
}
return $sendback ;
}
public function remove_plugin_bulk_actions ( $actions ) {
if ( ! $this -> is_troubleshooting () ) {
$actions [ 'health-check-troubleshoot' ] = __ ( 'Troubleshoot' , 'health-check' );
return $actions ;
}
$actions = array (
'health-check-enable' => __ ( 'Enable while troubleshooting' , 'health-check' ),
'health-check-disable' => __ ( 'Disable while troubleshooting' , 'health-check' ),
);
return $actions ;
}
/**
* Modify plugin actions .
*
* While in Troubleshooting Mode , weird things will happen if you start
* modifying your plugin list . Prevent this , but also add in the ability
* to enable or disable a plugin during troubleshooting from this screen .
*
* @ param $actions
* @ param $plugin_file
* @ param $plugin_data
* @ param $context
*
* @ return array
*/
public function plugin_actions ( $actions , $plugin_file , $plugin_data , $context ) {
if ( 'mustuse' === $context ) {
return $actions ;
}
/*
* Disable all plugin actions when in Troubleshooting Mode .
*
* We intentionally remove all plugin actions to avoid accidental clicking , activating or deactivating plugins
* while our plugin is altering plugin data may lead to unexpected behaviors , so to keep things sane we do
* not allow users to perform any actions during this time .
*/
$actions = array ();
// This isn't an active plugin, so does not apply to our troubleshooting scenarios.
if ( ! in_array ( $plugin_file , $this -> active_plugins , true ) ) {
return $actions ;
}
// Set a slug if the plugin lives in the plugins directory root.
if ( ! stristr ( $plugin_file , '/' ) ) {
$plugin_slug = $plugin_file ;
} else { // Set the slug for plugin inside a folder.
$plugin_slug = explode ( '/' , $plugin_file );
$plugin_slug = $plugin_slug [ 0 ];
}
if ( in_array ( $plugin_slug , $this -> allowed_plugins , true ) ) {
$actions [ 'troubleshoot-disable' ] = sprintf (
'<a href="%s">%s</a>' ,
esc_url (
add_query_arg (
array (
'health-check-troubleshoot-disable-plugin' => $plugin_slug ,
),
admin_url ( 'plugins.php' )
)
),
esc_html__ ( 'Disable while troubleshooting' , 'health-check' )
);
} else {
$actions [ 'troubleshoot-disable' ] = sprintf (
'<a href="%s">%s</a>' ,
esc_url (
add_query_arg (
array (
'health-check-troubleshoot-enable-plugin' => $plugin_slug ,
),
admin_url ( 'plugins.php' )
)
),
esc_html__ ( 'Enable while troubleshooting' , 'health-check' )
);
}
return $actions ;
}
/**
* Get the actual list of active plugins .
*
* When in Troubleshooting Mode we override the list of plugins ,
* this function lets us grab the active plugins list without
* any interference .
*
* @ return array Array of active plugins .
*/
public function get_unfiltered_plugin_list () {
$this -> override_active = false ;
$all_plugins = get_option ( 'active_plugins' );
$this -> override_active = true ;
return $all_plugins ;
}
/**
* Check if the user is currently in Troubleshooting Mode or not .
*
* @ return bool
*/
public function is_troubleshooting () {
// Check if a session cookie to disable plugins has been set.
if ( isset ( $_COOKIE [ 'wp-health-check-disable-plugins' ] ) ) {
$_GET [ 'health-check-disable-plugin-hash' ] = $_COOKIE [ 'wp-health-check-disable-plugins' ] . md5 ( $_SERVER [ 'REMOTE_ADDR' ] );
}
// If the disable hash isn't set, no need to interact with things.
if ( ! isset ( $_GET [ 'health-check-disable-plugin-hash' ] ) ) {
return false ;
}
if ( empty ( $this -> disable_hash ) ) {
return false ;
}
// If the plugin hash is not valid, we also break out
if ( $this -> disable_hash !== $_GET [ 'health-check-disable-plugin-hash' ] ) {
return false ;
}
return true ;
}
/**
* Filter the plugins that are activated in WordPress .
*
* @ param array $plugins An array of plugins marked as active .
*
* @ return array
*/
function health_check_loopback_test_disable_plugins ( $plugins ) {
if ( ! $this -> is_troubleshooting () || ! $this -> override_active ) {
return $plugins ;
}
// If we've received a comma-separated list of allowed plugins, we'll add them to the array of allowed plugins.
if ( isset ( $_GET [ 'health-check-allowed-plugins' ] ) ) {
$this -> allowed_plugins = explode ( ',' , $_GET [ 'health-check-allowed-plugins' ] );
}
foreach ( $plugins as $plugin_no => $plugin_path ) {
// Split up the plugin path, [0] is the slug and [1] holds the primary plugin file.
$plugin_parts = explode ( '/' , $plugin_path );
// We may want to allow individual, or groups of plugins, so introduce a skip-mechanic for those scenarios.
if ( in_array ( $plugin_parts [ 0 ], $this -> allowed_plugins , true ) ) {
continue ;
}
// Remove the reference to this plugin.
unset ( $plugins [ $plugin_no ] );
}
// Return a possibly modified list of activated plugins.
return $plugins ;
}
/**
* Check if a default theme exists .
*
* If a default theme exists , return the most recent one , if not return `false` .
*
* @ return bool | string
*/
function has_default_theme () {
foreach ( $this -> default_themes as $default_theme ) {
if ( $this -> theme_exists ( $default_theme ) ) {
return $default_theme ;
}
}
return false ;
}
/**
* Check if a theme exists by looking for the slug .
*
* @ param string $theme_slug
*
* @ return bool
*/
function theme_exists ( $theme_slug ) {
return is_dir ( WP_CONTENT_DIR . '/themes/' . $theme_slug );
}
/**
* Check if theme overrides are active .
*
* @ return bool
*/
function override_theme () {
if ( ! $this -> is_troubleshooting () ) {
return false ;
}
return true ;
}
/**
* Override the default theme .
*
* Attempt to set one of the default themes , or a theme of the users choosing , as the active one
* during Troubleshooting Mode .
*
* @ param $default
*
* @ return bool | string
*/
function health_check_troubleshoot_theme_stylesheet ( $default ) {
if ( $this -> self_fetching_theme ) {
return $default ;
}
if ( ! $this -> override_theme () ) {
return $default ;
}
if ( empty ( $this -> current_theme_details ) ) {
$this -> self_fetching_theme = true ;
$this -> current_theme_details = wp_get_theme ( $this -> current_theme );
$this -> self_fetching_theme = false ;
}
// If no theme has been chosen, start off by troubleshooting as a default theme if one exists.
$default_theme = $this -> has_default_theme ();
if ( false === $this -> current_theme ) {
if ( $default_theme ) {
return $default_theme ;
}
}
return $this -> current_theme ;
}
/**
* Override the default parent theme .
*
* If this is a child theme , override the parent and provide our users chosen themes parent instead .
*
* @ param $default
*
* @ return bool | string
*/
function health_check_troubleshoot_theme_template ( $default ) {
if ( $this -> self_fetching_theme ) {
return $default ;
}
if ( ! $this -> override_theme () ) {
return $default ;
}
if ( empty ( $this -> current_theme_details ) ) {
$this -> self_fetching_theme = true ;
$this -> current_theme_details = wp_get_theme ( $this -> current_theme );
$this -> self_fetching_theme = false ;
}
// If no theme has been chosen, start off by troubleshooting as a default theme if one exists.
$default_theme = $this -> has_default_theme ();
if ( false === $this -> current_theme ) {
if ( $default_theme ) {
return $default_theme ;
}
}
if ( $this -> current_theme_details -> parent () ) {
return $this -> current_theme_details -> get_template ();
}
return $this -> current_theme ;
}
/**
* Disable Troubleshooting Mode on logout .
*
* If logged in , disable the Troubleshooting Mode when the logout
* event is fired , this ensures we start with a clean slate on
* the next login .
*
* @ return void
*/
function health_check_troubleshooter_mode_logout () {
if ( isset ( $_COOKIE [ 'wp-health-check-disable-plugins' ] ) ) {
$this -> disable_troubleshooting_mode ();
}
}
function disable_troubleshooting_mode () {
unset ( $_COOKIE [ 'wp-health-check-disable-plugins' ] );
setcookie ( 'wp-health-check-disable-plugins' , null , 0 , COOKIEPATH , COOKIE_DOMAIN );
delete_option ( 'health-check-allowed-plugins' );
delete_option ( 'health-check-default-theme' );
delete_option ( 'health-check-current-theme' );
delete_option ( 'health-check-backup-plugin-list' );
}
/**
* Catch query arguments .
*
* When in Troubleshooting Mode , look for various GET variables that trigger
* various plugin actions .
*
* @ return void
*/
function health_check_troubleshoot_get_captures () {
// Disable Troubleshooting Mode.
if ( isset ( $_GET [ 'health-check-disable-troubleshooting' ] ) ) {
$this -> disable_troubleshooting_mode ();
wp_redirect ( remove_query_arg ( $this -> available_query_args ) );
die ();
}
// Dismiss notices.
if ( isset ( $_GET [ 'health-check-dismiss-notices' ] ) && $this -> is_troubleshooting () && is_admin () ) {
update_option ( 'health-check-dashboard-notices' , array () );
wp_redirect ( admin_url () );
die ();
}
// Enable an individual plugin.
if ( isset ( $_GET [ 'health-check-troubleshoot-enable-plugin' ] ) ) {
$old_allowed_plugins = $this -> allowed_plugins ;
$this -> allowed_plugins [ $_GET [ 'health-check-troubleshoot-enable-plugin' ] ] = $_GET [ 'health-check-troubleshoot-enable-plugin' ];
update_option ( 'health-check-allowed-plugins' , $this -> allowed_plugins );
2022-12-15 19:05:44 +01:00
if ( isset ( $_GET [ 'health-check-plugin-force-enable' ] ) ) {
2021-01-02 14:53:24 +01:00
$this -> add_dashboard_notice (
sprintf (
2022-12-15 19:05:44 +01:00
// translators: %s: The plugin slug.
'The %s plugin was forcefully enabled.' ,
2021-01-02 14:53:24 +01:00
$_GET [ 'health-check-troubleshoot-enable-plugin' ]
),
2022-12-15 19:05:44 +01:00
'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 );
$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 (
'<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 ,
2021-01-02 14:53:24 +01:00
'warning'
);
}
wp_redirect ( remove_query_arg ( $this -> available_query_args ) );
die ();
}
// Disable an individual plugin.
if ( isset ( $_GET [ 'health-check-troubleshoot-disable-plugin' ] ) ) {
$old_allowed_plugins = $this -> allowed_plugins ;
unset ( $this -> allowed_plugins [ $_GET [ 'health-check-troubleshoot-disable-plugin' ] ] );
update_option ( 'health-check-allowed-plugins' , $this -> allowed_plugins );
2022-12-15 19:05:44 +01:00
if ( isset ( $_GET [ 'health-check-plugin-force-disable' ] ) ) {
2021-01-02 14:53:24 +01:00
$this -> add_dashboard_notice (
sprintf (
2022-12-15 19:05:44 +01:00
// translators: %s: The plugin slug.
'The %s plugin was forcefully disabled.' ,
2021-01-02 14:53:24 +01:00
$_GET [ 'health-check-troubleshoot-disable-plugin' ]
),
2022-12-15 19:05:44 +01:00
'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 );
$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 (
'<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 ,
2021-01-02 14:53:24 +01:00
'warning'
);
}
wp_redirect ( remove_query_arg ( $this -> available_query_args ) );
die ();
}
// Change the active theme for this session.
if ( isset ( $_GET [ 'health-check-change-active-theme' ] ) ) {
$old_theme = get_option ( 'health-check-current-theme' );
update_option ( 'health-check-current-theme' , $_GET [ 'health-check-change-active-theme' ] );
2022-12-15 19:05:44 +01:00
if ( isset ( $_GET [ 'health-check-theme-force-switch' ] ) ) {
2021-01-02 14:53:24 +01:00
$this -> add_dashboard_notice (
sprintf (
2022-12-15 19:05:44 +01:00
// translators: %s: The theme slug.
'The theme was forcefully switched to %s.' ,
2021-01-02 14:53:24 +01:00
$_GET [ 'health-check-change-active-theme' ]
),
2022-12-15 19:05:44 +01:00
'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 ,
2021-01-02 14:53:24 +01:00
'warning'
);
}
wp_redirect ( remove_query_arg ( $this -> available_query_args ) );
die ();
}
}
private function add_dashboard_notice ( $message , $severity = 'notice' ) {
$notices = get_option ( 'health-check-dashboard-notices' , array () );
$notices [] = array (
'severity' => $severity ,
'message' => $message ,
'time' => gmdate ( 'Y-m-d H:i' ),
);
update_option ( 'health-check-dashboard-notices' , $notices );
}
/**
* Extend the admin bar .
*
* When in Troubleshooting Mode , introduce a new element to the admin bar to show
* enabled and disabled plugins ( if conditions are met ), switch between themes
* and disable Troubleshooting Mode altogether .
*
* @ param WP_Admin_Bar $wp_menu
*
* @ return void
*/
function health_check_troubleshoot_menu_bar ( $wp_menu ) {
// 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' );
}
// 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' ) ) {
2022-12-15 19:05:44 +01:00
require_once ( trailingslashit ( ABSPATH ) . 'wp-admin/includes/update.php' );
}
2021-01-02 14:53:24 +01:00
// Ensure the theme functions are available to us on every page.
include_once ( trailingslashit ( ABSPATH ) . 'wp-admin/includes/theme.php' );
// Add top-level menu item.
$wp_menu -> add_menu (
array (
'id' => 'health-check' ,
'title' => esc_html__ ( 'Troubleshooting Mode' , 'health-check' ),
'href' => admin_url ( '/' ),
)
);
// Add a link to manage plugins if there are more than 20 set to be active.
if ( count ( $this -> active_plugins ) > 20 ) {
$wp_menu -> add_node (
array (
'id' => 'health-check-plugins' ,
'title' => esc_html__ ( 'Manage active plugins' , 'health-check' ),
'parent' => 'health-check' ,
'href' => admin_url ( 'plugins.php' ),
)
);
} else {
$wp_menu -> add_node (
array (
'id' => 'health-check-plugins' ,
'title' => esc_html__ ( 'Plugins' , 'health-check' ),
'parent' => 'health-check' ,
'href' => admin_url ( 'plugins.php' ),
)
);
$wp_menu -> add_group (
array (
'id' => 'health-check-plugins-enabled' ,
'parent' => 'health-check-plugins' ,
)
);
$wp_menu -> add_group (
array (
'id' => 'health-check-plugins-disabled' ,
'parent' => 'health-check-plugins' ,
)
);
foreach ( $this -> active_plugins as $single_plugin ) {
$plugin_slug = explode ( '/' , $single_plugin );
$plugin_slug = $plugin_slug [ 0 ];
$plugin_data = get_plugin_data ( trailingslashit ( WP_PLUGIN_DIR ) . $single_plugin );
$enabled = true ;
if ( in_array ( $plugin_slug , $this -> allowed_plugins , true ) ) {
$label = sprintf (
// Translators: %s: Plugin slug.
esc_html__ ( 'Disable %s' , 'health-check' ),
sprintf (
'<strong>%s</strong>' ,
$plugin_data [ 'Name' ]
)
);
$url = add_query_arg (
array (
'health-check-troubleshoot-disable-plugin' => $plugin_slug ,
)
);
} else {
$enabled = false ;
$label = sprintf (
// Translators: %s: Plugin slug.
esc_html__ ( 'Enable %s' , 'health-check' ),
sprintf (
'<strong>%s</strong>' ,
$plugin_data [ 'Name' ]
)
);
$url = add_query_arg (
array (
'health-check-troubleshoot-enable-plugin' => $plugin_slug ,
)
);
}
$wp_menu -> add_node (
array (
'id' => sprintf (
'health-check-plugin-%s' ,
$plugin_slug
),
'title' => $label ,
'parent' => ( $enabled ? 'health-check-plugins-enabled' : 'health-check-plugins-disabled' ),
'href' => $url ,
)
);
}
}
$wp_menu -> add_node (
array (
'id' => 'health-check-theme' ,
'title' => esc_html__ ( 'Themes' , 'health-check' ),
'parent' => 'health-check' ,
'href' => admin_url ( 'themes.php' ),
)
);
$themes = wp_prepare_themes_for_js ();
foreach ( $themes as $theme ) {
$node = array (
'id' => sprintf (
'health-check-theme-%s' ,
sanitize_title ( $theme [ 'id' ] )
),
'title' => sprintf (
'%s %s' ,
( $theme [ 'active' ] ? esc_html_x ( 'Active:' , 'Prefix for the active theme in troubleshooting mode' , 'health-check' ) : esc_html_x ( 'Switch to' , 'Prefix for inactive themes in troubleshooting mode' , 'health-check' ) ),
$theme [ 'name' ]
),
'parent' => 'health-check-theme' ,
);
if ( ! $theme [ 'active' ] ) {
$node [ 'href' ] = add_query_arg (
array (
'health-check-change-active-theme' => $theme [ 'id' ],
)
);
}
$wp_menu -> add_node ( $node );
}
// Add a link to disable Troubleshooting Mode.
$wp_menu -> add_node (
array (
'id' => 'health-check-disable' ,
'title' => esc_html__ ( 'Disable Troubleshooting Mode' , 'health-check' ),
'parent' => 'health-check' ,
'href' => add_query_arg (
array (
'health-check-disable-troubleshooting' => true ,
)
),
)
);
}
public function test_site_state () {
// 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' ) ) {
2022-12-15 19:05:44 +01:00
$plugin_file = trailingslashit ( WP_PLUGIN_DIR ) . 'health-check/HealthCheck/class-health-check-loopback.php' ;
2021-01-02 14:53:24 +01:00
// Make sure the file exists, in case someone deleted the plugin manually, we don't want any errors.
if ( ! file_exists ( $plugin_file ) ) {
// If the plugin files are inaccessible, we can't guarantee for the state of the site, so the default is a bad response.
return false ;
}
require_once ( $plugin_file );
}
$loopback_state = Health_Check_Loopback :: can_perform_loopback ();
if ( 'good' !== $loopback_state -> status ) {
return false ;
}
return true ;
}
public function dashboard_widget_scripts () {
// 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 ) {
return ;
}
}
public function display_dashboard_widget () {
// 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 ) {
return ;
}
$notices = get_option ( 'health-check-dashboard-notices' , array () );
$active_plugins = array ();
$inactive_plugins = array ();
$themes = wp_prepare_themes_for_js ();
?>
< div class = " wrap " >
< div id = " health-check-dashboard-widget " >
< div class = " welcome-panel-content health-check-column " >
< h2 >
< ? php
printf (
// translators: %s: The running status of Troubleshooting Mode.
esc_html__ ( 'Troubleshooting Mode - %s' , 'health-check' ),
sprintf (
'<span class="green">%s</span>' ,
esc_html__ ( 'enabled' , 'health-check' )
)
);
?>
</ h2 >
< ? php
printf (
'<a href="%s" class="button button-primary">%s</a>' ,
esc_url (
add_query_arg (
array (
'health-check-disable-troubleshooting' => true ,
)
)
),
esc_html__ ( 'Disable Troubleshooting Mode' , 'health-check' )
);
?>
< div class = " about-description " >
< p >
< ? php _e ( 'Your site is currently in Troubleshooting Mode. This has <strong>no effect on your site visitors</strong>, they will continue to view your site as usual, but for you it will look as if you had just installed WordPress for the first time.' , 'health-check' ); ?>
</ p >
< 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 >
2022-12-15 19:05:44 +01:00
< 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 >
2021-01-02 14:53:24 +01:00
</ div >
</ div >
< div class = " health-check-column " >
< dl role = " presentation " class = " health-check-accordion " >
< dt role = " heading " aria - level = " 3 " >
< button aria - expanded = " false " class = " health-check-accordion-trigger " aria - controls = " health-check-accordion-block-plugins " id = " health-check-accordion-heading-plugins " type = " button " >
< span class = " title " >
< ? php
printf (
// translators: %d: The amount of available plugins.
esc_html__ ( 'Available plugins (%d)' , 'health-check' ),
esc_html ( is_countable ( $this -> active_plugins ) ? count ( $this -> active_plugins ) : 0 )
);
?>
</ span >
< span class = " icon " ></ span >
</ button >
</ dt >
< dd id = " health-check-accordion-block-plugins " role = " region " aria - labelledby = " health-check-accordion-heading-plugins " class = " health-check-accordion-panel " hidden = " hidden " >
< ul id = " health-check-plugins " role = " list " >
< ? php
$has_toggle = false ;
foreach ( $this -> active_plugins as $count => $single_plugin ) {
$plugin_slug = explode ( '/' , $single_plugin );
$plugin_slug = $plugin_slug [ 0 ];
$plugin_is_visible = true ;
if ( $count >= 5 ) {
$plugin_is_visible = false ;
}
$plugin_data = get_plugin_data ( trailingslashit ( WP_PLUGIN_DIR ) . $single_plugin );
$actions = array ();
if ( in_array ( $plugin_slug , $this -> allowed_plugins , true ) ) {
$actions [] = sprintf (
'<a href="%s" aria-label="%s">%s</a>' ,
esc_url (
add_query_arg (
array (
'health-check-troubleshoot-disable-plugin' => $plugin_slug ,
)
)
),
esc_attr (
sprintf (
// translators: %s: Plugin name.
__ ( 'Disable the plugin, %s, while troubleshooting.' , 'health-check' ),
$plugin_data [ 'Name' ]
)
),
esc_html__ ( 'Disable' , 'health-check' )
);
} else {
$actions [] = sprintf (
'<a href="%s" aria-label="%s">%s</a>' ,
esc_url (
add_query_arg (
array (
'health-check-troubleshoot-enable-plugin' => $plugin_slug ,
)
)
),
esc_attr (
sprintf (
// translators: %s: Plugin name.
__ ( 'Enable the plugin, %s, while troubleshooting.' , 'health-check' ),
$plugin_data [ 'Name' ]
)
),
esc_html__ ( 'Enable' , 'health-check' )
);
}
if ( ! $plugin_is_visible && ! $has_toggle ) {
$has_toggle = true ;
printf (
'<li><button type="button" class="show-remaining button button-link">%s</button></li>' ,
sprintf (
// translators: %d: Amount of hidden plugins.
2022-12-15 19:05:44 +01:00
_n (
'Show %d remaining plugin' ,
'Show %d remaining plugins' ,
( is_countable ( $this -> active_plugins ) ? ( count ( $this -> active_plugins ) - 5 ) : 0 ),
'health-check'
),
2021-01-02 14:53:24 +01:00
( is_countable ( $this -> active_plugins ) ? ( count ( $this -> active_plugins ) - 5 ) : 0 )
)
);
}
printf (
'<li class="%s">%s - %s</li>' ,
( ! $plugin_is_visible ? 'toggle-visibility hidden' : '' ),
esc_html ( $plugin_data [ 'Name' ] ),
implode ( ' | ' , $actions )
);
}
?>
</ ul >
</ dd >
< dt role = " heading " aria - level = " 3 " >
< button aria - expanded = " false " class = " health-check-accordion-trigger " aria - controls = " health-check-accordion-block-themes " id = " health-check-accordion-heading-themes " type = " button " >
< span class = " title " >
< ? php
printf (
// translators: %d: The amount of available themes.
esc_html__ ( 'Available themes (%d)' , 'health-check' ),
esc_html ( is_countable ( $themes ) ? count ( $themes ) : 0 )
);
?>
</ span >
< span class = " icon " ></ span >
</ button >
</ dt >
< dd id = " health-check-accordion-block-themes " role = " region " aria - labelledby = " health-check-accordion-heading-themes " class = " health-check-accordion-panel " hidden = " hidden " >
< ul id = " health-check-themes " role = " list " >
< ? php
$has_toggle = false ;
foreach ( $themes as $count => $theme ) {
$theme_is_visible = true ;
if ( $count >= 5 ) {
$theme_is_visible = false ;
}
$actions = sprintf (
'<a href="%s" aria-label="%s">%s</a>' ,
esc_url (
add_query_arg (
array (
'health-check-change-active-theme' => $theme [ 'id' ],
)
)
),
esc_attr (
sprintf (
// translators: %s: Theme name.
__ ( 'Switch the active theme to %s' , 'health-check' ),
$theme [ 'name' ]
)
),
esc_html__ ( 'Switch to this theme' , 'health-check' )
);
$plugin_label = sprintf (
'%s %s' ,
// translators: Prefix for the active theme in a listing.
( $theme [ 'active' ] ? esc_html__ ( 'Active:' , 'health-check' ) : '' ),
$theme [ 'name' ]
);
if ( ! $theme [ 'active' ] ) {
$plugin_label .= ' - ' . $actions ;
}
if ( ! $theme_is_visible && ! $has_toggle ) {
$has_toggle = true ;
printf (
'<li><button type="button" class="show-remaining button button-link">%s</button></li>' ,
sprintf (
// translators: %d: Amount of hidden themes.
2022-12-15 19:05:44 +01:00
_n (
'Show %d remaining theme' ,
'Show %d remaining themes' ,
( is_countable ( $themes ) ? ( count ( $themes ) - 5 ) : 0 ),
'health-check'
),
2021-01-02 14:53:24 +01:00
( is_countable ( $themes ) ? ( count ( $themes ) - 5 ) : 0 )
)
);
}
printf (
'<li class="%s">%s</li>' ,
( ! $theme_is_visible ? 'toggle-visibility hidden' : '' ),
$plugin_label
);
}
?>
</ ul >
</ dd >
< dt role = " heading " aria - level = " 3 " >
< button aria - expanded = " true " class = " health-check-accordion-trigger " aria - controls = " health-check-accordion-block-notices " id = " health-check-accordion-heading-notices " type = " button " >
< span class = " title " >
< ? php
printf (
// translators: %d: The amount of notices that are visible.
esc_html__ ( 'Notices (%d)' , 'health-check' ),
esc_html ( is_countable ( $notices ) ? count ( $notices ) : 0 )
);
?>
</ span >
< span class = " icon " ></ span >
</ button >
</ dt >
< dd id = " health-check-accordion-block-notices " role = " region " aria - labelledby = " health-check-accordion-heading-notices " class = " health-check-accordion-panel " >
< ? php if ( empty ( $notices ) && 'plugins' !== $screen -> id ) : ?>
< div class = " no-notices " >
< p >
< ? php esc_html_e ( 'There are no notices to show.' , 'health-check' ); ?>
</ p >
</ div >
< ? php endif ; ?>
< ? php if ( 'plugins' === $screen -> id ) : ?>
< div class = " notice notice-warning inline " >
< p >
< ? php esc_html_e ( 'Plugin actions, such as activating and deactivating, are not available while in Troubleshooting Mode.' , 'health-check' ); ?>
</ p >
</ div >
< ? php endif ; ?>
< ? php
foreach ( $notices as $notice ) {
printf (
'<div class="notice notice-%s inline"><p>%s</p></div>' ,
esc_attr ( $notice [ 'severity' ] ),
2022-12-15 19:05:44 +01:00
wp_kses (
$notice [ 'message' ],
array (
'a' => array (
'class' => true ,
'href' => true ,
'aria-label' => true ,
),
)
)
2021-01-02 14:53:24 +01:00
);
}
?>
< ? php
if ( ! empty ( $notices ) ) {
printf (
'<div class="dismiss-notices"><a href="%s" class="">%s</a></div>' ,
esc_url (
add_query_arg (
array (
'health-check-dismiss-notices' => true ,
)
)
),
esc_html__ ( 'Dismiss notices' , 'health-check' )
);
}
?>
</ dd >
</ dl >
</ div >
</ div >
</ div >
< ? php
}
}
new Health_Check_Troubleshooting_MU ();