diff --git a/src/wp-admin/css/list-tables.css b/src/wp-admin/css/list-tables.css index 60c0da30c5..c22d4cc852 100644 --- a/src/wp-admin/css/list-tables.css +++ b/src/wp-admin/css/list-tables.css @@ -1301,31 +1301,6 @@ ul.cat-checklist { text-decoration: underline; } -.plugins tr.paused th.check-column { - border-left: 4px solid #d54e21; -} - -.plugins tr.paused th, -.plugins tr.paused td { - background-color: #fef7f1; -} - -.plugins tr.paused .plugin-title, -.plugins .paused .dashicons-warning { - color: #dc3232; -} - -.plugins .paused .error-display p, -.plugins .paused .error-display code { - font-size: 90%; - font-style: italic; - color: rgb( 0, 0, 0, 0.7 ); -} - -.plugins .resume-link { - color: #dc3232; -} - .plugin-card .update-now:before { color: #f56e28; content: "\f463"; diff --git a/src/wp-admin/includes/admin-filters.php b/src/wp-admin/includes/admin-filters.php index 3407e93171..4da6469d5f 100644 --- a/src/wp-admin/includes/admin-filters.php +++ b/src/wp-admin/includes/admin-filters.php @@ -117,8 +117,6 @@ add_action( 'load-plugins.php', 'wp_plugin_update_rows', 20 ); // After wp_updat add_action( 'load-themes.php', 'wp_theme_update_rows', 20 ); // After wp_update_themes() is called. add_action( 'admin_notices', 'update_nag', 3 ); -add_action( 'admin_notices', 'paused_plugins_notice', 5 ); -add_action( 'admin_notices', 'paused_themes_notice', 5 ); add_action( 'admin_notices', 'maintenance_nag', 10 ); add_filter( 'update_footer', 'core_update_footer' ); diff --git a/src/wp-admin/includes/class-wp-plugins-list-table.php b/src/wp-admin/includes/class-wp-plugins-list-table.php index a07945a973..fa40ba9a36 100644 --- a/src/wp-admin/includes/class-wp-plugins-list-table.php +++ b/src/wp-admin/includes/class-wp-plugins-list-table.php @@ -40,7 +40,7 @@ class WP_Plugins_List_Table extends WP_List_Table { ); $status = 'all'; - if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search', 'paused' ) ) ) { + if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search' ) ) ) { $status = $_REQUEST['plugin_status']; } @@ -99,7 +99,6 @@ class WP_Plugins_List_Table extends WP_List_Table { 'upgrade' => array(), 'mustuse' => array(), 'dropins' => array(), - 'paused' => array(), ); $screen = $this->screen; @@ -210,9 +209,6 @@ class WP_Plugins_List_Table extends WP_List_Table { if ( $show_network_active ) { // On the non-network screen, show network-active plugins if allowed $plugins['active'][ $plugin_file ] = $plugin_data; - if ( is_plugin_paused( $plugin_file ) ) { - $plugins['paused'][ $plugin_file ] = $plugin_data; - } } else { // On the non-network screen, filter out network-active plugins unset( $plugins['all'][ $plugin_file ] ); @@ -222,9 +218,6 @@ class WP_Plugins_List_Table extends WP_List_Table { // On the non-network screen, populate the active list with plugins that are individually activated // On the network-admin screen, populate the active list with plugins that are network activated $plugins['active'][ $plugin_file ] = $plugin_data; - if ( is_plugin_paused( $plugin_file ) ) { - $plugins['paused'][ $plugin_file ] = $plugin_data; - } } else { if ( isset( $recently_activated[ $plugin_file ] ) ) { // Populate the recently activated list with plugins that have been recently activated @@ -452,10 +445,6 @@ class WP_Plugins_List_Table extends WP_List_Table { /* translators: %s: plugin count */ $text = _n( 'Drop-ins (%s)', 'Drop-ins (%s)', $count ); break; - case 'paused': - /* translators: %s: plugin count */ - $text = _n( 'Paused (%s)', 'Paused (%s)', $count ); - break; case 'upgrade': /* translators: %s: plugin count */ $text = _n( 'Update Available (%s)', 'Update Available (%s)', $count ); @@ -644,19 +633,11 @@ class WP_Plugins_List_Table extends WP_List_Table { /* translators: %s: plugin name */ $actions['deactivate'] = '' . __( 'Network Deactivate' ) . ''; } - if ( current_user_can( 'manage_network_plugins' ) && count_paused_plugin_sites_for_network( $plugin_file ) ) { - /* translators: %s: plugin name */ - $actions['resume'] = '' . __( 'Network Resume' ) . ''; - } } else { if ( current_user_can( 'manage_network_plugins' ) ) { /* translators: %s: plugin name */ $actions['activate'] = '' . __( 'Network Activate' ) . ''; } - if ( current_user_can( 'manage_network_plugins' ) && count_paused_plugin_sites_for_network( $plugin_file ) ) { - /* translators: %s: plugin name */ - $actions['resume'] = '' . __( 'Network Resume' ) . ''; - } if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) { /* translators: %s: plugin name */ $actions['delete'] = '' . __( 'Delete' ) . ''; @@ -667,10 +648,6 @@ class WP_Plugins_List_Table extends WP_List_Table { $actions = array( 'network_active' => __( 'Network Active' ), ); - if ( ! $restrict_network_only && current_user_can( 'resume_plugin', $plugin_file ) && is_plugin_paused( $plugin_file ) ) { - /* translators: %s: plugin name */ - $actions['resume'] = '' . __( 'Resume' ) . ''; - } } elseif ( $restrict_network_only ) { $actions = array( 'network_only' => __( 'Network Only' ), @@ -680,10 +657,6 @@ class WP_Plugins_List_Table extends WP_List_Table { /* translators: %s: plugin name */ $actions['deactivate'] = '' . __( 'Deactivate' ) . ''; } - if ( current_user_can( 'resume_plugin', $plugin_file ) && is_plugin_paused( $plugin_file ) ) { - /* translators: %s: plugin name */ - $actions['resume'] = '' . __( 'Resume' ) . ''; - } } else { if ( current_user_can( 'activate_plugin', $plugin_file ) ) { /* translators: %s: plugin name */ @@ -791,12 +764,6 @@ class WP_Plugins_List_Table extends WP_List_Table { $class .= ' update'; } - $paused = is_plugin_paused( $plugin_file ); - $paused_on_network_sites_count = $screen->in_admin( 'network' ) ? count_paused_plugin_sites_for_network( $plugin_file ) : 0; - if ( $paused || $paused_on_network_sites_count ) { - $class .= ' paused'; - } - $plugin_slug = isset( $plugin_data['slug'] ) ? $plugin_data['slug'] : sanitize_title( $plugin_name ); printf( '', @@ -878,53 +845,13 @@ class WP_Plugins_List_Table extends WP_List_Table { * @param array $plugin_data An array of plugin data. * @param string $status Status of the plugin. Defaults are 'All', 'Active', * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', - * 'Drop-ins', 'Search', 'Paused'. + * 'Drop-ins', 'Search'. */ $plugin_meta = apply_filters( 'plugin_row_meta', $plugin_meta, $plugin_file, $plugin_data, $status ); echo implode( ' | ', $plugin_meta ); echo ''; - if ( $paused || $paused_on_network_sites_count ) { - $notice_text = __( 'This plugin failed to load properly and was paused within the admin backend.' ); - if ( $screen->in_admin( 'network' ) && $paused_on_network_sites_count ) { - $notice_text = sprintf( - /* translators: %s: number of sites */ - _n( 'This plugin failed to load properly and was paused within the admin backend for %s site.', 'This plugin failed to load properly and was paused within the admin backend for %s sites.', $paused_on_network_sites_count ), - number_format_i18n( $paused_on_network_sites_count ) - ); - } - - printf( '

%s

', $notice_text ); - - $error = wp_get_plugin_error( $plugin_file ); - - if ( false !== $error ) { - $constants = get_defined_constants( true ); - $constants = isset( $constants['Core'] ) ? $constants['Core'] : $constants['internal']; - - foreach ( $constants as $constant => $value ) { - if ( 0 === strpos( $constant, 'E_' ) ) { - $core_errors[ $value ] = $constant; - } - } - - $error['type'] = $core_errors[ $error['type'] ]; - - printf( - '

%s

', - sprintf( - /* translators: 1: error type, 2: error line number, 3: error file name, 4: error message */ - __( 'The plugin caused an error of type %1$s in line %2$s of the file %3$s. Error message: %4$s' ), - "{$error['type']}", - "{$error['line']}", - "{$error['file']}", - "{$error['message']}" - ) - ); - } - } - echo ''; break; default: @@ -958,7 +885,7 @@ class WP_Plugins_List_Table extends WP_List_Table { * @param array $plugin_data An array of plugin data. * @param string $status Status of the plugin. Defaults are 'All', 'Active', * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', - * 'Drop-ins', 'Search', 'Paused'. + * 'Drop-ins', 'Search'. */ do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status ); @@ -974,7 +901,7 @@ class WP_Plugins_List_Table extends WP_List_Table { * @param array $plugin_data An array of plugin data. * @param string $status Status of the plugin. Defaults are 'All', 'Active', * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use', - * 'Drop-ins', 'Search', 'Paused'. + * 'Drop-ins', 'Search'. */ do_action( "after_plugin_row_{$plugin_file}", $plugin_file, $plugin_data, $status ); } diff --git a/src/wp-admin/includes/plugin.php b/src/wp-admin/includes/plugin.php index 05e3861f17..5873a33466 100644 --- a/src/wp-admin/includes/plugin.php +++ b/src/wp-admin/includes/plugin.php @@ -468,14 +468,12 @@ function get_dropins() { */ function _get_dropins() { $dropins = array( - 'advanced-cache.php' => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ), // WP_CACHE - 'db.php' => array( __( 'Custom database class.' ), true ), // auto on load - 'db-error.php' => array( __( 'Custom database error message.' ), true ), // auto on error - 'install.php' => array( __( 'Custom installation script.' ), true ), // auto on installation - 'maintenance.php' => array( __( 'Custom maintenance message.' ), true ), // auto on maintenance - 'object-cache.php' => array( __( 'External object cache.' ), true ), // auto on load - 'php-error.php' => array( __( 'Custom PHP error message.' ), true ), // auto on error - 'fatal-error-handler.php' => array( __( 'Custom PHP fatal error handler.' ), true ), // auto on error + 'advanced-cache.php' => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ), // WP_CACHE + 'db.php' => array( __( 'Custom database class.' ), true ), // auto on load + 'db-error.php' => array( __( 'Custom database error message.' ), true ), // auto on error + 'install.php' => array( __( 'Custom installation script.' ), true ), // auto on installation + 'maintenance.php' => array( __( 'Custom maintenance message.' ), true ), // auto on maintenance + 'object-cache.php' => array( __( 'External object cache.' ), true ), // auto on load ); if ( is_multisite() ) { @@ -528,84 +526,6 @@ function is_plugin_inactive( $plugin ) { return ! is_plugin_active( $plugin ); } -/** - * Determines whether a plugin is technically active but was paused while - * loading. - * - * For more information on this and similar theme functions, check out - * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ - * Conditional Tags} article in the Theme Developer Handbook. - * - * @since 5.1.0 - * - * @param string $plugin Path to the plugin file relative to the plugins directory. - * @return bool True, if in the list of paused plugins. False, not in the list. - */ -function is_plugin_paused( $plugin ) { - if ( ! isset( $GLOBALS['_paused_plugins'] ) ) { - return false; - } - - if ( ! is_plugin_active( $plugin ) && ! is_plugin_active_for_network( $plugin ) ) { - return false; - } - - list( $plugin ) = explode( '/', $plugin ); - - return array_key_exists( $plugin, $GLOBALS['_paused_plugins'] ); -} - -/** - * Gets the error that was recorded for a paused plugin. - * - * @since 5.1.0 - * - * @param string $plugin Path to the plugin file relative to the plugins - * directory. - * @return array|false Array of error information as it was returned by - * `error_get_last()`, or false if none was recorded. - */ -function wp_get_plugin_error( $plugin ) { - if ( ! isset( $GLOBALS['_paused_plugins'] ) ) { - return false; - } - - list( $plugin ) = explode( '/', $plugin ); - - if ( ! array_key_exists( $plugin, $GLOBALS['_paused_plugins'] ) ) { - return false; - } - - return $GLOBALS['_paused_plugins'][ $plugin ]; -} - -/** - * Gets the number of sites on which a specific plugin is paused. - * - * @since 5.1.0 - * - * @param string $plugin Path to the plugin file relative to the plugins directory. - * @return int Site count. - */ -function count_paused_plugin_sites_for_network( $plugin ) { - if ( ! is_multisite() ) { - return is_plugin_paused( $plugin ) ? 1 : 0; - } - - list( $plugin ) = explode( '/', $plugin ); - - $query_args = array( - 'count' => true, - 'number' => 0, - 'network_id' => get_current_network_id(), - 'meta_query' => array( - wp_paused_plugins()->get_site_meta_query_clause( $plugin ), - ), - ); - - return get_sites( $query_args ); -} - /** * Determines whether the plugin is active for the entire network. * @@ -803,11 +723,6 @@ function deactivate_plugins( $plugins, $silent = false, $network_wide = null ) { continue; } - // Clean up the database before deactivating the plugin. - if ( is_plugin_paused( $plugin ) ) { - resume_plugin( $plugin ); - } - $network_deactivating = false !== $network_wide && is_plugin_active_for_network( $plugin ); if ( ! $silent ) { @@ -1002,11 +917,6 @@ function delete_plugins( $plugins, $deprecated = '' ) { uninstall_plugin( $plugin_file ); } - // Clean up the database before removing the plugin. - if ( is_plugin_paused( $plugin_file ) ) { - resume_plugin( $plugin_file ); - } - /** * Fires immediately before a plugin deletion attempt. * @@ -1084,57 +994,6 @@ function delete_plugins( $plugins, $deprecated = '' ) { return true; } -/** - * Tries to resume a single plugin. - * - * If a redirect was provided, we first ensure the plugin does not throw fatal - * errors anymore. - * - * The way it works is by setting the redirection to the error before trying to - * include the plugin file. If the plugin fails, then the redirection will not - * be overwritten with the success message and the plugin will not be resumed. - * - * @since 5.1.0 - * - * @param string $plugin Single plugin to resume. - * @param string $redirect Optional. URL to redirect to. Default empty string. - * @param bool $network_wide Optional. Whether to resume the plugin for the entire - * network. Default false. - * @return bool|WP_Error True on success, false if `$plugin` was not paused, - * `WP_Error` on failure. - */ -function resume_plugin( $plugin, $redirect = '', $network_wide = false ) { - /* - * We'll override this later if the plugin could be included without - * creating a fatal error. - */ - if ( ! empty( $redirect ) ) { - wp_redirect( - add_query_arg( - '_error_nonce', - wp_create_nonce( 'plugin-resume-error_' . $plugin ), - $redirect - ) - ); - - // Load the plugin to test whether it throws a fatal error. - ob_start(); - plugin_sandbox_scrape( $plugin ); - ob_clean(); - } - - $result = wp_forget_extension_error( 'plugins', $plugin, $network_wide ); - - if ( ! $result ) { - return new WP_Error( - 'could_not_resume_plugin', - __( 'Could not resume the plugin.' ) - ); - } - - return true; -} - /** * Validate active plugins * @@ -2242,33 +2101,3 @@ function wp_add_privacy_policy_content( $plugin_name, $policy_text ) { WP_Privacy_Policy_Content::add( $plugin_name, $policy_text ); } - -/** - * Renders an admin notice in case some plugins have been paused due to errors. - * - * @since 5.1.0 - */ -function paused_plugins_notice() { - if ( 'plugins.php' === $GLOBALS['pagenow'] ) { - return; - } - - if ( ! current_user_can( 'deactivate_plugins' ) ) { - return; - } - - if ( ! isset( $GLOBALS['_paused_plugins'] ) || empty( $GLOBALS['_paused_plugins'] ) ) { - return; - } - - printf( - '

%s
%s

%s

', - __( 'One or more plugins failed to load properly.' ), - __( 'You can find more details and make changes on the Plugins screen.' ), - sprintf( - '%s', - admin_url( 'plugins.php?plugin_status=paused' ), - 'Go to the Plugins screen' - ) - ); -} diff --git a/src/wp-admin/includes/theme.php b/src/wp-admin/includes/theme.php index 7c307c33eb..91a3577906 100644 --- a/src/wp-admin/includes/theme.php +++ b/src/wp-admin/includes/theme.php @@ -768,127 +768,3 @@ function customize_themes_print_templates() { true, - 'number' => 0, - 'network_id' => get_current_network_id(), - 'meta_query' => array( - wp_paused_themes()->get_site_meta_query_clause( $theme ), - ), - ); - - return get_sites( $query_args ); -} - -/** - * Tries to resume a single theme. - * - * @since 5.1.0 - * - * @param string $theme Single theme to resume. - * @return bool|WP_Error True on success, false if `$theme` was not paused, - * `WP_Error` on failure. - */ -function resume_theme( $theme ) { - $result = wp_forget_extension_error( 'themes', $theme ); - - if ( ! $result ) { - return new WP_Error( - 'could_not_resume_theme', - __( 'Could not resume the theme.' ) - ); - } - - return true; -} - -/** - * Renders an admin notice in case some themes have been paused due to errors. - * - * @since 5.1.0 - */ -function paused_themes_notice() { - if ( 'themes.php' === $GLOBALS['pagenow'] ) { - return; - } - - if ( ! current_user_can( 'switch_themes' ) ) { - return; - } - - if ( ! isset( $GLOBALS['_paused_themes'] ) || empty( $GLOBALS['_paused_themes'] ) ) { - return; - } - - printf( - '

%s
%s

%s

', - __( 'One or more themes failed to load properly.' ), - __( 'You can find more details and make changes on the Themes screen.' ), - sprintf( - '%s', - admin_url( 'themes.php' ), - 'Go to the Themes screen' - ) - ); -} diff --git a/src/wp-admin/plugins.php b/src/wp-admin/plugins.php index 6c41e31b2f..c80e96831f 100644 --- a/src/wp-admin/plugins.php +++ b/src/wp-admin/plugins.php @@ -389,27 +389,6 @@ if ( $action ) { } break; - case 'resume': - if ( ! current_user_can( 'resume_plugin', $plugin ) ) { - wp_die( __( 'Sorry, you are not allowed to resume this plugin.' ) ); - } - - if ( is_multisite() && ! is_network_admin() && is_network_only_plugin( $plugin ) ) { - wp_redirect( self_admin_url( "plugins.php?plugin_status=$status&paged=$page&s=$s" ) ); - exit; - } - - check_admin_referer( 'resume-plugin_' . $plugin ); - - $result = resume_plugin( $plugin, self_admin_url( 'plugins.php?error=resuming' ), is_network_admin() ); - - if ( is_wp_error( $result ) ) { - wp_die( $result ); - } - - wp_redirect( self_admin_url( "plugins.php?resume=true&plugin_status=$status&paged=$page&s=$s" ) ); - exit; - default: if ( isset( $_POST['checked'] ) ) { check_admin_referer( 'bulk-plugins' ); @@ -509,8 +488,6 @@ if ( isset( $_GET['error'] ) ) : $_GET['charsout'] ); $errmsg .= ' ' . __( 'If you notice “headers already sent” messages, problems with syndication feeds or other issues, try deactivating or removing this plugin.' ); - } elseif ( 'resuming' === $_GET['error'] ) { - $errmsg = __( 'Plugin could not be resumed because it triggered a fatal error.' ); } else { $errmsg = __( 'Plugin could not be activated because it triggered a fatal error.' ); } @@ -564,8 +541,6 @@ elseif ( isset( $_GET['deleted'] ) ) :

deactivated.' ); ?>

- -

resumed.' ); ?>

diff --git a/src/wp-admin/themes.php b/src/wp-admin/themes.php index 754b75808d..494e952184 100644 --- a/src/wp-admin/themes.php +++ b/src/wp-admin/themes.php @@ -33,26 +33,6 @@ if ( current_user_can( 'switch_themes' ) && isset( $_GET['action'] ) ) { switch_theme( $theme->get_stylesheet() ); wp_redirect( admin_url( 'themes.php?activated=true' ) ); exit; - } elseif ( 'resume' === $_GET['action'] ) { - check_admin_referer( 'resume-theme_' . $_GET['stylesheet'] ); - $theme = wp_get_theme( $_GET['stylesheet'] ); - - if ( ! current_user_can( 'resume_themes' ) ) { - wp_die( - '

' . __( 'You need a higher level of permission.' ) . '

' . - '

' . __( 'Sorry, you are not allowed to resume this theme.' ) . '

', - 403 - ); - } - - $result = resume_theme( $theme->get_stylesheet() ); - - if ( is_wp_error( $result ) ) { - wp_die( $result ); - } - - wp_redirect( admin_url( 'themes.php?resumed=true' ) ); - exit; } elseif ( 'delete' == $_GET['action'] ) { check_admin_referer( 'delete-theme_' . $_GET['stylesheet'] ); $theme = wp_get_theme( $_GET['stylesheet'] ); @@ -215,10 +195,6 @@ if ( ! validate_current_theme() || isset( $_GET['broken'] ) ) { ?>

-

-

@@ -380,9 +355,6 @@ if ( ! is_multisite() && current_user_can( 'edit_themes' ) && $broken_themes = w - - - @@ -395,27 +367,6 @@ if ( ! is_multisite() && current_user_can( 'edit_themes' ) && $broken_themes = w get( 'Name' ) ? $broken_theme->display( 'Name' ) : $broken_theme->get_stylesheet(); ?> errors()->get_error_message(); ?> errors()->get_error_code() ) { - $stylesheet = $broken_theme->get_stylesheet(); - $resume_url = add_query_arg( - array( - 'action' => 'resume', - 'stylesheet' => urlencode( $stylesheet ), - ), - admin_url( 'themes.php' ) - ); - $resume_url = wp_nonce_url( $resume_url, 'resume-theme_' . $stylesheet ); - ?> - - - - get_stylesheet(); $delete_url = add_query_arg( diff --git a/src/wp-includes/capabilities.php b/src/wp-includes/capabilities.php index afb6f59507..c192639608 100644 --- a/src/wp-includes/capabilities.php +++ b/src/wp-includes/capabilities.php @@ -464,14 +464,6 @@ function map_meta_cap( $cap, $user_id ) { } } break; - case 'resume_plugin': - // Even in a multisite, regular administrators should be able to resume a plugin. - $caps[] = 'activate_plugins'; - break; - case 'resume_themes': - // Even in a multisite, regular administrators should be able to resume a theme. - $caps[] = 'switch_themes'; - break; case 'delete_user': case 'delete_users': // If multisite only super admins can delete users. diff --git a/src/wp-includes/class-wp-fatal-error-handler.php b/src/wp-includes/class-wp-fatal-error-handler.php deleted file mode 100644 index 0299b67a48..0000000000 --- a/src/wp-includes/class-wp-fatal-error-handler.php +++ /dev/null @@ -1,200 +0,0 @@ -detect_error(); - if ( ! $error ) { - return; - } - - // If the error was stored and thus the extension paused, - // redirect the request to catch multiple errors in one go. - if ( $this->store_error( $error ) ) { - $this->redirect_protected(); - } - - // Display the PHP error template. - $this->display_error_template(); - } catch ( Exception $e ) { - // Catch exceptions and remain silent. - } - } - - /** - * Detects the error causing the crash if it should be handled. - * - * @since 5.1.0 - * - * @return array|null Error that was triggered, or null if no error received or if the error should not be handled. - */ - protected function detect_error() { - $error = error_get_last(); - - // No error, just skip the error handling code. - if ( null === $error ) { - return null; - } - - // Bail if this error should not be handled. - if ( ! wp_should_handle_error( $error ) ) { - return null; - } - - return $error; - } - - /** - * Stores the given error so that the extension causing it is paused. - * - * @since 5.1.0 - * - * @param array $error Error that was triggered. - * @return bool True if the error was stored successfully, false otherwise. - */ - protected function store_error( $error ) { - // Do not pause extensions if they only crash on a non-protected endpoint. - if ( ! is_protected_endpoint() ) { - return false; - } - - return wp_record_extension_error( $error ); - } - - /** - * Redirects the current request to allow recovering multiple errors in one go. - * - * The redirection will only happen when on a protected endpoint. - * - * It must be ensured that this method is only called when an error actually occurred and will not occur on the - * next request again. Otherwise it will create a redirect loop. - * - * @since 5.1.0 - */ - protected function redirect_protected() { - // Do not redirect requests on non-protected endpoints. - if ( ! is_protected_endpoint() ) { - return; - } - - // Pluggable is usually loaded after plugins, so we manually include it here for redirection functionality. - if ( ! function_exists( 'wp_redirect' ) ) { - include ABSPATH . WPINC . '/pluggable.php'; - } - - $scheme = is_ssl() ? 'https://' : 'http://'; - - $url = "{$scheme}{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; - wp_redirect( $url ); - exit; - } - - /** - * Displays the PHP error template and sends the HTTP status code, typically 500. - * - * A drop-in 'php-error.php' can be used as a custom template. This drop-in should control the HTTP status code and - * print the HTML markup indicating that a PHP error occurred. Note that this drop-in may potentially be executed - * very early in the WordPress bootstrap process, so any core functions used that are not part of - * `wp-includes/load.php` should be checked for before being called. - * - * If no such drop-in is available, this will call {@see WP_Fatal_Error_Handler::display_default_error_template()}. - * - * @since 5.1.0 - */ - protected function display_error_template() { - if ( defined( 'WP_CONTENT_DIR' ) ) { - // Load custom PHP error template, if present. - $php_error_pluggable = WP_CONTENT_DIR . '/php-error.php'; - if ( is_readable( $php_error_pluggable ) ) { - require_once $php_error_pluggable; - return; - } - } - - // Otherwise, display the default error template. - $this->display_default_error_template(); - } - - /** - * Displays the default PHP error template. - * - * This method is called conditionally if no 'php-error.php' drop-in is available. - * - * It calls {@see wp_die()} with a message indicating that the site is experiencing technical difficulties and a - * login link to the admin backend. The {@see 'wp_php_error_message'} and {@see 'wp_php_error_args'} filters can - * be used to modify these parameters. - * - * @since 5.1.0 - */ - protected function display_default_error_template() { - if ( ! function_exists( '__' ) ) { - wp_load_translations_early(); - } - - if ( ! function_exists( 'wp_die' ) ) { - require_once ABSPATH . WPINC . '/functions.php'; - } - - $message = __( 'The site is experiencing technical difficulties.' ); - - $args = array( - 'response' => 500, - 'exit' => false, - ); - if ( function_exists( 'admin_url' ) ) { - $args['link_url'] = admin_url(); - $args['link_text'] = __( 'Log into the admin backend to fix this.' ); - } - - /** - * Filters the message that the default PHP error template displays. - * - * @since 5.1.0 - * - * @param string $message HTML error message to display. - */ - $message = apply_filters( 'wp_php_error_message', $message ); - - /** - * Filters the arguments passed to {@see wp_die()} for the default PHP error template. - * - * @since 5.1.0 - * - * @param array $args Associative array of arguments passed to `wp_die()`. By default these contain a - * 'response' key, and optionally 'link_url' and 'link_text' keys. - */ - $args = apply_filters( 'wp_php_error_args', $args ); - - wp_die( $message, '', $args ); - } -} diff --git a/src/wp-includes/class-wp-paused-extensions-storage.php b/src/wp-includes/class-wp-paused-extensions-storage.php deleted file mode 100644 index 37b39d2788..0000000000 --- a/src/wp-includes/class-wp-paused-extensions-storage.php +++ /dev/null @@ -1,221 +0,0 @@ -option_name = $option_name; - $this->meta_prefix = $meta_prefix; - } - - /** - * Records an extension error. - * - * Only one error is stored per extension, with subsequent errors for the same extension overriding the - * previously stored error. - * - * @since 5.1.0 - * - * @param string $extension Plugin or theme directory name. - * @param array $error { - * Error that was triggered. - * - * @type string $type The error type. - * @type string $file The name of the file in which the error occurred. - * @type string $line The line number in which the error occurred. - * @type string $message The error message. - * } - * @return bool True on success, false on failure. - */ - public function record( $extension, $error ) { - if ( ! $this->is_api_loaded() ) { - return false; - } - - if ( is_multisite() && is_site_meta_supported() ) { - // Do not update if the error is already stored. - if ( get_site_meta( get_current_blog_id(), $this->meta_prefix . $extension, true ) === $error ) { - return true; - } - - return (bool) update_site_meta( get_current_blog_id(), $this->meta_prefix . $extension, $error ); - } - - $paused_extensions = $this->get_all(); - - // Do not update if the error is already stored. - if ( isset( $paused_extensions[ $extension ] ) && $paused_extensions[ $extension ] === $error ) { - return true; - } - - $paused_extensions[ $extension ] = $error; - - return update_option( $this->option_name, $paused_extensions ); - } - - /** - * Forgets a previously recorded extension error. - * - * @since 5.1.0 - * - * @param string $extension Plugin or theme directory name. - * @return bool True on success, false on failure. - */ - public function forget( $extension ) { - if ( ! $this->is_api_loaded() ) { - return false; - } - - if ( is_multisite() && is_site_meta_supported() ) { - // Do not delete if no error is stored. - if ( get_site_meta( get_current_blog_id(), $this->meta_prefix . $extension ) === array() ) { - return true; - } - - return (bool) delete_site_meta( get_current_blog_id(), $this->meta_prefix . $extension ); - } - - $paused_extensions = $this->get_all(); - - // Do not delete if no error is stored. - if ( ! isset( $paused_extensions[ $extension ] ) ) { - return true; - } - - // Clean up the entire option if we're removing the only error. - if ( count( $paused_extensions ) === 1 ) { - return delete_option( $this->option_name ); - } - - unset( $paused_extensions[ $extension ] ); - - return update_option( $this->option_name, $paused_extensions ); - } - - /** - * Gets the error for an extension, if paused. - * - * @since 5.1.0 - * - * @param string $extension Plugin or theme directory name. - * @return array|null Error that is stored, or null if the extension is not paused. - */ - public function get( $extension ) { - if ( ! $this->is_api_loaded() ) { - return null; - } - - if ( is_multisite() && is_site_meta_supported() ) { - $error = get_site_meta( get_current_blog_id(), $this->meta_prefix . $extension, true ); - if ( ! $error ) { - return null; - } - - return $error; - } - - $paused_extensions = $this->get_all(); - - if ( ! isset( $paused_extensions[ $extension ] ) ) { - return null; - } - - return $paused_extensions[ $extension ]; - } - - /** - * Gets the paused extensions with their errors. - * - * @since 5.1.0 - * - * @return array Associative array of $extension => $error pairs. - */ - public function get_all() { - if ( ! $this->is_api_loaded() ) { - return array(); - } - - if ( is_multisite() && is_site_meta_supported() ) { - $site_metadata = get_site_meta( get_current_blog_id() ); - - $paused_extensions = array(); - foreach ( $site_metadata as $meta_key => $meta_values ) { - if ( 0 !== strpos( $meta_key, $this->meta_prefix ) ) { - continue; - } - - $error = maybe_unserialize( array_shift( $meta_values ) ); - - $paused_extensions[ substr( $meta_key, strlen( $this->meta_prefix ) ) ] = $error; - } - - return $paused_extensions; - } - - return (array) get_option( $this->option_name, array() ); - } - - /** - * Gets the site meta query clause for querying sites with paused extensions. - * - * @since 5.1.0 - * - * @param string $extension Plugin or theme directory name. - * @return array A single clause to add to a meta query. - */ - public function get_site_meta_query_clause( $extension ) { - return array( - 'key' => $this->meta_prefix . $extension, - 'compare_key' => '=', - ); - } - - /** - * Checks whether the underlying API to store paused extensions is loaded. - * - * @since 5.1.0 - * - * @return bool True if the API is loaded, false otherwise. - */ - protected function is_api_loaded() { - if ( is_multisite() ) { - return function_exists( 'is_site_meta_supported' ) && function_exists( 'get_site_meta' ); - } - - return function_exists( 'get_option' ); - } -} diff --git a/src/wp-includes/class-wp-theme.php b/src/wp-includes/class-wp-theme.php index 0bdd6a43e3..22a5768448 100644 --- a/src/wp-includes/class-wp-theme.php +++ b/src/wp-includes/class-wp-theme.php @@ -371,10 +371,6 @@ final class WP_Theme implements ArrayAccess { $this->parent = new WP_Theme( $this->template, isset( $theme_root_template ) ? $theme_root_template : $this->theme_root, $this ); } - if ( wp_paused_themes()->get( $this->stylesheet ) && ( ! is_wp_error( $this->errors ) || ! isset( $this->errors->errors['theme_paused'] ) ) ) { - $this->errors = new WP_Error( 'theme_paused', __( 'This theme failed to load properly and was paused within the admin backend.' ) ); - } - // We're good. If we didn't retrieve from cache, set it. if ( ! is_array( $cache ) ) { $cache = array( diff --git a/src/wp-includes/error-protection.php b/src/wp-includes/error-protection.php deleted file mode 100644 index c9b5740960..0000000000 --- a/src/wp-includes/error-protection.php +++ /dev/null @@ -1,199 +0,0 @@ -record( $extension, $error ); -} - -/** - * Forgets a previously recorded extension error again. - * - * @since 5.1.0 - * - * @param string $type Type of the extension. - * @param string $extension Relative path of the extension. - * @param bool $network_wide Optional. Whether to resume the plugin for the entire - * network. Default false. - * @return bool Whether the extension error was successfully forgotten. - */ -function wp_forget_extension_error( $type, $extension, $network_wide = false ) { - switch ( $type ) { - case 'plugins': - $callback = 'wp_paused_plugins'; - list( $extension ) = explode( '/', $extension ); - break; - case 'themes': - $callback = 'wp_paused_themes'; - list( $extension ) = explode( '/', $extension ); - break; - } - - if ( empty( $callback ) || empty( $extension ) ) { - return false; - } - - // Handle manually since the regular APIs do not expose this functionality. - if ( $network_wide && is_site_meta_supported() ) { - $site_meta_query_clause = call_user_func( $callback )->get_site_meta_query_clause( $extension ); - return delete_metadata( 'blog', 0, $site_meta_query_clause['key'], '', true ); - } - - return call_user_func( $callback )->forget( $extension ); -} - -/** - * Determines whether we are dealing with an error that WordPress should handle - * in order to protect the admin backend against WSODs. - * - * @param array $error Error information retrieved from error_get_last(). - * - * @return bool Whether WordPress should handle this error. - */ -function wp_should_handle_error( $error ) { - if ( ! isset( $error['type'] ) ) { - return false; - } - - $error_types_to_handle = array( - E_ERROR, - E_PARSE, - E_USER_ERROR, - E_COMPILE_ERROR, - E_RECOVERABLE_ERROR, - ); - - return in_array( $error['type'], $error_types_to_handle, true ); -} - -/** - * Registers the shutdown handler for fatal errors. - * - * The handler will only be registered if {@see wp_is_fatal_error_handler_enabled()} returns true. - * - * @since 5.1.0 - */ -function wp_register_fatal_error_handler() { - if ( ! wp_is_fatal_error_handler_enabled() ) { - return; - } - - $handler = null; - if ( defined( 'WP_CONTENT_DIR' ) && is_readable( WP_CONTENT_DIR . '/fatal-error-handler.php' ) ) { - $handler = include WP_CONTENT_DIR . '/fatal-error-handler.php'; - } - - if ( ! is_object( $handler ) || ! is_callable( array( $handler, 'handle' ) ) ) { - $handler = new WP_Fatal_Error_Handler(); - } - - register_shutdown_function( array( $handler, 'handle' ) ); -} - -/** - * Checks whether the fatal error handler is enabled. - * - * A constant `WP_DISABLE_FATAL_ERROR_HANDLER` can be set in `wp-config.php` to disable it, or alternatively the - * {@see 'wp_fatal_error_handler_enabled'} filter can be used to modify the return value. - * - * @since 5.1.0 - * - * @return bool True if the fatal error handler is enabled, false otherwise. - */ -function wp_is_fatal_error_handler_enabled() { - $enabled = ! defined( 'WP_DISABLE_FATAL_ERROR_HANDLER' ) || ! WP_DISABLE_FATAL_ERROR_HANDLER; - - /** - * Filters whether the fatal error handler is enabled. - * - * @since 5.1.0 - * - * @param bool $enabled True if the fatal error handler is enabled, false otherwise. - */ - return apply_filters( 'wp_fatal_error_handler_enabled', $enabled ); -} diff --git a/src/wp-includes/load.php b/src/wp-includes/load.php index 7fe5566e7e..245ecb1e61 100644 --- a/src/wp-includes/load.php +++ b/src/wp-includes/load.php @@ -697,43 +697,6 @@ function wp_get_active_and_valid_plugins() { } } - /* - * Remove plugins from the list of active plugins when we're on an endpoint - * that should be protected against WSODs and the plugin is paused. - */ - if ( is_protected_endpoint() ) { - $plugins = wp_skip_paused_plugins( $plugins ); - } - - return $plugins; -} - -/** - * Filters a given list of plugins, removing any paused plugins from it. - * - * @since 5.1.0 - * - * @param array $plugins List of absolute plugin main file paths. - * @return array Filtered value of $plugins, without any paused plugins. - */ -function wp_skip_paused_plugins( array $plugins ) { - $paused_plugins = wp_paused_plugins()->get_all(); - - if ( empty( $paused_plugins ) ) { - return $plugins; - } - - foreach ( $plugins as $index => $plugin ) { - list( $plugin ) = explode( '/', plugin_basename( $plugin ) ); - - if ( array_key_exists( $plugin, $paused_plugins ) ) { - unset( $plugins[ $index ] ); - - // Store list of paused plugins for displaying an admin notice. - $GLOBALS['_paused_plugins'][ $plugin ] = $paused_plugins[ $plugin ]; - } - } - return $plugins; } @@ -762,48 +725,6 @@ function wp_get_active_and_valid_themes() { $themes[] = TEMPLATEPATH; - /* - * Remove themes from the list of active themes when we're on an endpoint - * that should be protected against WSODs and the theme is paused. - */ - if ( is_protected_endpoint() ) { - $themes = wp_skip_paused_themes( $themes ); - - // If no active and valid themes exist, skip loading themes. - if ( empty( $themes ) ) { - add_filter( 'wp_using_themes', '__return_false' ); - } - } - - return $themes; -} - -/** - * Filters a given list of themes, removing any paused themes from it. - * - * @since 5.1.0 - * - * @param array $themes List of absolute theme directory paths. - * @return array Filtered value of $themes, without any paused themes. - */ -function wp_skip_paused_themes( array $themes ) { - $paused_themes = wp_paused_themes()->get_all(); - - if ( empty( $paused_themes ) ) { - return $themes; - } - - foreach ( $themes as $index => $theme ) { - $theme = basename( $theme ); - - if ( array_key_exists( $theme, $paused_themes ) ) { - unset( $themes[ $index ] ); - - // Store list of paused themes for displaying an admin notice. - $GLOBALS['_paused_themes'][ $theme ] = $paused_themes[ $theme ]; - } - } - return $themes; } @@ -1289,88 +1210,6 @@ function wp_using_themes() { return apply_filters( 'wp_using_themes', defined( 'WP_USE_THEMES' ) && WP_USE_THEMES ); } -/** - * Determines whether we are currently on an endpoint that should be protected against WSODs. - * - * @since 5.1.0 - * - * @return bool True if the current endpoint should be protected. - */ -function is_protected_endpoint() { - // Protect login pages. - if ( isset( $GLOBALS['pagenow'] ) && 'wp-login.php' === $GLOBALS['pagenow'] ) { - return true; - } - - // Protect the admin backend. - if ( is_admin() && ! wp_doing_ajax() ) { - return true; - } - - // Protect AJAX actions that could help resolve a fatal error should be available. - if ( is_protected_ajax_action() ) { - return true; - } - - /** - * Filters whether the current request is against a protected endpoint. - * - * This filter is only fired when an endpoint is requested which is not already protected by - * WordPress core. As such, it exclusively allows providing further protected endpoints in - * addition to the admin backend, login pages and protected AJAX actions. - * - * @since 5.1.0 - * - * @param bool $is_protected_endpoint Whether the currently requested endpoint is protected. Default false. - */ - return (bool) apply_filters( 'is_protected_endpoint', false ); -} - -/** - * Determines whether we are currently handling an AJAX action that should be protected against WSODs. - * - * @since 5.1.0 - * - * @return bool True if the current AJAX action should be protected. - */ -function is_protected_ajax_action() { - if ( ! wp_doing_ajax() ) { - return false; - } - - if ( ! isset( $_REQUEST['action'] ) ) { - return false; - } - - $actions_to_protect = array( - 'edit-theme-plugin-file', // Saving changes in the core code editor. - 'heartbeat', // Keep the heart beating. - 'install-plugin', // Installing a new plugin. - 'install-theme', // Installing a new theme. - 'search-plugins', // Searching in the list of plugins. - 'search-install-plugins', // Searching for a plugin in the plugin install screen. - 'update-plugin', // Update an existing plugin. - 'update-theme', // Update an existing theme. - ); - - /** - * Filters the array of protected AJAX actions. - * - * This filter is only fired when doing AJAX and the AJAX request has an 'action' property. - * - * @since 5.1.0 - * - * @param array $actions_to_protect Array of strings with AJAX actions to protect. - */ - $actions_to_protect = (array) apply_filters( 'wp_protected_ajax_actions', $actions_to_protect ); - - if ( ! in_array( $_REQUEST['action'], $actions_to_protect, true ) ) { - return false; - } - - return true; -} - /** * Determines whether the current request is a WordPress cron request. * diff --git a/src/wp-includes/ms-load.php b/src/wp-includes/ms-load.php index 4f630cce27..91c9c8c301 100644 --- a/src/wp-includes/ms-load.php +++ b/src/wp-includes/ms-load.php @@ -53,14 +53,6 @@ function wp_get_active_network_plugins() { } } - /* - * Remove plugins from the list of active plugins when we're on an endpoint - * that should be protected against WSODs and the plugin is paused. - */ - if ( is_protected_endpoint() ) { - $plugins = wp_skip_paused_plugins( $plugins ); - } - return $plugins; } diff --git a/src/wp-settings.php b/src/wp-settings.php index e48208beb6..b54d6f39d9 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -17,15 +17,9 @@ define( 'WPINC', 'wp-includes' ); // Include files required for initialization. require( ABSPATH . WPINC . '/load.php' ); -require( ABSPATH . WPINC . '/class-wp-paused-extensions-storage.php' ); -require( ABSPATH . WPINC . '/class-wp-fatal-error-handler.php' ); -require( ABSPATH . WPINC . '/error-protection.php' ); require( ABSPATH . WPINC . '/default-constants.php' ); require_once( ABSPATH . WPINC . '/plugin.php' ); -// Make sure we register the shutdown handler for fatal errors as soon as possible. -wp_register_fatal_error_handler(); - /* * These can't be directly globalized in version.php. When updating, * we're including version.php from another installation and don't want @@ -530,12 +524,3 @@ if ( is_multisite() ) { * @since 3.0.0 */ do_action( 'wp_loaded' ); - -/* - * Store the fact that we could successfully execute the entire WordPress - * lifecycle. This is used to skip the premature shutdown handler, as it cannot - * be unregistered. - */ -if ( ! defined( 'WP_EXECUTION_SUCCEEDED' ) ) { - define( 'WP_EXECUTION_SUCCEEDED', true ); -} diff --git a/tests/phpunit/tests/user/capabilities.php b/tests/phpunit/tests/user/capabilities.php index 69742c3972..3bc5264d52 100644 --- a/tests/phpunit/tests/user/capabilities.php +++ b/tests/phpunit/tests/user/capabilities.php @@ -257,7 +257,6 @@ class Tests_User_Capabilities extends WP_UnitTestCase { 'export_others_personal_data' => array( 'administrator' ), 'erase_others_personal_data' => array( 'administrator' ), 'manage_privacy_options' => array( 'administrator' ), - 'resume_themes' => array( 'administrator' ), 'edit_categories' => array( 'administrator', 'editor' ), 'delete_categories' => array( 'administrator', 'editor' ), @@ -297,7 +296,6 @@ class Tests_User_Capabilities extends WP_UnitTestCase { 'customize' => array( 'administrator' ), 'delete_site' => array( 'administrator' ), 'add_users' => array( 'administrator' ), - 'resume_themes' => array( 'administrator' ), 'edit_categories' => array( 'administrator', 'editor' ), 'delete_categories' => array( 'administrator', 'editor' ), @@ -456,7 +454,6 @@ class Tests_User_Capabilities extends WP_UnitTestCase { // Singular object meta capabilities (where an object ID is passed) are not tested: $expected['activate_plugin'], $expected['deactivate_plugin'], - $expected['resume_plugin'], $expected['remove_user'], $expected['promote_user'], $expected['edit_user'],