Make WordPress Core


Ignore:
Timestamp:
05/20/2020 06:47:24 PM (6 years ago)
Author:
whyisjake
Message:

Security: Add user interface to auto-update themes and plugins.

Building on core update mechanisms, this adds the ability to enable automatic updates for themes and plugins to the WordPress admin.

Fixes: #50052.
Props: afercia, afragen, audrasjb, azaozz, bookdude13, davidperonne, desrosj, gmays, gmays, javiercasares, karmatosed, knutsp, mapk, mukesh27, netweb, nicolaskulka, nielsdeblaauw, paaljoachim, passoniate, pbiron, pedromendonca, whodunitagency, whyisjake, wpamitkumar, and xkon.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/class-wp-automatic-updater.php

    r47808 r47835  
    159159                if ( 'core' === $type ) {
    160160                        $update = Core_Upgrader::should_update_to_version( $item->current );
     161                } elseif ( 'plugin' === $type || 'theme' === $type ) {
     162                        $update = ! empty( $item->autoupdate );
     163
     164                        if ( ! $update && wp_is_auto_update_enabled_for_type( $type ) ) {
     165                                // Check if the site admin has enabled auto-updates by default for the specific item.
     166                                $auto_updates = (array) get_site_option( "auto_update_{$type}s", array() );
     167                                $update       = in_array( $item->{$type}, $auto_updates, true );
     168                        }
    161169                } else {
    162170                        $update = ! empty( $item->autoupdate );
    … …  
    502510                        if ( ! empty( $this->update_results['core'] ) ) {
    503511                                $this->after_core_update( $this->update_results['core'][0] );
     512                        } elseif ( ! empty( $this->update_results['plugin'] ) || ! empty( $this->update_results['theme'] ) ) {
     513                                $this->after_plugin_theme_update( $this->update_results );
    504514                        }
    505515
    … …  
    855865        }
    856866
     867
     868        /**
     869         * If we tried to perform plugin or theme updates, check if we should send an email.
     870         *
     871         * @since 5.5.0
     872         *
     873         * @param object $results The result of updates tasks.
     874         */
     875        protected function after_plugin_theme_update( $update_results ) {
     876                $successful_updates = array();
     877                $failed_updates     = array();
     878
     879                /**
     880                 * Filters whether to send an email following an automatic background plugin update.
     881                 *
     882                 * @since 5.5.0
     883                 *
     884                 * @param bool $enabled True if plugins notifications are enabled, false otherwise.
     885                 */
     886                $notifications_enabled = apply_filters( 'auto_plugin_update_send_email', true );
     887
     888                if ( ! empty( $update_results['plugin'] ) && $notifications_enabled ) {
     889                        foreach ( $update_results['plugin'] as $update_result ) {
     890                                if ( true === $update_result->result ) {
     891                                        $successful_updates['plugin'][] = $update_result;
     892                                } else {
     893                                        $failed_updates['plugin'][] = $update_result;
     894                                }
     895                        }
     896                }
     897
     898                /**
     899                 * Filters whether to send an email following an automatic background theme update.
     900                 *
     901                 * @since 5.5.0
     902                 *
     903                 * @param bool $enabled True if notifications are enabled, false otherwise.
     904                 */
     905                $notifications_enabled = apply_filters( 'send_theme_auto_update_email', true );
     906
     907                if ( ! empty( $update_results['theme'] ) && $notifications_enabled ) {
     908                        foreach ( $update_results['theme'] as $update_result ) {
     909                                if ( true === $update_result->result ) {
     910                                        $successful_updates['theme'][] = $update_result;
     911                                } else {
     912                                        $failed_updates['theme'][] = $update_result;
     913                                }
     914                        }
     915                }
     916
     917                if ( empty( $successful_updates ) && empty( $failed_updates ) ) {
     918                        return;
     919                }
     920
     921                if ( empty( $failed_updates ) ) {
     922                        $this->send_plugin_theme_email( 'success', $successful_updates, $failed_updates );
     923                } elseif ( empty( $successful_updates ) ) {
     924                        $this->send_plugin_theme_email( 'fail', $successful_updates, $failed_updates );
     925                } else {
     926                        $this->send_plugin_theme_email( 'mixed', $successful_updates, $failed_updates );
     927                }
     928        }
     929
     930        /**
     931         * Sends an email upon the completion or failure of a plugin or theme background update.
     932         *
     933         * @since 5.5.0
     934         *
     935         * @param string $type               The type of email to send. Can be one of 'success', 'failure', 'mixed'.
     936         * @param array  $successful_updates A list of updates that succeeded.
     937         * @param array  $failed_updates     A list of updates that failed.
     938         */
     939        protected function send_plugin_theme_email( $type, $successful_updates, $failed_updates ) {
     940                // No updates were attempted.
     941                if ( empty( $successful_updates ) && empty( $failed_updates ) ) {
     942                        return;
     943                }
     944                $body = array();
     945
     946                switch ( $type ) {
     947                        case 'success':
     948                                /* translators: %s: Site title. */
     949                                $subject = __( '[%s] Some plugins or themes were automatically updated' );
     950                                break;
     951                        case 'fail':
     952                                /* translators: %s: Site title. */
     953                                $subject = __( '[%s] Some plugins or themes have failed to update' );
     954                                $body[]  = sprintf(
     955                                        /* translators: %s: Home URL. */
     956                                        __( 'Howdy! Failures occurred when attempting to update plugins/themes on your site at %s.' ),
     957                                        home_url()
     958                                );
     959                                $body[] = "\n";
     960                                $body[] = __( 'Please check out your site now. It’s possible that everything is working. If it says you need to update, you should do so.' );
     961                                break;
     962                        case 'mixed':
     963                                /* translators: %s: Site title. */
     964                                $subject = __( '[%s] Some plugins or themes were automatically updated' );
     965                                $body[]  = sprintf(
     966                                        /* translators: %s: Home URL. */
     967                                        __( 'Howdy! Failures occurred when attempting to update plugins/themes on your site at %s.' ),
     968                                        home_url()
     969                                );
     970                                $body[] = "\n";
     971                                $body[] = __( 'Please check out your site now. It’s possible that everything is working. If it says you need to update, you should do so.' );
     972                                $body[] = "\n";
     973                                break;
     974                }
     975
     976                // Get failed plugin updates.
     977                if ( in_array( $type, array( 'fail', 'mixed' ), true ) && ! empty( $failed_updates['plugin'] ) ) {
     978                        $body[] = __( 'The following plugins failed to update:' );
     979                        // List failed updates.
     980                        foreach ( $failed_updates['plugin'] as $item ) {
     981                                $body[] = "- {$item->name}";
     982                        }
     983                        $body[] = "\n";
     984                }
     985                // Get failed theme updates.
     986                if ( in_array( $type, array( 'fail', 'mixed' ), true ) && ! empty( $failed_updates['theme'] ) ) {
     987                        $body[] = __( 'The following themes failed to update:' );
     988                        // List failed updates.
     989                        foreach ( $failed_updates['theme'] as $item ) {
     990                                $body[] = "- {$item->name}";
     991                        }
     992                        $body[] = "\n";
     993                }
     994                // Get successful plugin updates.
     995                if ( in_array( $type, array( 'success', 'mixed' ), true ) && ! empty( $successful_updates['plugin'] ) ) {
     996                        $body[] = __( 'The following plugins were successfully updated:' );
     997                        // List successful updates.
     998                        foreach ( $successful_updates['plugin'] as $item ) {
     999                                $body[] = "- {$item->name}";
     1000                        }
     1001                        $body[] = "\n";
     1002                }
     1003                // Get successful theme updates.
     1004                if ( in_array( $type, array( 'success', 'mixed' ), true ) && ! empty( $successful_updates['theme'] ) ) {
     1005                        $body[] = __( 'The following themes were successfully updated:' );
     1006                        // List successful updates.
     1007                        foreach ( $successful_updates['theme'] as $item ) {
     1008                                $body[] = "- {$item->name}";
     1009                        }
     1010                        $body[] = "\n";
     1011                }
     1012                $body[] = "\n";
     1013
     1014                // Add a note about the support forums.
     1015                $body[] = __( 'If you experience any issues or need support, the volunteers in the WordPress.org support forums may be able to help.' );
     1016                $body[] = __( 'https://wordpress.org/support/forums/' );
     1017                $body[] = "\n" . __( 'The WordPress Team' );
     1018
     1019                $body    = implode( "\n", $body );
     1020                $to      = get_site_option( 'admin_email' );
     1021                $subject = sprintf( $subject, wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) );
     1022                $headers = '';
     1023
     1024                $email = compact( 'to', 'subject', 'body', 'headers' );
     1025
     1026                /**
     1027                 * Filters the email sent following an automatic background plugin update.
     1028                 *
     1029                 * @param array $email {
     1030                 *     Array of email arguments that will be passed to wp_mail().
     1031                 *
     1032                 *     @type string $to      The email recipient. An array of emails
     1033                 *                           can be returned, as handled by wp_mail().
     1034                 *     @type string $subject The email's subject.
     1035                 *     @type string $body    The email message body.
     1036                 *     @type string $headers Any email headers, defaults to no headers.
     1037                 * }
     1038                 * @param string $type               The type of email being sent. Can be one of
     1039                 *                                   'success', 'fail', 'mixed'.
     1040                 * @param object $successful_updates The updates that succeeded.
     1041                 * @param object $failed_updates     The updates that failed.
     1042                 */
     1043                $email = apply_filters( 'auto_plugin_theme_update_email', $email, $type, $successful_updates, $failed_updates );
     1044                wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
     1045        }
     1046
    8571047        /**
    8581048         * Prepares and sends an email of a full log of background update results, useful for debugging and geekery.
Note: See TracChangeset for help on using the changeset viewer.