[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> class-wp-fatal-error-handler.php (source)

   1  <?php
   2  /**
   3   * Error Protection API: WP_Fatal_Error_Handler class
   4   *
   5   * @package WordPress
   6   * @since   5.2.0
   7   */
   8  
   9  /**
  10   * Core class used as the default shutdown handler for fatal errors.
  11   *
  12   * A drop-in 'fatal-error-handler.php' can be used to override the instance of this class and use a custom
  13   * implementation for the fatal error handler that WordPress registers. The custom class should extend this class and
  14   * can override its methods individually as necessary. The file must return the instance of the class that should be
  15   * registered.
  16   *
  17   * @since 5.2.0
  18   */
  19  class WP_Fatal_Error_Handler {
  20  
  21      /**
  22       * Runs the shutdown handler.
  23       *
  24       * This method is registered via `register_shutdown_function()`.
  25       *
  26       * @since 5.2.0
  27       */
  28  	public function handle() {
  29          if ( defined( 'WP_SANDBOX_SCRAPING' ) && WP_SANDBOX_SCRAPING ) {
  30              return;
  31          }
  32  
  33          try {
  34              // Bail if no error found.
  35              $error = $this->detect_error();
  36              if ( ! $error ) {
  37                  return;
  38              }
  39  
  40              if ( ! isset( $GLOBALS['wp_locale'] ) && function_exists( 'load_default_textdomain' ) ) {
  41                  load_default_textdomain();
  42              }
  43  
  44              $handled = false;
  45  
  46              if ( ! is_multisite() && wp_recovery_mode()->is_initialized() ) {
  47                  $handled = wp_recovery_mode()->handle_error( $error );
  48              }
  49  
  50              // Display the PHP error template if headers not sent.
  51              if ( is_admin() || ! headers_sent() ) {
  52                  $this->display_error_template( $error, $handled );
  53              }
  54          } catch ( Exception $e ) {
  55              // Catch exceptions and remain silent.
  56          }
  57      }
  58  
  59      /**
  60       * Detects the error causing the crash if it should be handled.
  61       *
  62       * @since 5.2.0
  63       *
  64       * @return array|null Error that was triggered, or null if no error received or if the error should not be handled.
  65       */
  66  	protected function detect_error() {
  67          $error = error_get_last();
  68  
  69          // No error, just skip the error handling code.
  70          if ( null === $error ) {
  71              return null;
  72          }
  73  
  74          // Bail if this error should not be handled.
  75          if ( ! $this->should_handle_error( $error ) ) {
  76              return null;
  77          }
  78  
  79          return $error;
  80      }
  81  
  82      /**
  83       * Determines whether we are dealing with an error that WordPress should handle
  84       * in order to protect the admin backend against WSODs.
  85       *
  86       * @since 5.2.0
  87       *
  88       * @param array $error Error information retrieved from error_get_last().
  89       * @return bool Whether WordPress should handle this error.
  90       */
  91  	protected function should_handle_error( $error ) {
  92          $error_types_to_handle = array(
  93              E_ERROR,
  94              E_PARSE,
  95              E_USER_ERROR,
  96              E_COMPILE_ERROR,
  97              E_RECOVERABLE_ERROR,
  98          );
  99  
 100          if ( isset( $error['type'] ) && in_array( $error['type'], $error_types_to_handle, true ) ) {
 101              return true;
 102          }
 103  
 104          /**
 105           * Filters whether a given thrown error should be handled by the fatal error handler.
 106           *
 107           * This filter is only fired if the error is not already configured to be handled by WordPress core. As such,
 108           * it exclusively allows adding further rules for which errors should be handled, but not removing existing
 109           * ones.
 110           *
 111           * @since 5.2.0
 112           *
 113           * @param bool  $should_handle_error Whether the error should be handled by the fatal error handler.
 114           * @param array $error               Error information retrieved from error_get_last().
 115           */
 116          return (bool) apply_filters( 'wp_should_handle_php_error', false, $error );
 117      }
 118  
 119      /**
 120       * Displays the PHP error template and sends the HTTP status code, typically 500.
 121       *
 122       * A drop-in 'php-error.php' can be used as a custom template. This drop-in should control the HTTP status code and
 123       * print the HTML markup indicating that a PHP error occurred. Note that this drop-in may potentially be executed
 124       * very early in the WordPress bootstrap process, so any core functions used that are not part of
 125       * `wp-includes/load.php` should be checked for before being called.
 126       *
 127       * If no such drop-in is available, this will call {@see WP_Fatal_Error_Handler::display_default_error_template()}.
 128       *
 129       * @since 5.2.0
 130       * @since 5.3.0 The `$handled` parameter was added.
 131       *
 132       * @param array         $error   Error information retrieved from `error_get_last()`.
 133       * @param true|WP_Error $handled Whether Recovery Mode handled the fatal error.
 134       */
 135  	protected function display_error_template( $error, $handled ) {
 136          if ( defined( 'WP_CONTENT_DIR' ) ) {
 137              // Load custom PHP error template, if present.
 138              $php_error_pluggable = WP_CONTENT_DIR . '/php-error.php';
 139              if ( is_readable( $php_error_pluggable ) ) {
 140                  require_once $php_error_pluggable;
 141  
 142                  return;
 143              }
 144          }
 145  
 146          // Otherwise, display the default error template.
 147          $this->display_default_error_template( $error, $handled );
 148      }
 149  
 150      /**
 151       * Displays the default PHP error template.
 152       *
 153       * This method is called conditionally if no 'php-error.php' drop-in is available.
 154       *
 155       * It calls {@see wp_die()} with a message indicating that the site is experiencing technical difficulties and a
 156       * login link to the admin backend. The {@see 'wp_php_error_message'} and {@see 'wp_php_error_args'} filters can
 157       * be used to modify these parameters.
 158       *
 159       * @since 5.2.0
 160       * @since 5.3.0 The `$handled` parameter was added.
 161       *
 162       * @param array         $error   Error information retrieved from `error_get_last()`.
 163       * @param true|WP_Error $handled Whether Recovery Mode handled the fatal error.
 164       */
 165  	protected function display_default_error_template( $error, $handled ) {
 166          if ( ! function_exists( '__' ) ) {
 167              wp_load_translations_early();
 168          }
 169  
 170          if ( ! function_exists( 'wp_die' ) ) {
 171              require_once  ABSPATH . WPINC . '/functions.php';
 172          }
 173  
 174          if ( ! class_exists( 'WP_Error' ) ) {
 175              require_once  ABSPATH . WPINC . '/class-wp-error.php';
 176          }
 177  
 178          if ( true === $handled && wp_is_recovery_mode() ) {
 179              $message = __( 'There has been a critical error on your website, putting it in recovery mode. Please check the Themes and Plugins screens for more details. If you just installed or updated a theme or plugin, check the relevant page for that first.' );
 180          } elseif ( is_protected_endpoint() ) {
 181              $message = __( 'There has been a critical error on your website. Please check your site admin email inbox for instructions.' );
 182          } else {
 183              $message = __( 'There has been a critical error on your website.' );
 184          }
 185  
 186          $message = sprintf(
 187              '<p>%s</p><p><a href="%s">%s</a></p>',
 188              $message,
 189              /* translators: Documentation explaining debugging in WordPress. */
 190              esc_url( __( 'https://wordpress.org/support/article/debugging-in-wordpress/' ) ),
 191              __( 'Learn more about debugging in WordPress.' )
 192          );
 193  
 194          $args = array(
 195              'response' => 500,
 196              'exit'     => false,
 197          );
 198  
 199          /**
 200           * Filters the message that the default PHP error template displays.
 201           *
 202           * @since 5.2.0
 203           *
 204           * @param string $message HTML error message to display.
 205           * @param array  $error   Error information retrieved from `error_get_last()`.
 206           */
 207          $message = apply_filters( 'wp_php_error_message', $message, $error );
 208  
 209          /**
 210           * Filters the arguments passed to {@see wp_die()} for the default PHP error template.
 211           *
 212           * @since 5.2.0
 213           *
 214           * @param array $args Associative array of arguments passed to `wp_die()`. By default these contain a
 215           *                    'response' key, and optionally 'link_url' and 'link_text' keys.
 216           * @param array $error Error information retrieved from `error_get_last()`.
 217           */
 218          $args = apply_filters( 'wp_php_error_args', $args, $error );
 219  
 220          $wp_error = new WP_Error(
 221              'internal_server_error',
 222              $message,
 223              array(
 224                  'error' => $error,
 225              )
 226          );
 227  
 228          wp_die( $wp_error, '', $args );
 229      }
 230  }


Generated: Sun Nov 17 01:00:03 2019 Cross-referenced by PHPXref 0.7.1