WP_Automatic_Updater::has_fatal_error()protectedWP 6.6.0

Performs a loopback request to check for potential fatal errors.

Fatal errors cannot be detected unless maintenance mode is enabled.

Method of the class: WP_Automatic_Updater{}

Hooks from the method

Return

true|false. Whether a fatal error was detected.

Usage

// protected - for code of main (parent) or child class
$result = $this->has_fatal_error();

Notes

  • Global. Int. $upgrading The Unix timestamp marking when upgrading WordPress began.

Changelog

Since 6.6.0 Introduced.

WP_Automatic_Updater::has_fatal_error() code WP 6.6.2

protected function has_fatal_error() {
	global $upgrading;

	$maintenance_file = ABSPATH . '.maintenance';
	if ( ! file_exists( $maintenance_file ) ) {
		return false;
	}

	require $maintenance_file;
	if ( ! is_int( $upgrading ) ) {
		return false;
	}

	$scrape_key   = md5( $upgrading );
	$scrape_nonce = (string) $upgrading;
	$transient    = 'scrape_key_' . $scrape_key;
	set_transient( $transient, $scrape_nonce, 30 );

	$cookies       = wp_unslash( $_COOKIE );
	$scrape_params = array(
		'wp_scrape_key'   => $scrape_key,
		'wp_scrape_nonce' => $scrape_nonce,
	);
	$headers       = array(
		'Cache-Control' => 'no-cache',
	);

	/** This filter is documented in wp-includes/class-wp-http-streams.php */
	$sslverify = apply_filters( 'https_local_ssl_verify', false );

	// Include Basic auth in the loopback request.
	if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) {
		$headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
	}

	// Time to wait for loopback request to finish.
	$timeout = 50; // 50 seconds.

	$is_debug = WP_DEBUG && WP_DEBUG_LOG;
	if ( $is_debug ) {
		error_log( '    Scraping home page...' );
	}

	$needle_start = "###### wp_scraping_result_start:$scrape_key ######";
	$needle_end   = "###### wp_scraping_result_end:$scrape_key ######";
	$url          = add_query_arg( $scrape_params, home_url( '/' ) );
	$response     = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout', 'sslverify' ) );

	if ( is_wp_error( $response ) ) {
		if ( $is_debug ) {
			error_log( 'Loopback request failed: ' . $response->get_error_message() );
		}
		return true;
	}

	// If this outputs `true` in the log, it means there were no fatal errors detected.
	if ( $is_debug ) {
		error_log( var_export( substr( $response['body'], strpos( $response['body'], '###### wp_scraping_result_start:' ) ), true ) );
	}

	$body                   = wp_remote_retrieve_body( $response );
	$scrape_result_position = strpos( $body, $needle_start );
	$result                 = null;

	if ( false !== $scrape_result_position ) {
		$error_output = substr( $body, $scrape_result_position + strlen( $needle_start ) );
		$error_output = substr( $error_output, 0, strpos( $error_output, $needle_end ) );
		$result       = json_decode( trim( $error_output ), true );
	}

	delete_transient( $transient );

	// Only fatal errors will result in a 'type' key.
	return isset( $result['type'] );
}