Bootstrap/Load: Introduce fatal error handler.
This changeset introduces a `WP_Fatal_Error_Handler` class that detects fatal errors and displays a more user-friendly message about the site experiencing technical difficulties.
Websites that have custom requirements in that regard can implement their own fatal error handler by adding a `fatal-error-handler.php` drop-in that returns the handler instance to use, which must be based on a class that inherits `WP_Fatal_Error_Handler`. That handler will then be used in place of the default one. Alternatively, the fatal error handler feature can be completely disable through a constant `WP_DISABLE_FATAL_ERROR_HANDLER`.
Websites that would like to modify specifically the error template displayed in the frontend can add a `php-error.php` drop-in that works similarly to the existing `db-error.php` drop-in. For more granular customization, the fatal error handler also includes new filters `wp_should_handle_php_error`, `wp_php_error_message` and `wp_php_error_args`.
Props afragen, bradleyt, flixos90, ocean90, schlessera, SergeyBiryukov, spacedmonkey, timothyblynjacobs.
See #46130, #44458.
Built from https://develop.svn.wordpress.org/trunk@44962
git-svn-id: http://core.svn.wordpress.org/trunk@44793 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-03-21 12:03:51 -04:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Error Protection API: Functions
|
|
|
|
*
|
|
|
|
* @package WordPress
|
|
|
|
* @since 5.2.0
|
|
|
|
*/
|
|
|
|
|
Bootstrap/Load: Introduce a recovery mode for fixing fatal errors.
Using the new fatal handler introduced in [44962], an email is sent to the admin when a fatal error occurs. This email includes a secret link to enter recovery mode. When clicked, the link will be validated and on success a cookie will be placed on the client, enabling recovery mode for that user. This functionality is executed early before plugins and themes are loaded, in order to be unaffected by potential fatal errors these might be causing.
When in recovery mode, broken plugins and themes will be paused for that client, so that they are able to access the admin backend despite of these errors. They are notified about the broken extensions and the errors caused, and can then decide whether they would like to temporarily deactivate the extension or fix the problem and resume the extension.
A link in the admin bar allows the client to exit recovery mode.
Props timothyblynjacobs, afragen, flixos90, nerrad, miss_jwo, schlessera, spacedmonkey, swissspidy.
Fixes #46130, #44458.
Built from https://develop.svn.wordpress.org/trunk@44973
git-svn-id: http://core.svn.wordpress.org/trunk@44804 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-03-21 17:53:51 -04:00
|
|
|
/**
|
|
|
|
* Get the instance for storing paused plugins.
|
|
|
|
*
|
|
|
|
* @return WP_Paused_Extensions_Storage
|
|
|
|
*/
|
|
|
|
function wp_paused_plugins() {
|
|
|
|
static $storage = null;
|
|
|
|
|
|
|
|
if ( null === $storage ) {
|
|
|
|
$storage = new WP_Paused_Extensions_Storage( 'plugin' );
|
|
|
|
}
|
|
|
|
|
|
|
|
return $storage;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the instance for storing paused extensions.
|
|
|
|
*
|
|
|
|
* @return WP_Paused_Extensions_Storage
|
|
|
|
*/
|
|
|
|
function wp_paused_themes() {
|
|
|
|
static $storage = null;
|
|
|
|
|
|
|
|
if ( null === $storage ) {
|
|
|
|
$storage = new WP_Paused_Extensions_Storage( 'theme' );
|
|
|
|
}
|
|
|
|
|
|
|
|
return $storage;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a human readable description of an extension's error.
|
|
|
|
*
|
|
|
|
* @since 5.2.0
|
|
|
|
*
|
|
|
|
* @param array $error Error details {@see error_get_last()}
|
|
|
|
*
|
|
|
|
* @return string Formatted error description.
|
|
|
|
*/
|
|
|
|
function wp_get_extension_error_description( $error ) {
|
|
|
|
$constants = get_defined_constants( true );
|
|
|
|
$constants = isset( $constants['Core'] ) ? $constants['Core'] : $constants['internal'];
|
|
|
|
$core_errors = array();
|
|
|
|
|
|
|
|
foreach ( $constants as $constant => $value ) {
|
|
|
|
if ( 0 === strpos( $constant, 'E_' ) ) {
|
|
|
|
$core_errors[ $value ] = $constant;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( isset( $core_errors[ $error['type'] ] ) ) {
|
|
|
|
$error['type'] = $core_errors[ $error['type'] ];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* translators: 1: error type, 2: error line number, 3: error file name, 4: error message */
|
|
|
|
$error_message = __( 'An error of type %1$s was caused in line %2$s of the file %3$s. Error message: %4$s' );
|
|
|
|
|
|
|
|
return sprintf(
|
|
|
|
$error_message,
|
|
|
|
"<code>{$error['type']}</code>",
|
|
|
|
"<code>{$error['line']}</code>",
|
|
|
|
"<code>{$error['file']}</code>",
|
|
|
|
"<code>{$error['message']}</code>"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
Bootstrap/Load: Introduce fatal error handler.
This changeset introduces a `WP_Fatal_Error_Handler` class that detects fatal errors and displays a more user-friendly message about the site experiencing technical difficulties.
Websites that have custom requirements in that regard can implement their own fatal error handler by adding a `fatal-error-handler.php` drop-in that returns the handler instance to use, which must be based on a class that inherits `WP_Fatal_Error_Handler`. That handler will then be used in place of the default one. Alternatively, the fatal error handler feature can be completely disable through a constant `WP_DISABLE_FATAL_ERROR_HANDLER`.
Websites that would like to modify specifically the error template displayed in the frontend can add a `php-error.php` drop-in that works similarly to the existing `db-error.php` drop-in. For more granular customization, the fatal error handler also includes new filters `wp_should_handle_php_error`, `wp_php_error_message` and `wp_php_error_args`.
Props afragen, bradleyt, flixos90, ocean90, schlessera, SergeyBiryukov, spacedmonkey, timothyblynjacobs.
See #46130, #44458.
Built from https://develop.svn.wordpress.org/trunk@44962
git-svn-id: http://core.svn.wordpress.org/trunk@44793 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-03-21 12:03:51 -04:00
|
|
|
/**
|
|
|
|
* 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.2.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.2.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.2.0
|
|
|
|
*
|
|
|
|
* @param bool $enabled True if the fatal error handler is enabled, false otherwise.
|
|
|
|
*/
|
|
|
|
return apply_filters( 'wp_fatal_error_handler_enabled', $enabled );
|
|
|
|
}
|
Bootstrap/Load: Introduce a recovery mode for fixing fatal errors.
Using the new fatal handler introduced in [44962], an email is sent to the admin when a fatal error occurs. This email includes a secret link to enter recovery mode. When clicked, the link will be validated and on success a cookie will be placed on the client, enabling recovery mode for that user. This functionality is executed early before plugins and themes are loaded, in order to be unaffected by potential fatal errors these might be causing.
When in recovery mode, broken plugins and themes will be paused for that client, so that they are able to access the admin backend despite of these errors. They are notified about the broken extensions and the errors caused, and can then decide whether they would like to temporarily deactivate the extension or fix the problem and resume the extension.
A link in the admin bar allows the client to exit recovery mode.
Props timothyblynjacobs, afragen, flixos90, nerrad, miss_jwo, schlessera, spacedmonkey, swissspidy.
Fixes #46130, #44458.
Built from https://develop.svn.wordpress.org/trunk@44973
git-svn-id: http://core.svn.wordpress.org/trunk@44804 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2019-03-21 17:53:51 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Access the WordPress Recovery Mode instance.
|
|
|
|
*
|
|
|
|
* @since 5.2.0
|
|
|
|
*
|
|
|
|
* @return WP_Recovery_Mode
|
|
|
|
*/
|
|
|
|
function wp_recovery_mode() {
|
|
|
|
static $wp_recovery_mode;
|
|
|
|
|
|
|
|
if ( ! $wp_recovery_mode ) {
|
|
|
|
$wp_recovery_mode = new WP_Recovery_Mode();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $wp_recovery_mode;
|
|
|
|
}
|