wp/wp-includes/class-wp-fatal-error-handler.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
     1 <?php
     1 <?php
     2 /**
     2 /**
     3  * Error Protection API: WP_Fatal_Error_Handler class
     3  * Error Protection API: WP_Fatal_Error_Handler class
     4  *
     4  *
     5  * @package WordPress
     5  * @package WordPress
     6  * @since   5.2.0
     6  * @since 5.2.0
     7  */
     7  */
     8 
     8 
     9 /**
     9 /**
    10  * Core class used as the default shutdown handler for fatal errors.
    10  * Core class used as the default shutdown handler for fatal errors.
    11  *
    11  *
    28 	public function handle() {
    28 	public function handle() {
    29 		if ( defined( 'WP_SANDBOX_SCRAPING' ) && WP_SANDBOX_SCRAPING ) {
    29 		if ( defined( 'WP_SANDBOX_SCRAPING' ) && WP_SANDBOX_SCRAPING ) {
    30 			return;
    30 			return;
    31 		}
    31 		}
    32 
    32 
       
    33 		// Do not trigger the fatal error handler while updates are being installed.
       
    34 		if ( wp_is_maintenance_mode() ) {
       
    35 			return;
       
    36 		}
       
    37 
    33 		try {
    38 		try {
    34 			// Bail if no error found.
    39 			// Bail if no error found.
    35 			$error = $this->detect_error();
    40 			$error = $this->detect_error();
    36 			if ( ! $error ) {
    41 			if ( ! $error ) {
    37 				return;
    42 				return;
    39 
    44 
    40 			if ( ! isset( $GLOBALS['wp_locale'] ) && function_exists( 'load_default_textdomain' ) ) {
    45 			if ( ! isset( $GLOBALS['wp_locale'] ) && function_exists( 'load_default_textdomain' ) ) {
    41 				load_default_textdomain();
    46 				load_default_textdomain();
    42 			}
    47 			}
    43 
    48 
       
    49 			$handled = false;
       
    50 
    44 			if ( ! is_multisite() && wp_recovery_mode()->is_initialized() ) {
    51 			if ( ! is_multisite() && wp_recovery_mode()->is_initialized() ) {
    45 				wp_recovery_mode()->handle_error( $error );
    52 				$handled = wp_recovery_mode()->handle_error( $error );
    46 			}
    53 			}
    47 
    54 
    48 			// Display the PHP error template if headers not sent.
    55 			// Display the PHP error template if headers not sent.
    49 			if ( is_admin() || ! headers_sent() ) {
    56 			if ( is_admin() || ! headers_sent() ) {
    50 				$this->display_error_template( $error );
    57 				$this->display_error_template( $error, $handled );
    51 			}
    58 			}
    52 		} catch ( Exception $e ) {
    59 		} catch ( Exception $e ) {
    53 			// Catch exceptions and remain silent.
    60 			// Catch exceptions and remain silent.
    54 		}
    61 		}
    55 	}
    62 	}
   123 	 * `wp-includes/load.php` should be checked for before being called.
   130 	 * `wp-includes/load.php` should be checked for before being called.
   124 	 *
   131 	 *
   125 	 * If no such drop-in is available, this will call {@see WP_Fatal_Error_Handler::display_default_error_template()}.
   132 	 * If no such drop-in is available, this will call {@see WP_Fatal_Error_Handler::display_default_error_template()}.
   126 	 *
   133 	 *
   127 	 * @since 5.2.0
   134 	 * @since 5.2.0
   128 	 *
   135 	 * @since 5.3.0 The `$handled` parameter was added.
   129 	 * @param array $error Error information retrieved from `error_get_last()`.
   136 	 *
   130 	 */
   137 	 * @param array         $error   Error information retrieved from `error_get_last()`.
   131 	protected function display_error_template( $error ) {
   138 	 * @param true|WP_Error $handled Whether Recovery Mode handled the fatal error.
       
   139 	 */
       
   140 	protected function display_error_template( $error, $handled ) {
   132 		if ( defined( 'WP_CONTENT_DIR' ) ) {
   141 		if ( defined( 'WP_CONTENT_DIR' ) ) {
   133 			// Load custom PHP error template, if present.
   142 			// Load custom PHP error template, if present.
   134 			$php_error_pluggable = WP_CONTENT_DIR . '/php-error.php';
   143 			$php_error_pluggable = WP_CONTENT_DIR . '/php-error.php';
   135 			if ( is_readable( $php_error_pluggable ) ) {
   144 			if ( is_readable( $php_error_pluggable ) ) {
   136 				require_once $php_error_pluggable;
   145 				require_once $php_error_pluggable;
   138 				return;
   147 				return;
   139 			}
   148 			}
   140 		}
   149 		}
   141 
   150 
   142 		// Otherwise, display the default error template.
   151 		// Otherwise, display the default error template.
   143 		$this->display_default_error_template( $error );
   152 		$this->display_default_error_template( $error, $handled );
   144 	}
   153 	}
   145 
   154 
   146 	/**
   155 	/**
   147 	 * Displays the default PHP error template.
   156 	 * Displays the default PHP error template.
   148 	 *
   157 	 *
   151 	 * It calls {@see wp_die()} with a message indicating that the site is experiencing technical difficulties and a
   160 	 * It calls {@see wp_die()} with a message indicating that the site is experiencing technical difficulties and a
   152 	 * login link to the admin backend. The {@see 'wp_php_error_message'} and {@see 'wp_php_error_args'} filters can
   161 	 * login link to the admin backend. The {@see 'wp_php_error_message'} and {@see 'wp_php_error_args'} filters can
   153 	 * be used to modify these parameters.
   162 	 * be used to modify these parameters.
   154 	 *
   163 	 *
   155 	 * @since 5.2.0
   164 	 * @since 5.2.0
   156 	 *
   165 	 * @since 5.3.0 The `$handled` parameter was added.
   157 	 * @param array $error Error information retrieved from `error_get_last()`.
   166 	 *
   158 	 */
   167 	 * @param array         $error   Error information retrieved from `error_get_last()`.
   159 	protected function display_default_error_template( $error ) {
   168 	 * @param true|WP_Error $handled Whether Recovery Mode handled the fatal error.
       
   169 	 */
       
   170 	protected function display_default_error_template( $error, $handled ) {
   160 		if ( ! function_exists( '__' ) ) {
   171 		if ( ! function_exists( '__' ) ) {
   161 			wp_load_translations_early();
   172 			wp_load_translations_early();
   162 		}
   173 		}
   163 
   174 
   164 		if ( ! function_exists( 'wp_die' ) ) {
   175 		if ( ! function_exists( 'wp_die' ) ) {
   167 
   178 
   168 		if ( ! class_exists( 'WP_Error' ) ) {
   179 		if ( ! class_exists( 'WP_Error' ) ) {
   169 			require_once ABSPATH . WPINC . '/class-wp-error.php';
   180 			require_once ABSPATH . WPINC . '/class-wp-error.php';
   170 		}
   181 		}
   171 
   182 
   172 		if ( is_protected_endpoint() ) {
   183 		if ( true === $handled && wp_is_recovery_mode() ) {
   173 			$message = __( 'The site is experiencing technical difficulties. Please check your site admin email inbox for instructions.' );
   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.' );
   174 		} else {
   187 		} else {
   175 			$message = __( 'The site is experiencing technical difficulties.' );
   188 			$message = __( 'There has been a critical error on your website.' );
   176 		}
   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 		);
   177 
   198 
   178 		$args = array(
   199 		$args = array(
   179 			'response' => 500,
   200 			'response' => 500,
   180 			'exit'     => false,
   201 			'exit'     => false,
   181 		);
   202 		);