Make WordPress Core


Ignore:
Timestamp:
03/21/2019 09:52:07 PM (6 years ago)
Author:
flixos90
Message:

Bootstrap/Load: Introduce a recovery mode for fixing fatal errors.

Using the new fatal handler introduced in [44962], an email is sent to the admin when a fatal error occurs. This email includes a secret link to enter recovery mode. When clicked, the link will be validated and on success a cookie will be placed on the client, enabling recovery mode for that user. This functionality is executed early before plugins and themes are loaded, in order to be unaffected by potential fatal errors these might be causing.

When in recovery mode, broken plugins and themes will be paused for that client, so that they are able to access the admin backend despite of these errors. They are notified about the broken extensions and the errors caused, and can then decide whether they would like to temporarily deactivate the extension or fix the problem and resume the extension.

A link in the admin bar allows the client to exit recovery mode.

Props timothyblynjacobs, afragen, flixos90, nerrad, miss_jwo, schlessera, spacedmonkey, swissspidy.
Fixes #46130, #44458.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/themes.php

    r44717 r44973  
    3333        switch_theme( $theme->get_stylesheet() );
    3434        wp_redirect( admin_url( 'themes.php?activated=true' ) );
     35        exit;
     36    } elseif ( 'resume' === $_GET['action'] ) {
     37        check_admin_referer( 'resume-theme_' . $_GET['stylesheet'] );
     38        $theme = wp_get_theme( $_GET['stylesheet'] );
     39
     40        if ( ! current_user_can( 'resume_theme', $_GET['stylesheet'] ) ) {
     41            wp_die(
     42                '<h1>' . __( 'You need a higher level of permission.' ) . '</h1>' .
     43                '<p>' . __( 'Sorry, you are not allowed to resume this theme.' ) . '</p>',
     44                403
     45            );
     46        }
     47
     48        $result = resume_theme( $theme->get_stylesheet(), self_admin_url( 'themes.php?error=resuming' ) );
     49
     50        if ( is_wp_error( $result ) ) {
     51            wp_die( $result );
     52        }
     53
     54        wp_redirect( admin_url( 'themes.php?resumed=true' ) );
    3555        exit;
    3656    } elseif ( 'delete' == $_GET['action'] ) {
     
    196216    <div id="message4" class="error"><p><?php _e( 'You cannot delete a theme while it has an active child theme.' ); ?></p></div>
    197217    <?php
     218} elseif ( isset( $_GET['resumed'] ) ) {
     219    ?>
     220    <div id="message5" class="updated notice is-dismissible"><p><?php _e( 'Theme resumed.' ); ?></p></div>
     221    <?php
     222} elseif ( isset( $_GET['error'] ) && 'resuming' === $_GET['error'] ) {
     223    ?>
     224    <div id="message6" class="error"><p><?php _e( 'Theme could not be resumed because it triggered a <strong>fatal error</strong>.' ); ?></p></div>
     225    <?php
    198226}
    199227
     
    349377
    350378    <?php
     379    $can_resume  = current_user_can( 'resume_themes' );
    351380    $can_delete  = current_user_can( 'delete_themes' );
    352381    $can_install = current_user_can( 'install_themes' );
     
    356385        <th><?php _ex( 'Name', 'theme name' ); ?></th>
    357386        <th><?php _e( 'Description' ); ?></th>
     387        <?php if ( $can_resume ) { ?>
     388            <td></td>
     389        <?php } ?>
    358390        <?php if ( $can_delete ) { ?>
    359391            <td></td>
     
    368400            <td><?php echo $broken_theme->errors()->get_error_message(); ?></td>
    369401            <?php
     402            if ( $can_resume ) {
     403                if ( 'theme_paused' === $broken_theme->errors()->get_error_code() ) {
     404                    $stylesheet = $broken_theme->get_stylesheet();
     405                    $resume_url = add_query_arg(
     406                        array(
     407                            'action'     => 'resume',
     408                            'stylesheet' => urlencode( $stylesheet ),
     409                        ),
     410                        admin_url( 'themes.php' )
     411                    );
     412                    $resume_url = wp_nonce_url( $resume_url, 'resume-theme_' . $stylesheet );
     413                    ?>
     414                    <td><a href="<?php echo esc_url( $resume_url ); ?>" class="button resume-theme"><?php _e( 'Resume' ); ?></a></td>
     415                    <?php
     416                } else {
     417                    ?>
     418                    <td></td>
     419                    <?php
     420                }
     421            }
     422
    370423            if ( $can_delete ) {
    371424                $stylesheet = $broken_theme->get_stylesheet();
Note: See TracChangeset for help on using the changeset viewer.