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


Generated : Tue Mar 19 08:20:01 2024 Cross-referenced by PHPXref