Skip to content
Open
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions src/wp-admin/includes/class-wp-automatic-updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,16 @@ protected function send_plugin_theme_email( $type, $successful_updates, $failed_
*/
$email = apply_filters( 'auto_plugin_theme_update_email', $email, $type, $successful_updates, $failed_updates );

if ( defined( 'WP_DEBUG' ) && WP_DEBUG && 'fail' === $type ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constant is always defined in default-constants.php so the initial check can be removed:

Suggested change
if ( defined( 'WP_DEBUG' ) && WP_DEBUG && 'fail' === $type ) {
if ( WP_DEBUG && 'fail' === $type ) {

$fatal_error = get_transient( 'wp_last_fatal_error' );
if ( $fatal_error ) {
$email['body'] .= "\n\n=== LAST FATAL PHP ERROR ===\n";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be translated:

Suggested change
$email['body'] .= "\n\n=== LAST FATAL PHP ERROR ===\n";
$email['body'] .= "\n\n=== " . __( 'LAST FATAL PHP ERROR' ) . " ===\n";

$email['body'] .= '• ' . $fatal_error . "\n";
$email['body'] .= "========================================\n";
delete_transient( 'wp_last_fatal_error' );
}
}

$result = wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );

if ( $result ) {
Expand Down Expand Up @@ -1828,6 +1838,52 @@ protected function has_fatal_error() {
$result = json_decode( trim( $error_output ), true );
}

if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$fatal_error = null;

$last_error = error_get_last();
if ( $last_error && in_array( $last_error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR ) ) ) {
$fatal_error = "PHP Fatal error: {$last_error['message']} in {$last_error['file']} on line {$last_error['line']}";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be translated? I suppose it wouldn't be translated in the error log either.

} else {
$log_file = WP_CONTENT_DIR . '/debug.log';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use whatever the error_log is set to in the PHP config.

Suggested change
$log_file = WP_CONTENT_DIR . '/debug.log';
$log_file = ini_get( 'error_log' );

For another approach at parsing the error log, consider this code from the AMP plugin: https://github.com/ampproject/amp-wp/blob/2.5.4/src/Support/SupportData.php#L351-L410

if ( file_exists( $log_file ) && is_readable( $log_file ) ) {
$handle = fopen( $log_file, 'r' );
if ( $handle ) {
$pos = -2;
$current_line = '';
while ( $pos > -filesize( $log_file ) ) {
fseek( $handle, $pos, SEEK_END );
$char = fgetc( $handle );
if ( "\n" === $char ) {
if ( '' !== $current_line ) {
$line = strrev( $current_line );
if ( false !== strpos( $line, 'PHP Fatal error' ) ) {
$fatal_error = trim( $line );
break;
}
$current_line = '';
}
} else {
$current_line .= $char;
}
$pos--;
}
if ( '' !== $current_line && null === $fatal_error ) {
$line = strrev( $current_line );
if ( false !== strpos( $line, 'PHP Fatal error' ) ) {
$fatal_error = trim( $line );
}
}
fclose( $handle );
}
}
}

if ( $fatal_error ) {
set_transient( 'wp_last_fatal_error', $fatal_error, 5 * MINUTE_IN_SECONDS );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the transient's name should be specific to the updater to distinguish it from any other general captures of the last fatal error (if we ever do that). So maybe like wp_updater_last_fatal_error

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@westonruter All feedback addressed — thank you!

}
}

delete_transient( $transient );

// Only fatal errors will result in a 'type' key.
Expand Down
Loading