Make WordPress Core

Ticket #49199: 49199.4.diff

File 49199.4.diff, 17.6 KB (added by audrasjb, 3 years ago)

49199.4.diff: add multisite support for Themes autoupdates.

  • src/wp-admin/css/themes.css

    diff --git a/src/wp-admin/css/themes.css b/src/wp-admin/css/themes.css
    index 2b26a75f49..79c70fada8 100644
    a b body.folded .theme-browser ~ .theme-overlay .theme-wrap { 
    688688        line-height: inherit;
    689689}
    690690
    691 .theme-overlay .theme-author a {
     691.theme-overlay .theme-author a,
     692.theme-overlay .theme-autoupdate a {
    692693        text-decoration: none;
    693694}
    694695
  • src/wp-admin/includes/class-wp-ms-themes-list-table.php

    diff --git a/src/wp-admin/includes/class-wp-ms-themes-list-table.php b/src/wp-admin/includes/class-wp-ms-themes-list-table.php
    index 96e17efe58..1c1a008516 100644
    a b class WP_MS_Themes_List_Table extends WP_List_Table { 
    382382                }
    383383                if ( ! $this->is_site_themes ) {
    384384                        if ( current_user_can( 'update_themes' ) ) {
    385                                 $actions['update-selected'] = __( 'Update' );
     385                                $actions['update-selected']             = __( 'Update' );
     386                                $actions['enable-autoupdate-selected']  = __( 'Enable auto update' );
     387                                $actions['disable-autoupdate-selected'] = __( 'Disable auto update' );
    386388                        }
    387389                        if ( current_user_can( 'delete_themes' ) ) {
    388390                                $actions['delete-selected'] = __( 'Delete' );
    class WP_MS_Themes_List_Table extends WP_List_Table { 
    440442
    441443                // Pre-order.
    442444                $actions = array(
    443                         'enable'  => '',
    444                         'disable' => '',
    445                         'delete'  => '',
     445                        'enable'     => '',
     446                        'disable'    => '',
     447                        'delete'     => '',
     448                        'autoupdate' => '',
    446449                );
    447450
    448451                $stylesheet = $theme->get_stylesheet();
    class WP_MS_Themes_List_Table extends WP_List_Table { 
    637640                echo implode( ' | ', $theme_meta );
    638641
    639642                echo '</div>';
     643
     644                if ( wp_is_themes_auto_update_enabled() ) {
     645                        $wp_auto_update_themes = get_site_option( 'wp_auto_update_themes', array() );
     646                        if ( in_array( $stylesheet, $wp_auto_update_themes, true ) ) {
     647                                $aria_label = esc_attr(
     648                                        sprintf(
     649                                                /* translators: Theme name. */
     650                                                _x( 'Disable automatic updates for %s', 'theme' ),
     651                                                $theme->display( 'Name' )
     652                                        )
     653                                );
     654                                echo '<p class="theme-autoupdate-enabled">';
     655                                echo '<span class="dashicons dashicons-update" aria-hidden="true"></span> ' . __( 'Automatic update enabled' );
     656                                if ( current_user_can( 'update_themes', $stylesheet ) ) {
     657                                        echo sprintf(
     658                                                ' | <a href="%s" class="edit" aria-label="%s">%s</a>',
     659                                                wp_nonce_url( 'themes.php?action=autoupdate&amp;theme=' . urlencode( $stylesheet ), 'autoupdate-theme_' . urlencode( $stylesheet ) ),
     660                                                $aria_label,
     661                                                __( 'Disable' )
     662                                        );
     663                                }
     664                                echo '</p>';
     665                        } else {
     666                                if ( current_user_can( 'update_themes', $stylesheet ) ) {
     667                                        $aria_label = esc_attr(
     668                                                sprintf(
     669                                                        /* translators: Theme name. */
     670                                                        _x( 'Enable automatic updates for %s', 'theme' ),
     671                                                        $stylesheet
     672                                                )
     673                                        );
     674                                        echo '<p class="theme-autoupdate-enabled">';
     675                                        echo sprintf(
     676                                                '<a href="%s" class="edit" aria-label="%s"><span class="dashicons dashicons-update" aria-hidden="true"></span> %s</a>',
     677                                                wp_nonce_url( 'themes.php?action=autoupdate&amp;theme=' . urlencode( $stylesheet ), 'autoupdate-theme_' . urlencode( $stylesheet ) ),
     678                                                $aria_label,
     679                                                __( 'Enable automatic updates' )
     680                                        );
     681                                        echo '</p>';
     682                                }
     683                        }
     684                }
    640685        }
    641686
    642687        /**
  • src/wp-admin/includes/theme.php

    diff --git a/src/wp-admin/includes/theme.php b/src/wp-admin/includes/theme.php
    index 9f7a181553..9bd07ec441 100644
    a b function wp_prepare_themes_for_js( $themes = null ) { 
    653653                        );
    654654                }
    655655
     656                $is_autoupdated_enabled = null;
     657                if ( wp_is_themes_auto_update_enabled() ) {
     658                        $wp_auto_update_themes = get_site_option( 'wp_auto_update_themes', array() );
     659                        if ( in_array( $slug, $wp_auto_update_themes, true ) ) {
     660                                $is_autoupdated_enabled = true;
     661                        }
     662                }
     663
    656664                $prepared_themes[ $slug ] = array(
    657665                        'id'           => $slug,
    658666                        'name'         => $theme->display( 'Name' ),
    function wp_prepare_themes_for_js( $themes = null ) { 
    667675                        'hasUpdate'    => isset( $updates[ $slug ] ),
    668676                        'hasPackage'   => isset( $updates[ $slug ] ) && ! empty( $updates[ $slug ]['package'] ),
    669677                        'update'       => get_theme_update_available( $theme ),
     678                        'autoupdated'  => $is_autoupdated_enabled,
    670679                        'actions'      => array(
    671680                                'activate'  => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&amp;stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null,
    672681                                'customize' => $customize_action,
    673682                                'delete'    => current_user_can( 'delete_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&amp;stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null,
     683                                'autoupdate' => current_user_can( 'update_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=autoupdate&amp;stylesheet=' . $encoded_slug ), 'autoupdate-theme_' . $slug ) : null,
    674684                        ),
    675685                );
    676686        }
  • src/wp-admin/network/themes.php

    diff --git a/src/wp-admin/network/themes.php b/src/wp-admin/network/themes.php
    index 8fbce0a519..a73b741d59 100644
    a b if ( $action ) { 
    8888                        echo '</div>';
    8989                        require_once( ABSPATH . 'wp-admin/admin-footer.php' );
    9090                        exit;
     91                case 'autoupdate':
     92                        if ( ! wp_is_themes_auto_update_enabled() ) {
     93                                wp_die( __( 'Sorry, you are not allowed to enable themes automatic updates.' ) );
     94                        }
     95
     96                        check_admin_referer( 'autoupdate-theme_' . $_GET['theme'] );
     97
     98                        $wp_auto_update_themes = get_site_option( 'wp_auto_update_themes', array() );
     99
     100                        if ( in_array( $_GET['theme'], $wp_auto_update_themes, true ) ) {
     101                                $wp_auto_update_themes = array_diff( $wp_auto_update_themes, array( $_GET['theme'] ) );
     102                                $action_type = 'disable-autoupdate';
     103                        } else {
     104                                $wp_auto_update_themes[] = $_GET['theme'];
     105                                $action_type = 'enable-autoupdate';
     106                        }
     107                        update_site_option( 'wp_auto_update_themes', $wp_auto_update_themes );
     108
     109                        wp_redirect( self_admin_url( "themes.php?$action_type=1&paged=$page&s=$s" ) );
     110                        exit;
     111                case 'enable-autoupdate-selected':
     112                        if ( ! wp_is_themes_auto_update_enabled() ) {
     113                                wp_die( __( 'Sorry, you are not allowed to enable themes automatic updates.' ) );
     114                        }
     115
     116                        check_admin_referer( 'bulk-themes' );
     117
     118                        if ( isset( $_GET['themes'] ) ) {
     119                                $themes = explode( ',', $_GET['themes'] );
     120                        } elseif ( isset( $_POST['checked'] ) ) {
     121                                $themes = (array) $_POST['checked'];
     122                        } else {
     123                                $themes = array();
     124                        }
     125
     126                        if ( empty( $themes ) ) {
     127                                wp_safe_redirect( add_query_arg( 'error', 'main', $referer ) );
     128                                exit;
     129                        }
     130
     131                        $previous_autoupdated_themes = get_site_option( 'wp_auto_update_themes', array() );
     132
     133                        $new_autoupdated_themes = array_merge( $previous_autoupdated_themes, $themes );
     134                        $new_autoupdated_themes = array_unique( $new_autoupdated_themes );
     135
     136                        update_site_option( 'wp_auto_update_themes', $new_autoupdated_themes );
     137
     138                        wp_redirect( self_admin_url( "themes.php?enable-autoupdate=true&paged=$page&s=$s" ) );
     139                        exit;
     140                case 'disable-autoupdate-selected':
     141                        if ( ! wp_is_themes_auto_update_enabled() ) {
     142                                wp_die( __( 'Sorry, you are not allowed to disable themes automatic updates.' ) );
     143                        }
     144
     145                        check_admin_referer( 'bulk-themes' );
     146
     147                        if ( isset( $_GET['themes'] ) ) {
     148                                $themes = explode( ',', $_GET['themes'] );
     149                        } elseif ( isset( $_POST['checked'] ) ) {
     150                                $themes = (array) $_POST['checked'];
     151                        } else {
     152                                $themes = array();
     153                        }
     154
     155                        if ( empty( $themes ) ) {
     156                                wp_safe_redirect( add_query_arg( 'error', 'main', $referer ) );
     157                                exit;
     158                        }
     159
     160                        $previous_autoupdated_themes = get_site_option( 'wp_auto_update_themes', array() );
     161
     162                        $new_autoupdated_themes = array_diff( $previous_autoupdated_themes, $themes );
     163                        $new_autoupdated_themes = array_unique( $new_autoupdated_themes );
     164
     165                        update_site_option( 'wp_auto_update_themes', $new_autoupdated_themes );
     166
     167                        wp_redirect( self_admin_url( "themes.php?disable-autoupdate=true&paged=$page&s=$s" ) );
     168                        exit;
    91169                case 'delete-selected':
    92170                        if ( ! current_user_can( 'delete_themes' ) ) {
    93171                                wp_die( __( 'Sorry, you are not allowed to delete themes for this site.' ) );
    if ( isset( $_GET['enabled'] ) ) { 
    309387                $message = _n( '%s theme deleted.', '%s themes deleted.', $deleted );
    310388        }
    311389        echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $deleted ) ) . '</p></div>';
     390} elseif ( isset( $_GET['enable-autoupdate'] ) ) {
     391        if ( 1 === intval( $_GET['enable-autoupdate'] ) ) {
     392                echo '<div id="message" class="updated notice is-dismissible"><p>' . __( 'The selected theme will now update automatically.' ) . '</p></div>';
     393        } else {
     394                echo '<div id="message" class="updated notice is-dismissible"><p>' . __( 'The selected themes will now update automatically.' ) . '</p></div>';
     395        }
     396} elseif ( isset( $_GET['disable-autoupdate'] ) ) {
     397        if ( 1 === intval( $_GET['disable-autoupdate'] ) ) {
     398                echo '<div id="message" class="updated notice is-dismissible"><p>' . __( 'The selected theme won’t update automatically anymore.' ) . '</p></div>';
     399        } else {
     400                echo '<div id="message" class="updated notice is-dismissible"><p>' . __( 'The selected themes won’t update automatically anymore.' ) . '</p></div>';
     401        }
    312402} elseif ( isset( $_GET['error'] ) && 'none' == $_GET['error'] ) {
    313403        echo '<div id="message" class="error notice is-dismissible"><p>' . __( 'No theme selected.' ) . '</p></div>';
    314404} elseif ( isset( $_GET['error'] ) && 'main' == $_GET['error'] ) {
  • src/wp-admin/themes.php

    diff --git a/src/wp-admin/themes.php b/src/wp-admin/themes.php
    index bf424e93ff..c3b2c5c8d3 100644
    a b if ( current_user_can( 'switch_themes' ) && isset( $_GET['action'] ) ) { 
    5353
    5454                wp_redirect( admin_url( 'themes.php?resumed=true' ) );
    5555                exit;
     56        } elseif ( 'autoupdate' == $_GET['action'] ) {
     57                check_admin_referer( 'autoupdate-theme_' . $_GET['stylesheet'] );
     58                $theme = wp_get_theme( $_GET['stylesheet'] );
     59                $slug = $theme->get_stylesheet();
     60
     61                if ( ! current_user_can( 'update_themes' ) ) {
     62                        wp_die(
     63                                '<h1>' . __( 'You need a higher level of permission.' ) . '</h1>' .
     64                                '<p>' . __( 'Sorry, you are not allowed to enable automatic update for themes.' ) . '</p>',
     65                                403
     66                        );
     67                }
     68
     69                if ( ! wp_is_themes_auto_update_enabled() ) {
     70                        wp_die(
     71                                '<h1>' . __( 'You need a higher level of permission.' ) . '</h1>' .
     72                                '<p>' . __( 'Sorry, you are not allowed to enable automatic update for themes.' ) . '</p>',
     73                                403
     74                        );
     75                }
     76
     77                $wp_auto_update_themes = get_site_option( 'wp_auto_update_themes', array() );
     78                if ( ! in_array( $slug, $wp_auto_update_themes, true ) ) {
     79                        $autoupdate_action    = 'enable';
     80                        $wp_auto_update_themes[] = $slug;
     81                } else {
     82                        $autoupdate_action    = 'disable';
     83                        $wp_auto_update_themes = array_diff( $wp_auto_update_themes, array( $slug ) );
     84                }
     85
     86                update_site_option( 'wp_auto_update_themes', $wp_auto_update_themes );
     87
     88                wp_redirect( admin_url( 'themes.php?autoupdated=' . $autoupdate_action ) );
     89                exit;
    5690        } elseif ( 'delete' == $_GET['action'] ) {
    5791                check_admin_referer( 'delete-theme_' . $_GET['stylesheet'] );
    5892                $theme = wp_get_theme( $_GET['stylesheet'] );
    if ( ! validate_current_theme() || isset( $_GET['broken'] ) ) { 
    228262        ?>
    229263        <div id="message6" class="error"><p><?php _e( 'Theme could not be resumed because it triggered a <strong>fatal error</strong>.' ); ?></p></div>
    230264        <?php
     265} elseif ( isset( $_GET['autoupdated'] ) ) {
     266        $wp_auto_update_themes = get_site_option( 'wp_auto_update_themes', array() );
     267        $autoupdate_notice  = __( 'The selected theme won’t update automatically anymore.' );
     268        if ( 'enable' === $_GET['autoupdated'] ) {
     269                $autoupdate_notice = __( 'The selected theme will now update automatically.' );
     270        }
     271        ?>
     272        <div id="message7" class="updated notice is-dismissible"><p><?php echo $autoupdate_notice; ?></p></div>
     273        <?php
    231274}
    232275
    233276$ct = wp_get_theme();
    foreach ( $themes as $theme ) : 
    359402                        $aria_label = sprintf( _x( 'Activate %s', 'theme' ), '{{ data.name }}' );
    360403                        ?>
    361404                        <a class="button activate" href="<?php echo $theme['actions']['activate']; ?>" aria-label="<?php echo esc_attr( $aria_label ); ?>"><?php _e( 'Activate' ); ?></a>
     405                        <?php
     406                        if ( wp_is_themes_auto_update_enabled() ) {
     407                                /* translators: %s: Theme name. */
     408                                $aria_label_enable  = sprintf( _x( 'Enable automatic update for %s', 'theme' ), '{{ data.name }}' );
     409                                $aria_label_disable = sprintf( _x( 'Disable automatic update for %s', 'theme' ), '{{ data.name }}' );
     410                                ?>
     411                                <# if ( data.autoupdated ) { #>
     412                                        <a class="button autoupdate" href="{{{ data.actions.autoupdate }}}" aria-label="<?php echo $aria_label_disable; ?>"><?php _e( 'Disable auto update' ); ?></a>
     413                                <# } else { #>
     414                                        <a class="button autoupdate" href="{{{ data.actions.autoupdate }}}" aria-label="<?php echo $aria_label_enable; ?>"><?php _e( 'Enable auto update' ); ?></a>
     415                                <# } #>
     416                        <?php } ?>
    362417                        <?php if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { ?>
    363418                                <a class="button button-primary load-customize hide-if-no-customize" href="<?php echo $theme['actions']['customize']; ?>"><?php _e( 'Live Preview' ); ?></a>
    364419                        <?php } ?>
    if ( ! is_multisite() && current_user_can( 'edit_themes' ) && $broken_themes ) { 
    562617                                        printf( __( 'By %s' ), '{{{ data.authorAndUri }}}' );
    563618                                        ?>
    564619                                </p>
    565 
     620                                <?php if ( wp_is_themes_auto_update_enabled() ) : ?>
     621                                <p class="theme-autoupdate">
     622                                        <?php
     623                                        /* translators: %s: Theme name. */
     624                                        $aria_label_enable  = sprintf( _x( 'Enable automatic update for %s', 'theme' ), '{{ data.name }}' );
     625                                        $aria_label_disable = sprintf( _x( 'Disable automatic update for %s', 'theme' ), '{{ data.name }}' );
     626                                        ?>
     627                                        <# if ( data.autoupdated ) { #>
     628                                                <a href="{{{ data.actions.autoupdate }}}" aria-label="<?php echo $aria_label_disable; ?>"><span class="dashicons dashicons-update" aria-hidden="true"></span> <?php _e( 'Disable automatic updates' ); ?></a>
     629                                        <# } else { #>
     630                                                <a href="{{{ data.actions.autoupdate }}}" aria-label="<?php echo $aria_label_enable; ?>"><span class="dashicons dashicons-update" aria-hidden="true"></span> <?php _e( 'Enable automatic updates' ); ?></a>
     631                                        <# } #>
     632                                </p>
     633                                <?php endif; ?>
    566634                                <# if ( data.hasUpdate ) { #>
    567635                                <div class="notice notice-warning notice-alt notice-large">
    568636                                        <h3 class="notice-title"><?php _e( 'Update Available' ); ?></h3>
    569637                                        {{{ data.update }}}
     638                                        <# if ( data.autoupdated ) { #>
     639                                                <?php
     640                                                $next_update_time = wp_next_scheduled( 'wp_version_check' );
     641                                                $time_to_next_update = human_time_diff( intval( $next_update_time ) );
     642                                                $autoupdate = sprintf(
     643                                                        /* translators: Time until the next update. */
     644                                                        __( 'Automatic update scheduled in %s.' ),
     645                                                        $time_to_next_update
     646                                                );
     647                                                ?>
     648                                                <p class="theme-autoupdate-enabled"><?php echo $autoupdate; ?></p>
     649                                        <# } #>
    570650                                </div>
    571651                                <# } #>
    572652                                <p class="theme-description">{{{ data.description }}}</p>
  • src/wp-admin/update-core.php

    diff --git a/src/wp-admin/update-core.php b/src/wp-admin/update-core.php
    index 0f075e6442..2377ab5c85 100644
    a b function list_theme_updates() { 
    478478
    479479        <tbody class="plugins">
    480480        <?php
     481        if ( wp_is_themes_auto_update_enabled() ) {
     482                $wp_auto_update_themes = get_site_option( 'wp_auto_update_themes', array() );
     483        }
     484
    481485        foreach ( $themes as $stylesheet => $theme ) {
    482486                $checkbox_id = 'checkbox_' . md5( $theme->get( 'Name' ) );
     487
     488                $autoupdate = '';
     489                if ( wp_is_themes_auto_update_enabled() ) {
     490                        if ( in_array( $stylesheet, $wp_auto_update_themes, true ) ) {
     491                                $next_update_time = wp_next_scheduled( 'wp_version_check' );
     492                                $time_to_next_update = human_time_diff( intval( $next_update_time ) );
     493                                $autoupdate = ' <p class="theme-autoupdate-enabled">';
     494                                $autoupdate .= sprintf(
     495                                        /* translators: Time until the next update. */
     496                                        __( 'Automatic update scheduled in %s.' ),
     497                                        $time_to_next_update
     498                                );
     499                                $autoupdate .= '</p> ';
     500                        }
     501                }
    483502                ?>
    484503        <tr>
    485504                <td class="check-column">
    function list_theme_updates() { 
    501520                                $theme->display( 'Version' ),
    502521                                $theme->update['new_version']
    503522                        );
     523                        echo $autoupdate;
    504524                        ?>
    505525                </p></td>
    506526        </tr>
  • src/wp-includes/update.php

    diff --git a/src/wp-includes/update.php b/src/wp-includes/update.php
    index 125a6e3084..1abf446734 100644
    a b if ( ( ! is_main_site() && ! is_network_admin() ) || wp_doing_ajax() ) { 
    813813        return;
    814814}
    815815
     816/**
     817 * Autoupdate selected themes.
     818 *
     819 * @since 5.4.0
     820 */
     821function wp_auto_update_theme( $update, $item ) {
     822        $wp_auto_update_themes = get_site_option( 'wp_auto_update_themes', array() );
     823        if ( in_array( $item->theme, $wp_auto_update_themes, true ) ) {
     824                return true;
     825        } else {
     826                return $update;
     827        }
     828}
     829
     830/**
     831 * Checks whether themes manual autoupdate is enabled.
     832 *
     833 * @since 5.4.0
     834 */
     835function wp_is_themes_auto_update_enabled() {
     836        $enabled = ! defined( 'WP_DISABLE_THEMES_AUTO_UPDATE' ) || ! WP_DISABLE_THEMES_AUTO_UPDATE;
     837
     838        /**
     839         * Filters whether themes manual autoupdate is enabled.
     840         *
     841         * @since 5.4.0
     842         *
     843         * @param bool $enabled True if themes auto udpate is enabled, false otherwise.
     844         */
     845        return apply_filters( 'wp_themes_auto_update_enabled', $enabled );
     846}
     847
    816848add_action( 'admin_init', '_maybe_update_core' );
    817849add_action( 'wp_version_check', 'wp_version_check' );
    818850
    add_action( 'wp_update_themes', 'wp_update_themes' ); 
    831863add_action( 'update_option_WPLANG', 'wp_clean_update_cache', 10, 0 );
    832864
    833865add_action( 'wp_maybe_auto_update', 'wp_maybe_auto_update' );
     866add_filter( 'auto_update_theme', 'wp_auto_update_theme', 10, 2 );
    834867
    835868add_action( 'init', 'wp_schedule_update_checks' );