Make WordPress Core

Changeset 48397


Ignore:
Timestamp:
07/07/2020 06:58:32 PM (4 years ago)
Author:
desrosj
Message:

Administration: Prevent repeat emails for identical plugin or theme auto-update attempt failures.

This change adds a throttle mechanism to plugin and theme auto-update failure emails using similar logic to the email sent for a Core auto-update.

The first time a plugin or theme auto-update fails, the package and new_version will be tracked in the auto_plugin_theme_update_emails option. An email for this specific update attempt will not be resent.

However, if this update fails again and non-repeat failures or successful updates are also present, then the failure information will be included in that email (an email needs to be sent for the new events regardless).

Props johnbillion, arpitgshah, desrosj, audrasjb, pbiron, earnjam.
Fixes #50448.

Location:
trunk/src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/class-plugin-upgrader.php

    r48390 r48397  
    248248        wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
    249249
     250        // Ensure any future auto-update failures trigger a failure email by removing the last
     251        // failure notification from the list when plugins update successfully.
     252        $past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );
     253
     254        if ( isset( $past_failure_emails[ $plugin ] ) ) {
     255            unset( $past_failure_emails[ $plugin ] );
     256            update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );
     257        }
     258
    250259        return true;
    251260    }
     
    371380        remove_filter( 'upgrader_clear_destination', array( $this, 'delete_old_plugin' ) );
    372381
     382        // Ensure any future auto-update failures trigger a failure email by removing the last
     383        // failure notification from the list when plugins update successfully.
     384        $past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );
     385
     386        foreach ( $results as $plugin => $result ) {
     387            // Maintain last failure notification when plugins failed to update manually.
     388            if ( ! $result || is_wp_error( $result ) || ! isset( $past_failure_emails[ $plugin ] ) ) {
     389                continue;
     390            }
     391
     392            unset( $past_failure_emails[ $plugin ] );
     393        }
     394        update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );
     395
    373396        return $results;
    374397    }
  • trunk/src/wp-admin/includes/class-theme-upgrader.php

    r48390 r48397  
    353353        wp_clean_themes_cache( $parsed_args['clear_update_cache'] );
    354354
     355        // Ensure any future auto-update failures trigger a failure email by removing the last
     356        // failure notification from the list when themes update successfully.
     357        $past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );
     358
     359        if ( isset( $past_failure_emails[ $theme ] ) ) {
     360            unset( $past_failure_emails[ $theme ] );
     361            update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );
     362        }
     363
    355364        return true;
    356365    }
     
    480489        remove_filter( 'upgrader_clear_destination', array( $this, 'delete_old_theme' ) );
    481490
     491        // Ensure any future auto-update failures trigger a failure email by removing the last
     492        // failure notification from the list when themes update successfully.
     493        $past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );
     494
     495        foreach ( $results as $theme => $result ) {
     496            // Maintain last failure notification when themes failed to update manually.
     497            if ( ! $result || is_wp_error( $result ) || ! isset( $past_failure_emails[ $theme ] ) ) {
     498                continue;
     499            }
     500
     501            unset( $past_failure_emails[ $theme ] );
     502        }
     503        update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );
     504
    482505        return $results;
    483506    }
  • trunk/src/wp-admin/includes/class-wp-automatic-updater.php

    r48344 r48397  
    940940        if ( empty( $successful_updates ) && empty( $failed_updates ) ) {
    941941            return;
     942        }
     943
     944        $unique_failures     = false;
     945        $past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );
     946
     947        // When only failures have occurred, an email should only be sent if there are unique failures.
     948        // A failure is considered unique if an email has not been sent for an update attempt failure
     949        // to a plugin or theme with the same new_version.
     950        if ( 'fail' === $type ) {
     951            foreach ( $failed_updates as $update_type => $failures ) {
     952                foreach ( $failures as $failed_update ) {
     953                    if ( ! isset( $past_failure_emails[ $failed_update->item->{$update_type} ] ) ) {
     954                        $unique_failures = true;
     955                        continue;
     956                    }
     957
     958                    // Check that the failure represents a new failure based on the new_version.
     959                    if ( version_compare( $past_failure_emails[ $failed_update->item->{$update_type} ], $failed_update->item->new_version, '<' ) ) {
     960                        $unique_failures = true;
     961                    }
     962                }
     963            }
     964
     965            if ( ! $unique_failures ) {
     966                return;
     967            }
    942968        }
    943969
     
    10181044
    10191045                foreach ( $failed_updates['plugin'] as $item ) {
    1020                     $body[] = "- {$item->name}";
     1046                    $body[]                                     = "- {$item->name}";
     1047                    $past_failure_emails[ $item->item->plugin ] = $item->item->new_version;
    10211048                }
    10221049                $body[] = "\n";
     
    10281055
    10291056                foreach ( $failed_updates['theme'] as $item ) {
    1030                     $body[] = "- {$item->name}";
     1057                    $body[]                                    = "- {$item->name}";
     1058                    $past_failure_emails[ $item->item->theme ] = $item->item->new_version;
    10311059                }
    10321060                $body[] = "\n";
     
    10441072                foreach ( $successful_updates['plugin'] as $item ) {
    10451073                    $body[] = "- {$item->name}";
     1074                    unset( $past_failure_emails[ $item->item->plugin ] );
    10461075                }
    10471076                $body[] = "\n";
     
    10541083                foreach ( $successful_updates['theme'] as $item ) {
    10551084                    $body[] = "- {$item->name}";
     1085                    unset( $past_failure_emails[ $item->item->theme ] );
    10561086                }
    10571087                $body[] = "\n";
     
    11091139        $email = apply_filters( 'auto_plugin_theme_update_email', $email, $type, $successful_updates, $failed_updates );
    11101140
    1111         wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
     1141        $result = wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
     1142
     1143        if ( $result ) {
     1144            update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );
     1145        }
    11121146    }
    11131147
  • trunk/src/wp-admin/includes/schema.php

    r48121 r48397  
    535535        'blocklist_keys'                  => '',
    536536        'comment_previously_approved'     => 1,
     537        'auto_plugin_theme_update_emails' => array(),
    537538    );
    538539
     
    553554
    554555    // Set autoload to no for these options.
    555     $fat_options = array( 'moderation_keys', 'recently_edited', 'blocklist_keys', 'uninstall_plugins' );
     556    $fat_options = array(
     557        'moderation_keys',
     558        'recently_edited',
     559        'blocklist_keys',
     560        'uninstall_plugins',
     561        'auto_plugin_theme_update_emails',
     562    );
    556563
    557564    $keys             = "'" . implode( "', '", array_keys( $options ) ) . "'";
  • trunk/src/wp-includes/version.php

    r48158 r48397  
    2121 * @global int $wp_db_version
    2222 */
    23 $wp_db_version = 48121;
     23$wp_db_version = 48397;
    2424
    2525/**
Note: See TracChangeset for help on using the changeset viewer.