[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

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


Generated : Sun Jun 7 08:20:01 2020 Cross-referenced by PHPXref