WordPress.org

Make WordPress Core

Ticket #50052: 50052.3.diff

File 50052.3.diff, 65.3 KB (added by azaozz, 16 months ago)

Diff from https://github.com/WordPress/wordpress-develop/pull/281

  • src/js/_enqueues/wp/updates.js

     
    409409         *
    410410         * @since 4.2.0
    411411         * @since 4.6.0 More accurately named `updatePluginSuccess`.
     412         * @since 5.5.0 Auto-update "time to next update" text cleared.
    412413         *
    413414         * @param {object} response            Response from the server.
    414415         * @param {string} response.slug       Slug of the plugin to be updated.
     
    431432                        // Update the version number in the row.
    432433                        newText = $pluginRow.find( '.plugin-version-author-uri' ).html().replace( response.oldVersion, response.newVersion );
    433434                        $pluginRow.find( '.plugin-version-author-uri' ).html( newText );
     435
     436                        // Clear the "time to next auto-update" text.
     437                        $pluginRow.find( '.auto-update-time' ).empty();
    434438                } else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
    435439                        $updateMessage = $( '.plugin-card-' + response.slug ).find( '.update-now' )
    436440                                .removeClass( 'updating-message' )
     
    969973         * Updates the UI appropriately after a successful theme update.
    970974         *
    971975         * @since 4.6.0
     976         * @since 5.5.0 Auto-update "time to next update" text cleared.
    972977         *
    973978         * @param {object} response
    974979         * @param {string} response.slug       Slug of the theme to be updated.
     
    10021007                        // Update the version number in the row.
    10031008                        newText = $theme.find( '.theme-version-author-uri' ).html().replace( response.oldVersion, response.newVersion );
    10041009                        $theme.find( '.theme-version-author-uri' ).html( newText );
     1010
     1011                        // Clear the "time to next auto-update" text.
     1012                        $theme.find( '.auto-update-time' ).empty();
    10051013                } else {
    10061014                        $notice = $( '.theme-info .notice' ).add( $theme.find( '.update-message' ) );
    10071015
     
    10081016                        // Focus on Customize button after updating.
    10091017                        if ( isModalOpen ) {
    10101018                                $( '.load-customize:visible' ).focus();
     1019                                $( '.theme-info .theme-autoupdate' ).find( '.auto-update-time' ).empty();
    10111020                        } else {
    10121021                                $theme.find( '.load-customize' ).focus();
    10131022                        }
     
    24612470                 * @since 4.2.0
    24622471                 */
    24632472                $( window ).on( 'beforeunload', wp.updates.beforeunload );
     2473
     2474                /**
     2475                 * Click handler for enabling and disabling plugin and theme auto-updates.
     2476                 *
     2477                 * @since 5.5.0
     2478                 */
     2479                $document.on( 'click', '.column-auto-updates a.toggle-auto-update, .theme-overlay a.toggle-auto-update', function( event ) {
     2480                        var data, asset, type, $parent;
     2481                        var $anchor = $( this ),
     2482                                action = $anchor.attr( 'data-wp-action' ),
     2483                                $label = $anchor.find( '.label' );
     2484
     2485                        if ( 'themes' !== pagenow ) {
     2486                                $parent = $anchor.closest( '.column-auto-updates' );
     2487                        } else {
     2488                                $parent = $anchor.closest( '.theme-autoupdate' );
     2489                        }
     2490
     2491                        event.preventDefault();
     2492
     2493                        // Prevent multiple simultaneous requests.
     2494                        if ( $anchor.attr( 'data-doing-ajax' ) === 'yes' ) {
     2495                                return;
     2496                        }
     2497
     2498                        $anchor.attr( 'data-doing-ajax', 'yes' );
     2499
     2500                        switch ( pagenow ) {
     2501                                case 'plugins':
     2502                                case 'plugins-network':
     2503                                        type = 'plugin';
     2504                                        asset = $anchor.closest( 'tr' ).attr( 'data-plugin' );
     2505                                        break;
     2506                                case 'themes-network':
     2507                                        type = 'theme';
     2508                                        asset = $anchor.closest( 'tr' ).attr( 'data-slug' );
     2509                                        break;
     2510                                case 'themes':
     2511                                        type = 'theme';
     2512                                        asset = $anchor.attr( 'data-slug' );
     2513                                        break;
     2514                        }
     2515
     2516                        // Clear any previous errors.
     2517                        $parent.find( '.notice.error' ).addClass( 'hidden' );
     2518
     2519                        // Show loading status.
     2520                        if ( 'enable' === action ) {
     2521                                $label.text( wp.updates.l10n.autoUpdatesEnabling );
     2522                        } else {
     2523                                $label.text( wp.updates.l10n.autoUpdatesDisabling );
     2524                        }
     2525
     2526                        $anchor.find( '.dashicons-update' ).removeClass( 'hidden' );
     2527
     2528                        data = {
     2529                                action: 'toggle-auto-updates',
     2530                                _ajax_nonce: settings.ajax_nonce,
     2531                                state: action,
     2532                                type: type,
     2533                                asset: asset
     2534                        };
     2535
     2536                        $.post( window.ajaxurl, data )
     2537                                .done( function( response ) {
     2538                                        var $enabled, $disabled, enabledNumber, disabledNumber, errorMessage;
     2539                                        var href = $anchor.attr( 'href' );
     2540
     2541                                        if ( ! response.success ) {
     2542                                                // if WP returns 0 for response (which can happen in a few cases),
     2543                                                // output the general error message since we won't have response.data.error.
     2544                                                if ( response.data && response.data.error ) {
     2545                                                        errorMessage = response.data.error;
     2546                                                } else {
     2547                                                        errorMessage = wp.updates.l10n.autoUpdatesError;
     2548                                                }
     2549
     2550                                                $parent.find( '.notice.error' ).removeClass( 'hidden' ).find( 'p' ).text( errorMessage );
     2551                                                wp.a11y.speak( errorMessage, 'polite' );
     2552                                                return;
     2553                                        }
     2554
     2555                                        // Update the counts in the enabled/disabled views if on a screen
     2556                                        // with a list table.
     2557                                        if ( 'themes' !== pagenow ) {
     2558                                                $enabled       = $( '.auto-update-enabled span' );
     2559                                                $disabled      = $( '.auto-update-disabled span' );
     2560                                                enabledNumber  = parseInt( $enabled.text().replace( /[^\d]+/g, '' ), 10 ) || 0;
     2561                                                disabledNumber = parseInt( $disabled.text().replace( /[^\d]+/g, '' ), 10 ) || 0;
     2562
     2563                                                switch ( action ) {
     2564                                                        case 'enable':
     2565                                                                ++enabledNumber;
     2566                                                                --disabledNumber;
     2567                                                                break;
     2568                                                        case 'disable':
     2569                                                                --enabledNumber;
     2570                                                                ++disabledNumber;
     2571                                                                break;
     2572                                                }
     2573
     2574                                                enabledNumber = Math.max( 0, enabledNumber );
     2575                                                disabledNumber = Math.max( 0, disabledNumber );
     2576
     2577                                                $enabled.text( '(' + enabledNumber + ')' );
     2578                                                $disabled.text( '(' + disabledNumber + ')' );
     2579                                        }
     2580
     2581                                        if ( 'enable' === action ) {
     2582                                                href = href.replace( 'action=enable-auto-update', 'action=disable-auto-update' );
     2583                                                $anchor.attr( {
     2584                                                        'data-wp-action': 'disable',
     2585                                                        href: href
     2586                                                } );
     2587
     2588                                                $label.text( wp.updates.l10n.autoUpdatesDisable );
     2589                                                $parent.find( '.auto-update-time' ).removeClass( 'hidden' );
     2590                                                wp.a11y.speak( wp.updates.l10n.autoUpdatesEnabled, 'polite' );
     2591                                        } else {
     2592                                                href = href.replace( 'action=disable-auto-update', 'action=enable-auto-update' );
     2593                                                $anchor.attr( {
     2594                                                        'data-wp-action': 'enable',
     2595                                                        href: href
     2596                                                } );
     2597
     2598                                                $label.text( wp.updates.l10n.autoUpdatesEnable );
     2599                                                $parent.find( '.auto-update-time' ).addClass( 'hidden' );
     2600                                                wp.a11y.speak( wp.updates.l10n.autoUpdatesDisabled, 'polite' );
     2601                                        }
     2602                                } )
     2603                                .fail( function() {
     2604                                        $parent.find( '.notice.error' ).removeClass( 'hidden' ).find( 'p' ).text( wp.updates.l10n.autoUpdatesError );
     2605                                        wp.a11y.speak( wp.updates.l10n.autoUpdatesError, 'polite' );
     2606                                } )
     2607                                .always( function() {
     2608                                        $anchor.removeAttr( 'data-doing-ajax' ).find( '.dashicons-update' ).addClass( 'hidden' );
     2609                                } );
     2610                        }
     2611                );
    24642612        } );
    24652613})( jQuery, window.wp, window._wpUpdatesSettings );
  • src/wp-admin/admin-ajax.php

     
    139139        'health-check-background-updates',
    140140        'health-check-loopback-requests',
    141141        'health-check-get-sizes',
     142        'toggle-auto-updates',
    142143);
    143144
    144145// Deprecated.
  • src/wp-admin/css/common.css

     
    15241524.updating-message p:before,
    15251525.import-php .updating-message:before,
    15261526.button.updating-message:before,
    1527 .button.installing:before {
     1527.button.installing:before,
     1528.plugins .column-auto-updates .dashicons-update.spin,
     1529.theme-overlay .theme-autoupdate .dashicons-update.spin {
    15281530        animation: rotation 2s infinite linear;
    15291531}
    15301532
  • src/wp-admin/css/list-tables.css

     
    12361236        width: 85px;
    12371237}
    12381238
     1239.plugins .column-auto-updates {
     1240        width: 14.2em;
     1241}
     1242
    12391243.plugins .inactive .plugin-title strong {
    12401244        font-weight: 400;
    12411245}
  • src/wp-admin/css/themes.css

     
    679679        line-height: inherit;
    680680}
    681681
    682 .theme-overlay .theme-author a {
     682.theme-overlay .theme-author a,
     683.theme-overlay .theme-autoupdate a {
    683684        text-decoration: none;
    684685}
    685686
  • src/wp-admin/includes/ajax-actions.php

     
    45674567function wp_ajax_search_plugins() {
    45684568        check_ajax_referer( 'updates' );
    45694569
     4570        // Ensure after_plugin_row_{$plugin_file} gets hooked.
     4571        wp_plugin_update_rows();
     4572
    45704573        $pagenow = isset( $_POST['pagenow'] ) ? sanitize_key( $_POST['pagenow'] ) : '';
    45714574        if ( 'plugins-network' === $pagenow || 'plugins' === $pagenow ) {
    45724575                set_current_screen( $pagenow );
     
    52675270function wp_ajax_rest_nonce() {
    52685271        exit( wp_create_nonce( 'wp_rest' ) );
    52695272}
     5273
     5274/**
     5275 * Ajax handler to enable or disable plugin and theme auto-updates.
     5276 *
     5277 * @since 5.5.0
     5278 */
     5279function wp_ajax_toggle_auto_updates() {
     5280        check_ajax_referer( 'updates' );
     5281
     5282        if ( empty( $_POST['type'] ) || empty( $_POST['asset'] ) || empty( $_POST['state'] ) ) {
     5283                wp_send_json_error( array( 'error' => __( 'Invalid data. No selected item.' ) ) );
     5284        }
     5285
     5286        $asset = sanitize_text_field( urldecode( $_POST['asset'] ) );
     5287
     5288        if ( 'enable' !== $_POST['state'] && 'disable' !== $_POST['state'] ) {
     5289                wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown state.' ) ) );
     5290        }
     5291        $state = $_POST['state'];
     5292
     5293        if ( 'plugin' !== $_POST['type'] && 'theme' !== $_POST['type'] ) {
     5294                wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown type.' ) ) );
     5295        }
     5296        $type = $_POST['type'];
     5297
     5298        switch ( $type ) {
     5299                case 'plugin':
     5300                        if ( ! current_user_can( 'update_plugins' ) ) {
     5301                                $error_message = __( 'You do not have permission to modify plugins.' );
     5302                                wp_send_json_error( array( 'error' => $error_message ) );
     5303                        }
     5304
     5305                        $option = 'auto_update_plugins';
     5306                        /** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
     5307                        $all_items = apply_filters( 'all_plugins', get_plugins() );
     5308                        break;
     5309                case 'theme':
     5310                        if ( ! current_user_can( 'update_themes' ) ) {
     5311                                $error_message = __( 'You do not have permission to modify themes.' );
     5312                                wp_send_json_error( array( 'error' => $error_message ) );
     5313                        }
     5314
     5315                        $option    = 'auto_update_themes';
     5316                        $all_items = wp_get_themes();
     5317                        break;
     5318                default:
     5319                        wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown type.' ) ) );
     5320        }
     5321
     5322        if ( ! array_key_exists( $asset, $all_items ) ) {
     5323                $error_message = __( 'Invalid data. The item does not exist.' );
     5324                wp_send_json_error( array( 'error' => $error_message ) );
     5325        }
     5326
     5327        $auto_updates = (array) get_site_option( $option, array() );
     5328
     5329        if ( 'disable' === $state ) {
     5330                $auto_updates = array_diff( $auto_updates, array( $asset ) );
     5331        } else {
     5332                $auto_updates[] = $asset;
     5333                $auto_updates   = array_unique( $auto_updates );
     5334        }
     5335
     5336        // Remove items that have been deleted since the site option was last updated.
     5337        $auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
     5338
     5339        update_site_option( $option, $auto_updates );
     5340
     5341        wp_send_json_success();
     5342}
  • src/wp-admin/includes/class-wp-automatic-updater.php

     
    158158                // Next up, is this an item we can update?
    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 );
    163171                }
     
    501509
    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
    506516                        /**
     
    854864                wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
    855865        }
    856866
     867
    857868        /**
     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
     1047        /**
    8581048         * Prepares and sends an email of a full log of background update results, useful for debugging and geekery.
    8591049         *
    8601050         * @since 3.7.0
  • src/wp-admin/includes/class-wp-debug-data.php

     
    858858                // List all available plugins.
    859859                $plugins        = get_plugins();
    860860                $plugin_updates = get_plugin_updates();
     861                $auto_updates   = array();
    861862
     863                $auto_updates_enabled      = wp_is_auto_update_enabled_for_type( 'plugin' );
     864                $auto_updates_enabled_str  = __( 'Auto-updates enabled' );
     865                $auto_updates_disabled_str = __( 'Auto-updates disabled' );
     866
     867                if ( $auto_updates_enabled ) {
     868                        $auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
     869                }
     870
    862871                foreach ( $plugins as $plugin_path => $plugin ) {
    863872                        $plugin_part = ( is_plugin_active( $plugin_path ) ) ? 'wp-plugins-active' : 'wp-plugins-inactive';
    864873
     
    892901                                $plugin_version_string_debug .= sprintf( ' (latest version: %s)', $plugin_updates[ $plugin_path ]->update->new_version );
    893902                        }
    894903
     904                        if ( $auto_updates_enabled ) {
     905                                if ( in_array( $plugin_path, $auto_updates, true ) ) {
     906                                        $plugin_version_string       .= ' | ' . $auto_updates_enabled_str;
     907                                        $plugin_version_string_debug .= ', ' . $auto_updates_enabled_str;
     908                                } else {
     909                                        $plugin_version_string       .= ' | ' . $auto_updates_disabled_str;
     910                                        $plugin_version_string_debug .= ', ' . $auto_updates_disabled_str;
     911                                }
     912                        }
     913
    895914                        $info[ $plugin_part ]['fields'][ sanitize_text_field( $plugin['Name'] ) ] = array(
    896915                                'label' => $plugin['Name'],
    897916                                'value' => $plugin_version_string,
     
    915934                $active_theme_version       = $active_theme->version;
    916935                $active_theme_version_debug = $active_theme_version;
    917936
     937                $auto_updates         = array();
     938                $auto_updates_enabled = wp_is_auto_update_enabled_for_type( 'theme' );
     939                if ( $auto_updates_enabled ) {
     940                        $auto_updates = (array) get_site_option( 'auto_update_themes', array() );
     941                }
     942
    918943                if ( array_key_exists( $active_theme->stylesheet, $theme_updates ) ) {
    919944                        $theme_update_new_version = $theme_updates[ $active_theme->stylesheet ]->update['new_version'];
    920945
     
    9801005                                'value' => get_stylesheet_directory(),
    9811006                        ),
    9821007                );
     1008                if ( $auto_updates_enabled ) {
     1009                        if ( in_array( $active_theme->stylesheet, $auto_updates ) ) {
     1010                                $theme_auto_update_string = __( 'Enabled' );
     1011                        } else {
     1012                                $theme_auto_update_string = __( 'Disabled' );
     1013                        }
    9831014
     1015                        $info['wp-active-theme']['fields']['auto_update'] = array(
     1016                                'label' => __( 'Auto-update' ),
     1017                                'value' => $theme_auto_update_string,
     1018                                'debug' => $theme_auto_update_string,
     1019                        );
     1020                }
    9841021                $parent_theme = $active_theme->parent();
    9851022
    9861023                if ( $parent_theme ) {
     
    10261063                                        'value' => get_template_directory(),
    10271064                                ),
    10281065                        );
     1066                        if ( $auto_updates_enabled ) {
     1067                                if ( in_array( $parent_theme->stylesheet, $auto_updates ) ) {
     1068                                        $parent_theme_auto_update_string = __( 'Enabled' );
     1069                                } else {
     1070                                        $parent_theme_auto_update_string = __( 'Disabled' );
     1071                                }
     1072
     1073                                $info['wp-parent-theme']['fields']['auto_update'] = array(
     1074                                        'label' => __( 'Auto-update' ),
     1075                                        'value' => $parent_theme_auto_update_string,
     1076                                        'debug' => $parent_theme_auto_update_string,
     1077                                );
     1078                        }
    10291079                }
    10301080
    10311081                // Populate a list of all themes available in the install.
     
    10751125                                $theme_version_string_debug .= sprintf( ' (latest version: %s)', $theme_updates[ $theme_slug ]->update['new_version'] );
    10761126                        }
    10771127
     1128                        if ( $auto_updates_enabled ) {
     1129                                if ( in_array( $theme_slug, $auto_updates ) ) {
     1130                                        $theme_version_string       .= ' | ' . $auto_updates_enabled_str;
     1131                                        $theme_version_string_debug .= ',' . $auto_updates_enabled_str;
     1132                                } else {
     1133                                        $theme_version_string       .= ' | ' . $auto_updates_disabled_str;
     1134                                        $theme_version_string_debug .= ', ' . $auto_updates_disabled_str;
     1135                                }
     1136                        }
     1137
    10781138                        $info['wp-themes-inactive']['fields'][ sanitize_text_field( $theme->name ) ] = array(
    10791139                                'label' => sprintf(
    10801140                                        /* translators: 1: Theme name. 2: Theme slug. */
  • src/wp-admin/includes/class-wp-ms-themes-list-table.php

     
    2323        private $has_items;
    2424
    2525        /**
     26         * Whether to show the auto-updates UI.
     27         *
     28         * @since 5.5.0
     29         *
     30         * @var bool True if auto-updates UI is to be shown, false otherwise.
     31         */
     32        protected $show_autoupdates = true;
     33
     34        /**
    2635         * Constructor.
    2736         *
    2837         * @since 3.1.0
     
    4554                );
    4655
    4756                $status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all';
    48                 if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken' ), true ) ) {
     57                if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken', 'auto-update-enabled', 'auto-update-disabled' ), true ) ) {
    4958                        $status = 'all';
    5059                }
    5160
     
    5665                if ( $this->is_site_themes ) {
    5766                        $this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0;
    5867                }
     68
     69                $this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'theme' ) &&
     70                        ! $this->is_site_themes && current_user_can( 'update_themes' );
    5971        }
    6072
    6173        /**
     
    107119                        'broken'   => $this->is_site_themes ? array() : wp_get_themes( array( 'errors' => true ) ),
    108120                );
    109121
     122                if ( $this->show_autoupdates ) {
     123                        $auto_updates = (array) get_site_option( 'auto_update_themes', array() );
     124
     125                        $themes['auto-update-enabled']  = array();
     126                        $themes['auto-update-disabled'] = array();
     127                }
     128
    110129                if ( $this->is_site_themes ) {
    111130                        $themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' );
    112131                        $allowed_where   = 'site';
     
    131150
    132151                        $filter                    = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled';
    133152                        $themes[ $filter ][ $key ] = $themes['all'][ $key ];
     153
     154                        if ( $this->show_autoupdates ) {
     155                                if ( in_array( $key, $auto_updates, true ) ) {
     156                                        $themes['auto-update-enabled'][ $key ] = $themes['all'][ $key ];
     157                                } else {
     158                                        $themes['auto-update-disabled'][ $key ] = $themes['all'][ $key ];
     159                                }
     160                        }
    134161                }
    135162
    136163                if ( $s ) {
     
    257284         * @return array
    258285         */
    259286        public function get_columns() {
    260                 return array(
     287                $columns = array(
    261288                        'cb'          => '<input type="checkbox" />',
    262289                        'name'        => __( 'Theme' ),
    263290                        'description' => __( 'Description' ),
    264291                );
     292
     293                if ( $this->show_autoupdates ) {
     294                        $columns['auto-updates'] = __( 'Automatic Updates' );
     295                }
     296
     297                return $columns;
    265298        }
    266299
    267300        /**
     
    344377                                                'themes'
    345378                                        );
    346379                                        break;
     380                                case 'auto-update-enabled':
     381                                        /* translators: %s: Number of themes. */
     382                                        $text = _n(
     383                                                'Auto-updates Enabled <span class="count">(%s)</span>',
     384                                                'Auto-updates Enabled <span class="count">(%s)</span>',
     385                                                $count
     386                                        );
     387                                        break;
     388                                case 'auto-update-disabled':
     389                                        /* translators: %s: Number of themes. */
     390                                        $text = _n(
     391                                                'Auto-updates Disabled <span class="count">(%s)</span>',
     392                                                'Auto-updates Disabled <span class="count">(%s)</span>',
     393                                                $count
     394                                        );
     395                                        break;
    347396                        }
    348397
    349398                        if ( $this->is_site_themes ) {
     
    388437                                $actions['delete-selected'] = __( 'Delete' );
    389438                        }
    390439                }
     440
     441                if ( $this->show_autoupdates ) {
     442                        if ( 'auto-update-enabled' !== $status ) {
     443                                $actions['enable-auto-update-selected'] = __( 'Enable Auto-updates' );
     444                        }
     445
     446                        if ( 'auto-update-disabled' !== $status ) {
     447                                $actions['disable-auto-update-selected'] = __( 'Disable Auto-updates' );
     448                        }
     449                }
     450
    391451                return $actions;
    392452        }
    393453
     
    640700        }
    641701
    642702        /**
     703         * Handles the auto-updates column output.
     704         *
     705         * @since 5.5.0
     706         *
     707         * @global string $status
     708         * @global int  $page
     709         *
     710         * @param WP_Theme $theme The current WP_Theme object.
     711         */
     712        public function column_autoupdates( $theme ) {
     713                global $status, $page;
     714
     715                static $auto_updates, $available_updates;
     716
     717                if ( ! $auto_updates ) {
     718                        $auto_updates = (array) get_site_option( 'auto_update_themes', array() );
     719                }
     720                if ( ! $available_updates ) {
     721                        $available_updates = get_site_transient( 'update_themes' );
     722                }
     723
     724                $stylesheet = $theme->get_stylesheet();
     725
     726                if ( in_array( $stylesheet, $auto_updates, true ) ) {
     727                        $text       = __( 'Disable auto-updates' );
     728                        $action     = 'disable';
     729                        $time_class = '';
     730                } else {
     731                        $text       = __( 'Enable auto-updates' );
     732                        $action     = 'enable';
     733                        $time_class = ' hidden';
     734                }
     735
     736                $query_args = array(
     737                        'action'       => "{$action}-auto-update",
     738                        'theme'        => $stylesheet,
     739                        'paged'        => $page,
     740                        'theme_status' => $status,
     741                );
     742
     743                $url = add_query_arg( $query_args, 'themes.php' );
     744
     745                printf(
     746                        '<a href="%s" class="toggle-auto-update" data-wp-action="%s">',
     747                        wp_nonce_url( $url, 'updates' ),
     748                        $action
     749                );
     750
     751                echo '<span class="dashicons dashicons-update spin hidden"></span>';
     752                echo '<span class="label">' . $text . '</span>';
     753                echo '</a>';
     754
     755                $available_updates = get_site_transient( 'update_themes' );
     756                if ( isset( $available_updates->response[ $stylesheet ] ) ) {
     757                        printf(
     758                                '<div class="auto-update-time%s">%s</div>',
     759                                $time_class,
     760                                wp_get_auto_update_message()
     761                        );
     762                }
     763                echo '<div class="auto-updates-error inline notice error hidden"><p></p></div>';
     764        }
     765
     766        /**
    643767         * Handles default column output.
    644768         *
    645769         * @since 4.3.0
     
    721845                                        echo '</td>';
    722846                                        break;
    723847
     848                                case 'auto-updates':
     849                                        echo "<td class='column-auto-updates{$extra_classes}'>";
     850
     851                                        $this->column_autoupdates( $item );
     852
     853                                        echo '</td>';
     854                                        break;
    724855                                default:
    725856                                        echo "<td class='$column_name column-$column_name{$extra_classes}'>";
    726857
  • src/wp-admin/includes/class-wp-plugins-list-table.php

     
    1616 * @see WP_List_Table
    1717 */
    1818class WP_Plugins_List_Table extends WP_List_Table {
     19        /**
     20         * Whether to show the auto-updates UI.
     21         *
     22         * @since 5.5.0
     23         *
     24         * @var bool True if auto-updates UI is to be shown, false otherwise.
     25         */
     26        protected $show_autoupdates = true;
    1927
    2028        /**
    2129         * Constructor.
     
    3947                        )
    4048                );
    4149
    42                 $status_whitelist = array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search', 'paused' );
     50                $status_whitelist = array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search', 'paused', 'auto-update-enabled', 'auto-update-disabled' );
    4351
    4452                $status = 'all';
    4553                if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], $status_whitelist, true ) ) {
     
    5159                }
    5260
    5361                $page = $this->get_pagenum();
     62
     63                $this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'plugin' ) &&
     64                        current_user_can( 'update_plugins' ) &&
     65                        ( ! is_multisite() || $this->screen->in_admin( 'network' ) );
    5466        }
    5567
    5668        /**
     
    103115                        'dropins'            => array(),
    104116                        'paused'             => array(),
    105117                );
     118                if ( $this->show_autoupdates ) {
     119                        $auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
    106120
     121                        $plugins['auto-update-enabled']  = array();
     122                        $plugins['auto-update-disabled'] = array();
     123                }
     124
    107125                $screen = $this->screen;
    108126
    109127                if ( ! is_multisite() || ( $screen->in_admin( 'network' ) && current_user_can( 'manage_network_plugins' ) ) ) {
     
    233251                                // Populate the inactive list with plugins that aren't activated.
    234252                                $plugins['inactive'][ $plugin_file ] = $plugin_data;
    235253                        }
     254
     255                        if ( $this->show_autoupdates ) {
     256                                if ( in_array( $plugin_file, $auto_updates, true ) ) {
     257                                        $plugins['auto-update-enabled'][ $plugin_file ] = $plugins['all'][ $plugin_file ];
     258                                } else {
     259                                        $plugins['auto-update-disabled'][ $plugin_file ] = $plugins['all'][ $plugin_file ];
     260                                }
     261                        }
    236262                }
    237263
    238264                if ( strlen( $s ) ) {
     
    399425        public function get_columns() {
    400426                global $status;
    401427
    402                 return array(
     428                $columns = array(
    403429                        'cb'          => ! in_array( $status, array( 'mustuse', 'dropins' ), true ) ? '<input type="checkbox" />' : '',
    404430                        'name'        => __( 'Plugin' ),
    405431                        'description' => __( 'Description' ),
    406432                );
     433
     434                if ( $this->show_autoupdates ) {
     435                        $columns['auto-updates'] = __( 'Automatic Updates' );
     436                }
     437
     438                return $columns;
    407439        }
    408440
    409441        /**
     
    493525                                                $count
    494526                                        );
    495527                                        break;
     528                                case 'auto-update-enabled':
     529                                        /* translators: %s: Number of plugins. */
     530                                        $text = _n(
     531                                                'Auto-updates Enabled <span class="count">(%s)</span>',
     532                                                'Auto-updates Enabled <span class="count">(%s)</span>',
     533                                                $count
     534                                        );
     535                                        break;
     536                                case 'auto-update-disabled':
     537                                        /* translators: %s: Number of plugins. */
     538                                        $text = _n(
     539                                                'Auto-updates Disabled <span class="count">(%s)</span>',
     540                                                'Auto-updates Disabled <span class="count">(%s)</span>',
     541                                                $count
     542                                        );
     543                                        break;
    496544                        }
    497545
    498546                        if ( 'search' !== $type ) {
     
    533581                        if ( current_user_can( 'delete_plugins' ) && ( 'active' !== $status ) ) {
    534582                                $actions['delete-selected'] = __( 'Delete' );
    535583                        }
     584
     585                        if ( $this->show_autoupdates ) {
     586                                if ( 'auto-update-enabled' !== $status ) {
     587                                        $actions['enable-auto-update-selected'] = __( 'Enable Auto-updates' );
     588                                }
     589                                if ( 'auto-update-disabled' !== $status ) {
     590                                        $actions['disable-auto-update-selected'] = __( 'Disable Auto-updates' );
     591                                }
     592                        }
    536593                }
    537594
    538595                return $actions;
     
    882939
    883940                list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
    884941
     942                $auto_updates      = (array) get_site_option( 'auto_update_plugins', array() );
     943                $available_updates = get_site_transient( 'update_plugins' );
     944
    885945                foreach ( $columns as $column_name => $column_display_name ) {
    886946                        $extra_classes = '';
    887947                        if ( in_array( $column_name, $hidden, true ) ) {
     
    9741034
    9751035                                        echo '</td>';
    9761036                                        break;
     1037                                case 'auto-updates':
     1038                                        if ( ! $this->show_autoupdates ) {
     1039                                                break;
     1040                                        }
     1041
     1042                                        echo "<td class='column-auto-updates{$extra_classes}'>";
     1043
     1044                                        if ( in_array( $plugin_file, $auto_updates, true ) ) {
     1045                                                $text       = __( 'Disable auto-updates' );
     1046                                                $action     = 'disable';
     1047                                                $time_class = '';
     1048                                        } else {
     1049                                                $text       = __( 'Enable auto-updates' );
     1050                                                $action     = 'enable';
     1051                                                $time_class = ' hidden';
     1052                                        }
     1053
     1054                                        $query_args = array(
     1055                                                'action'        => "{$action}-auto-update",
     1056                                                'plugin'        => $plugin_file,
     1057                                                'paged'         => $page,
     1058                                                'plugin_status' => $status,
     1059                                        );
     1060
     1061                                        $url = add_query_arg( $query_args, 'plugins.php' );
     1062
     1063                                        printf(
     1064                                                '<a href="%s" class="toggle-auto-update" data-wp-action="%s">',
     1065                                                wp_nonce_url( $url, 'updates' ),
     1066                                                $action
     1067                                        );
     1068
     1069                                        echo '<span class="dashicons dashicons-update spin hidden"></span>';
     1070                                        echo '<span class="label">' . $text . '</span>';
     1071                                        echo '</a>';
     1072
     1073                                        $available_updates = get_site_transient( 'update_plugins' );
     1074
     1075                                        if ( isset( $available_updates->response[ $plugin_file ] ) ) {
     1076                                                printf(
     1077                                                        '<div class="auto-update-time%s">%s</div>',
     1078                                                        $time_class,
     1079                                                        wp_get_auto_update_message()
     1080                                                );
     1081                                        }
     1082
     1083                                        echo '<div class="inline notice error hidden"><p></p></div>';
     1084                                        echo '</td>';
     1085
     1086                                        break;
    9771087                                default:
    9781088                                        $classes = "$column_name column-$column_name $class";
    9791089
     
    10001110                 * Fires after each row in the Plugins list table.
    10011111                 *
    10021112                 * @since 2.3.0
     1113                 * @since 5.5.0 Added 'Auto-updates Enabled' and 'Auto-updates Disabled' `$status`.
    10031114                 *
    10041115                 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
    10051116                 * @param array  $plugin_data An array of plugin data.
    10061117                 * @param string $status      Status of the plugin. Defaults are 'All', 'Active',
    10071118                 *                            'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use',
    1008                  *                            'Drop-ins', 'Search', 'Paused'.
     1119                 *                            'Drop-ins', 'Search', 'Paused', 'Auto-updates Enabled',
     1120                 *                            'Auto-updates Disabled'.
    10091121                 */
    10101122                do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status );
    10111123
     
    10161128                 * to the plugin file, relative to the plugins directory.
    10171129                 *
    10181130                 * @since 2.7.0
     1131                 * @since 5.5.0 Added 'Auto-updates Enabled' and 'Auto-updates Disabled' `$status`.
    10191132                 *
    10201133                 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
    10211134                 * @param array  $plugin_data An array of plugin data.
    10221135                 * @param string $status      Status of the plugin. Defaults are 'All', 'Active',
    10231136                 *                            'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use',
    1024                  *                            'Drop-ins', 'Search', 'Paused'.
     1137                 *                            'Drop-ins', 'Search', 'Paused', 'Auto-updates Enabled',
     1138                 *                            'Auto-updates Disabled'.
    10251139                 */
    10261140                do_action( "after_plugin_row_{$plugin_file}", $plugin_file, $plugin_data, $status );
    10271141        }
  • src/wp-admin/includes/theme.php

     
    660660
    661661        $parents = array();
    662662
     663        $auto_updates = (array) get_site_option( 'auto_update_themes', array() );
     664
    663665        foreach ( $themes as $theme ) {
    664666                $slug         = $theme->get_stylesheet();
    665667                $encoded_slug = urlencode( $slug );
     
    683685                        );
    684686                }
    685687
     688                $auto_update        = in_array( $slug, $auto_updates, true );
     689                $auto_update_action = $auto_update ? 'disable-auto-update' : 'enable-auto-update';
     690
    686691                $prepared_themes[ $slug ] = array(
    687692                        'id'            => $slug,
    688693                        'name'          => $theme->display( 'Name' ),
     
    699704                        'hasUpdate'     => isset( $updates[ $slug ] ),
    700705                        'hasPackage'    => isset( $updates[ $slug ] ) && ! empty( $updates[ $slug ]['package'] ),
    701706                        'update'        => get_theme_update_available( $theme ),
     707                        'autoupdate'    => $auto_update,
    702708                        'actions'       => array(
    703                                 'activate'  => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&amp;stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null,
    704                                 'customize' => $customize_action,
    705                                 'delete'    => current_user_can( 'delete_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&amp;stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null,
     709                                'activate'   => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&amp;stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null,
     710                                'customize'  => $customize_action,
     711                                'delete'     => current_user_can( 'delete_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&amp;stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null,
     712                                'autoupdate' => wp_is_auto_update_enabled_for_type( 'theme' ) && ! is_multisite() && current_user_can( 'update_themes' )
     713                                        ? wp_nonce_url( admin_url( 'themes.php?action=' . $auto_update_action . '&amp;stylesheet=' . $encoded_slug ), 'updates' )
     714                                        : null,
    706715                        ),
    707716                );
    708717        }
  • src/wp-admin/includes/update.php

     
    435435        $details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $response->slug . '&section=changelog&TB_iframe=true&width=600&height=800' );
    436436
    437437        /** @var WP_Plugins_List_Table $wp_list_table */
    438         $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
     438        $wp_list_table = _get_list_table(
     439                'WP_Plugins_List_Table',
     440                array(
     441                        'screen' => get_current_screen(),
     442                )
     443        );
    439444
    440445        if ( is_network_admin() || ! is_multisite() ) {
    441446                if ( is_network_admin() ) {
     
    933938        </div>
    934939        <?php
    935940}
     941
     942/**
     943 * Checks whether auto-updates are enabled.
     944 *
     945 * @since 5.5.0
     946 *
     947 * @param string $type    The type of update being checked: 'theme' or 'plugin'.
     948 * @return bool True if auto-updates are enabled for `$type`, false otherwise.
     949 */
     950function wp_is_auto_update_enabled_for_type( $type ) {
     951        switch ( $type ) {
     952                case 'plugin':
     953                        /**
     954                         * Filters whether plugins manual auto-update is enabled.
     955                         *
     956                         * @since 5.5.0
     957                         *
     958                         * @param bool $enabled True if plugins auto-update is enabled, false otherwise.
     959                         */
     960                        return apply_filters( 'wp_plugins_auto_update_enabled', true );
     961                case 'theme':
     962                        /**
     963                         * Filters whether plugins manual auto-update is enabled.
     964                         *
     965                         * @since 5.5.0
     966                         *
     967                         * @param bool True if themes auto-update is enabled, false otherwise.
     968                         */
     969                        return apply_filters( 'wp_themes_auto_update_enabled', true );
     970        }
     971
     972        return false;
     973}
     974
     975/**
     976 * Determines the appropriate update message to be displayed.
     977 *
     978 * @since 5.5.0
     979 *
     980 * @return string The update message to be shown.
     981 */
     982function wp_get_auto_update_message() {
     983        $next_update_time = wp_next_scheduled( 'wp_version_check' );
     984
     985        // Check if event exists.
     986        if ( false === $next_update_time ) {
     987                return __( 'There may be a problem with WP-Cron. Automatic update not scheduled.' );
     988        }
     989
     990        // See if cron is disabled
     991        $cron_disabled = defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON;
     992        if ( $cron_disabled ) {
     993                return __( 'WP-Cron is disabled. Automatic updates not available.' );
     994        }
     995
     996        $time_to_next_update = human_time_diff( intval( $next_update_time ) );
     997
     998        // See if cron is overdue.
     999        $overdue = ( time() - $next_update_time ) > 0;
     1000        if ( $overdue ) {
     1001                return sprintf(
     1002                        /* translators: Duration that WP-Cron has been overdue. */
     1003                        __( 'There may be a problem with WP-Cron. Automatic update overdue by %s.' ),
     1004                        $time_to_next_update
     1005                );
     1006        } else {
     1007                return sprintf(
     1008                        /* translators: Time until the next update. */
     1009                        __( 'Auto-update scheduled in %s.' ),
     1010                        $time_to_next_update
     1011                );
     1012        }
     1013}
  • src/wp-admin/network/themes.php

     
    2222$s = isset( $_REQUEST['s'] ) ? $_REQUEST['s'] : '';
    2323
    2424// Clean up request URI from temporary args for screen options/paging uri's to work as expected.
    25 $temp_args              = array( 'enabled', 'disabled', 'deleted', 'error' );
     25$temp_args = array(
     26        'enabled',
     27        'disabled',
     28        'deleted',
     29        'error',
     30        'enabled-auto-update',
     31        'disabled-auto-update',
     32);
     33
    2634$_SERVER['REQUEST_URI'] = remove_query_arg( $temp_args, $_SERVER['REQUEST_URI'] );
    2735$referer                = remove_query_arg( $temp_args, wp_get_referer() );
    2836
     
    123131                                require_once ABSPATH . 'wp-admin/admin-header.php';
    124132                                $themes_to_delete = count( $themes );
    125133                                ?>
    126                         <div class="wrap">
    127                                 <?php if ( 1 == $themes_to_delete ) : ?>
     134                                <div class="wrap">
     135                                <?php if ( 1 === $themes_to_delete ) : ?>
    128136                                        <h1><?php _e( 'Delete Theme' ); ?></h1>
    129137                                        <div class="error"><p><strong><?php _e( 'Caution:' ); ?></strong> <?php _e( 'This theme may be active on other sites in the network.' ); ?></p></div>
    130138                                        <p><?php _e( 'You are about to remove the following theme:' ); ?></p>
     
    145153                                        }
    146154                                        ?>
    147155                                        </ul>
    148                                 <?php if ( 1 == $themes_to_delete ) : ?>
     156                                <?php if ( 1 === $themes_to_delete ) : ?>
    149157                                        <p><?php _e( 'Are you sure you want to delete this theme?' ); ?></p>
    150158                                <?php else : ?>
    151159                                        <p><?php _e( 'Are you sure you want to delete these themes?' ); ?></p>
     
    154162                                        <input type="hidden" name="verify-delete" value="1" />
    155163                                        <input type="hidden" name="action" value="delete-selected" />
    156164                                        <?php
     165
    157166                                        foreach ( (array) $themes as $theme ) {
    158167                                                echo '<input type="hidden" name="checked[]" value="' . esc_attr( $theme ) . '" />';
    159168                                        }
    160169
    161                                                 wp_nonce_field( 'bulk-themes' );
     170                                        wp_nonce_field( 'bulk-themes' );
    162171
    163                                         if ( 1 == $themes_to_delete ) {
     172                                        if ( 1 === $themes_to_delete ) {
    164173                                                submit_button( __( 'Yes, delete this theme' ), '', 'submit', false );
    165174                                        } else {
    166175                                                submit_button( __( 'Yes, delete these themes' ), '', 'submit', false );
    167176                                        }
     177
    168178                                        ?>
    169179                                </form>
    170                                 <?php
    171                                 $referer = wp_get_referer();
    172                                 ?>
     180                                <?php $referer = wp_get_referer(); ?>
    173181                                <form method="post" action="<?php echo $referer ? esc_url( $referer ) : ''; ?>" style="display:inline;">
    174182                                        <?php submit_button( __( 'No, return me to the theme list' ), '', 'submit', false ); ?>
    175183                                </form>
    176                         </div>
     184                                </div>
    177185                                <?php
     186
    178187                                require_once ABSPATH . 'wp-admin/admin-footer.php';
    179188                                exit;
    180189                        } // End if verify-delete.
     
    208217                                )
    209218                        );
    210219                        exit;
     220                case 'enable-auto-update':
     221                case 'disable-auto-update':
     222                case 'enable-auto-update-selected':
     223                case 'disable-auto-update-selected':
     224                        if ( ! ( current_user_can( 'update_themes' ) && wp_is_auto_update_enabled_for_type( 'theme' ) ) ) {
     225                                wp_die( __( 'Sorry, you are not allowed to change themes automatic update settings.' ) );
     226                        }
     227
     228                        if ( 'enable-auto-update' === $action || 'disable-auto-update' === $action ) {
     229                                check_admin_referer( 'updates' );
     230                        } else {
     231                                if ( empty( $_POST['checked'] ) ) {
     232                                        // Nothing to do.
     233                                        wp_safe_redirect( add_query_arg( 'error', 'none', $referer ) );
     234                                        exit;
     235                                }
     236
     237                                check_admin_referer( 'bulk-themes' );
     238                        }
     239
     240                        $auto_updates = (array) get_site_option( 'auto_update_themes', array() );
     241
     242                        if ( 'enable-auto-update' === $action ) {
     243                                $auto_updates[] = $_GET['theme'];
     244                                $auto_updates   = array_unique( $auto_updates );
     245                                $referer        = add_query_arg( 'enabled-auto-update', 1, $referer );
     246                        } elseif ( 'disable-auto-update' === $action ) {
     247                                $auto_updates = array_diff( $auto_updates, array( $_GET['theme'] ) );
     248                                $referer      = add_query_arg( 'disabled-auto-update', 1, $referer );
     249                        } else {
     250                                // Bulk enable/disable.
     251                                $themes = (array) wp_unslash( $_POST['checked'] );
     252
     253                                if ( 'enable-auto-update-selected' === $action ) {
     254                                        $auto_updates = array_merge( $auto_updates, $themes );
     255                                        $auto_updates = array_unique( $auto_updates );
     256                                        $referer      = add_query_arg( 'enabled-auto-update', count( $themes ), $referer );
     257                                } else {
     258                                        $auto_updates = array_diff( $auto_updates, $themes );
     259                                        $referer      = add_query_arg( 'disabled-auto-update', count( $themes ), $referer );
     260                                }
     261                        }
     262
     263                        $all_items = wp_get_themes();
     264
     265                        // Remove themes that don't exist or have been deleted since the option was last updated.
     266                        $auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
     267
     268                        update_site_option( 'auto_update_themes', $auto_updates );
     269
     270                        wp_safe_redirect( $referer );
     271                        exit;
    211272                default:
    212273                        $themes = isset( $_POST['checked'] ) ? (array) $_POST['checked'] : array();
    213274                        if ( empty( $themes ) ) {
     
    284345<?php
    285346if ( isset( $_GET['enabled'] ) ) {
    286347        $enabled = absint( $_GET['enabled'] );
    287         if ( 1 == $enabled ) {
     348        if ( 1 === $enabled ) {
    288349                $message = __( 'Theme enabled.' );
    289350        } else {
    290351                /* translators: %s: Number of themes. */
     
    293354        echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $enabled ) ) . '</p></div>';
    294355} elseif ( isset( $_GET['disabled'] ) ) {
    295356        $disabled = absint( $_GET['disabled'] );
    296         if ( 1 == $disabled ) {
     357        if ( 1 === $disabled ) {
    297358                $message = __( 'Theme disabled.' );
    298359        } else {
    299360                /* translators: %s: Number of themes. */
     
    302363        echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $disabled ) ) . '</p></div>';
    303364} elseif ( isset( $_GET['deleted'] ) ) {
    304365        $deleted = absint( $_GET['deleted'] );
    305         if ( 1 == $deleted ) {
     366        if ( 1 === $deleted ) {
    306367                $message = __( 'Theme deleted.' );
    307368        } else {
    308369                /* translators: %s: Number of themes. */
     
    309370                $message = _n( '%s theme deleted.', '%s themes deleted.', $deleted );
    310371        }
    311372        echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $deleted ) ) . '</p></div>';
    312 } elseif ( isset( $_GET['error'] ) && 'none' == $_GET['error'] ) {
     373} elseif ( isset( $_GET['enabled-auto-update'] ) ) {
     374        $enabled = absint( $_GET['enabled-auto-update'] );
     375        if ( 1 === $enabled ) {
     376                $message = __( 'Theme will be auto-updated.' );
     377        } else {
     378                /* translators: %s: Number of themes. */
     379                $message = _n( '%s theme will be auto-updated.', '%s themes will be auto-updated.', $enabled );
     380        }
     381        echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $enabled ) ) . '</p></div>';
     382} elseif ( isset( $_GET['disabled-auto-update'] ) ) {
     383        $disabled = absint( $_GET['disabled-auto-update'] );
     384        if ( 1 === $disabled ) {
     385                $message = __( 'Theme will no longer be auto-updated.' );
     386        } else {
     387                /* translators: %s: Number of themes. */
     388                $message = _n( '%s theme will no longer be auto-updated.', '%s themes will no longer be auto-updated.', $disabled );
     389        }
     390        echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $disabled ) ) . '</p></div>';
     391} elseif ( isset( $_GET['error'] ) && 'none' === $_GET['error'] ) {
    313392        echo '<div id="message" class="error notice is-dismissible"><p>' . __( 'No theme selected.' ) . '</p></div>';
    314 } elseif ( isset( $_GET['error'] ) && 'main' == $_GET['error'] ) {
     393} elseif ( isset( $_GET['error'] ) && 'main' === $_GET['error'] ) {
    315394        echo '<div class="error notice is-dismissible"><p>' . __( 'You cannot delete a theme while it is active on the main site.' ) . '</p></div>';
    316395}
    317396
     
    324403<?php
    325404$wp_list_table->views();
    326405
    327 if ( 'broken' == $status ) {
     406if ( 'broken' === $status ) {
    328407        echo '<p class="clear">' . __( 'The following themes are installed but incomplete.' ) . '</p>';
    329408}
    330409?>
  • src/wp-admin/plugins.php

     
    2222$s      = isset( $_REQUEST['s'] ) ? urlencode( wp_unslash( $_REQUEST['s'] ) ) : '';
    2323
    2424// Clean up request URI from temporary args for screen options/paging uri's to work as expected.
    25 $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'error', 'deleted', 'activate', 'activate-multi', 'deactivate', 'deactivate-multi', '_error_nonce' ), $_SERVER['REQUEST_URI'] );
     25$query_args_to_remove = array(
     26        'error',
     27        'deleted',
     28        'activate',
     29        'activate-multi',
     30        'deactivate',
     31        'deactivate-multi',
     32        'enabled-auto-update',
     33        'disabled-auto-update',
     34        'enabled-auto-update-multi',
     35        'disabled-auto-update-multi',
     36        '_error_nonce',
     37);
    2638
     39$_SERVER['REQUEST_URI'] = remove_query_arg( $query_args_to_remove, $_SERVER['REQUEST_URI'] );
     40
    2741wp_enqueue_script( 'updates' );
    2842
    2943if ( $action ) {
     
    284298                        if ( ! isset( $_REQUEST['verify-delete'] ) ) {
    285299                                wp_enqueue_script( 'jquery' );
    286300                                require_once ABSPATH . 'wp-admin/admin-header.php';
     301
    287302                                ?>
    288                         <div class="wrap">
     303                                <div class="wrap">
    289304                                <?php
    290                                         $plugin_info              = array();
    291                                         $have_non_network_plugins = false;
     305
     306                                $plugin_info              = array();
     307                                $have_non_network_plugins = false;
     308
    292309                                foreach ( (array) $plugins as $plugin ) {
    293310                                        $plugin_slug = dirname( $plugin );
    294311
     
    315332                                                }
    316333                                        }
    317334                                }
    318                                         $plugins_to_delete = count( $plugin_info );
     335
     336                                $plugins_to_delete = count( $plugin_info );
     337
    319338                                ?>
    320                                 <?php if ( 1 == $plugins_to_delete ) : ?>
     339                                <?php if ( 1 === $plugins_to_delete ) : ?>
    321340                                        <h1><?php _e( 'Delete Plugin' ); ?></h1>
    322341                                        <?php if ( $have_non_network_plugins && is_network_admin() ) : ?>
    323342                                                <div class="error"><p><strong><?php _e( 'Caution:' ); ?></strong> <?php _e( 'This plugin may be active on other sites in the network.' ); ?></p></div>
     
    332351                                <?php endif; ?>
    333352                                        <ul class="ul-disc">
    334353                                                <?php
     354
    335355                                                $data_to_delete = false;
     356
    336357                                                foreach ( $plugin_info as $plugin ) {
    337358                                                        if ( $plugin['is_uninstallable'] ) {
    338359                                                                /* translators: 1: Plugin name, 2: Plugin author. */
     
    343364                                                                echo '<li>', sprintf( _x( '%1$s by %2$s', 'plugin' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] ) . '</em>', '</li>';
    344365                                                        }
    345366                                                }
     367
    346368                                                ?>
    347369                                        </ul>
    348370                                <p>
    349371                                <?php
     372
    350373                                if ( $data_to_delete ) {
    351374                                        _e( 'Are you sure you want to delete these files and data?' );
    352375                                } else {
    353376                                        _e( 'Are you sure you want to delete these files?' );
    354377                                }
     378
    355379                                ?>
    356380                                </p>
    357381                                <form method="post" action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" style="display:inline;">
     
    358382                                        <input type="hidden" name="verify-delete" value="1" />
    359383                                        <input type="hidden" name="action" value="delete-selected" />
    360384                                        <?php
     385
    361386                                        foreach ( (array) $plugins as $plugin ) {
    362387                                                echo '<input type="hidden" name="checked[]" value="' . esc_attr( $plugin ) . '" />';
    363388                                        }
     389
    364390                                        ?>
    365391                                        <?php wp_nonce_field( 'bulk-plugins' ); ?>
    366392                                        <?php submit_button( $data_to_delete ? __( 'Yes, delete these files and data' ) : __( 'Yes, delete these files' ), '', 'submit', false ); ?>
    367393                                </form>
    368394                                <?php
     395
    369396                                $referer = wp_get_referer();
     397
    370398                                ?>
    371399                                <form method="post" action="<?php echo $referer ? esc_url( $referer ) : ''; ?>" style="display:inline;">
    372400                                        <?php submit_button( __( 'No, return me to the plugin list' ), '', 'submit', false ); ?>
    373401                                </form>
    374                         </div>
     402                                </div>
    375403                                <?php
     404
    376405                                require_once ABSPATH . 'wp-admin/admin-footer.php';
    377406                                exit;
    378407                        } else {
     
    385414                        set_transient( 'plugins_delete_result_' . $user_ID, $delete_result );
    386415                        wp_redirect( self_admin_url( "plugins.php?deleted=$plugins_to_delete&plugin_status=$status&paged=$page&s=$s" ) );
    387416                        exit;
    388 
    389417                case 'clear-recent-list':
    390418                        if ( ! is_network_admin() ) {
    391419                                update_option( 'recently_activated', array() );
     
    392420                        } else {
    393421                                update_site_option( 'recently_activated', array() );
    394422                        }
     423
    395424                        break;
    396 
    397425                case 'resume':
    398426                        if ( is_multisite() ) {
    399427                                return;
     
    413441
    414442                        wp_redirect( self_admin_url( "plugins.php?resume=true&plugin_status=$status&paged=$page&s=$s" ) );
    415443                        exit;
     444                case 'enable-auto-update':
     445                case 'disable-auto-update':
     446                case 'enable-auto-update-selected':
     447                case 'disable-auto-update-selected':
     448                        if ( ! current_user_can( 'update_plugins' ) || ! wp_is_auto_update_enabled_for_type( 'plugin' ) ) {
     449                                wp_die( __( 'Sorry, you are not allowed to manage plugins automatic updates.' ) );
     450                        }
    416451
     452                        if ( is_multisite() && ! is_network_admin() ) {
     453                                wp_die( __( 'Please connect to your network admin to manage plugins automatic updates.' ) );
     454                        }
     455
     456                        $redirect = self_admin_url( "plugins.php?plugin_status={$status}&paged={$page}&s={$s}" );
     457
     458                        if ( 'enable-auto-update' === $action || 'disable-auto-update' === $action ) {
     459                                if ( empty( $plugin ) ) {
     460                                        wp_redirect( $redirect );
     461                                        exit;
     462                                }
     463
     464                                check_admin_referer( 'updates' );
     465                        } else {
     466                                if ( empty( $_POST['checked'] ) ) {
     467                                        wp_redirect( $redirect );
     468                                        exit;
     469                                }
     470
     471                                check_admin_referer( 'bulk-plugins' );
     472                        }
     473
     474                        $auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
     475
     476                        if ( 'enable-auto-update' === $action ) {
     477                                $auto_updates[] = $plugin;
     478                                $auto_updates   = array_unique( $auto_updates );
     479                                $redirect       = add_query_arg( array( 'enabled-auto-update' => 'true' ), $redirect );
     480                        } elseif ( 'disable-auto-update' === $action ) {
     481                                $auto_updates = array_diff( $auto_updates, array( $plugin ) );
     482                                $redirect     = add_query_arg( array( 'disabled-auto-update' => 'true' ), $redirect );
     483                        } else {
     484                                $plugins = (array) wp_unslash( $_POST['checked'] );
     485
     486                                if ( 'enable-auto-update-selected' === $action ) {
     487                                        $new_auto_updates = array_merge( $auto_updates, $plugins );
     488                                        $new_auto_updates = array_unique( $new_auto_updates );
     489                                        $query_args       = array( 'enabled-auto-update-multi' => 'true' );
     490                                } else {
     491                                        $new_auto_updates = array_diff( $auto_updates, $plugins );
     492                                        $query_args       = array( 'disabled-auto-update-multi' => 'true' );
     493                                }
     494
     495                                // Return early if all selected plugins already have auto-updates enabled or disabled.
     496                                // Must use non-strict comparison, so that array order is not treated as significant.
     497                                if ( $new_auto_updates == $auto_updates ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
     498                                        wp_redirect( $redirect );
     499                                        exit;
     500                                }
     501
     502                                $auto_updates = $new_auto_updates;
     503                                $redirect     = add_query_arg( $query_args, $redirect );
     504                        }
     505
     506                        /** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
     507                        $all_items = apply_filters( 'all_plugins', get_plugins() );
     508
     509                        // Remove plugins that don't exist or have been deleted since the option was last updated.
     510                        $auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
     511
     512                        update_site_option( 'auto_update_plugins', $auto_updates );
     513
     514                        wp_redirect( $redirect );
     515                        exit;
    417516                default:
    418517                        if ( isset( $_POST['checked'] ) ) {
    419518                                check_admin_referer( 'bulk-plugins' );
     
    498597                echo '</p></div>';
    499598        }
    500599}
    501 ?>
    502600
    503 <?php
    504601if ( isset( $_GET['error'] ) ) :
    505602
    506603        if ( isset( $_GET['main'] ) ) {
     
    521618        } else {
    522619                $errmsg = __( 'Plugin could not be activated because it triggered a <strong>fatal error</strong>.' );
    523620        }
     621
    524622        ?>
    525623        <div id="message" class="error"><p><?php echo $errmsg; ?></p>
    526624        <?php
     625
    527626        if ( ! isset( $_GET['main'] ) && ! isset( $_GET['charsout'] ) && wp_verify_nonce( $_GET['_error_nonce'], 'plugin-activation-error_' . $plugin ) ) {
    528627                $iframe_url = add_query_arg(
    529628                        array(
     
    533632                        ),
    534633                        admin_url( 'plugins.php' )
    535634                );
     635
    536636                ?>
    537         <iframe style="border:0" width="100%" height="70px" src="<?php echo esc_url( $iframe_url ); ?>"></iframe>
     637                <iframe style="border:0" width="100%" height="70px" src="<?php echo esc_url( $iframe_url ); ?>"></iframe>
    538638                <?php
    539639        }
     640
    540641        ?>
    541642        </div>
    542643        <?php
    543644elseif ( isset( $_GET['deleted'] ) ) :
    544                 $delete_result = get_transient( 'plugins_delete_result_' . $user_ID );
    545                 // Delete it once we're done.
    546                 delete_transient( 'plugins_delete_result_' . $user_ID );
     645        $delete_result = get_transient( 'plugins_delete_result_' . $user_ID );
     646        // Delete it once we're done.
     647        delete_transient( 'plugins_delete_result_' . $user_ID );
    547648
    548649        if ( is_wp_error( $delete_result ) ) :
    549650                ?>
     
    562663                <div id="message" class="updated notice is-dismissible">
    563664                        <p>
    564665                                <?php
    565                                 if ( 1 == (int) $_GET['deleted'] ) {
     666                                if ( 1 === (int) $_GET['deleted'] ) {
    566667                                        _e( 'The selected plugin has been deleted.' );
    567668                                } else {
    568669                                        _e( 'The selected plugins have been deleted.' );
     
    570671                                ?>
    571672                        </p>
    572673                </div>
    573                 <?php endif; ?>
     674        <?php endif; ?>
    574675<?php elseif ( isset( $_GET['activate'] ) ) : ?>
    575676        <div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin activated.' ); ?></p></div>
    576677<?php elseif ( isset( $_GET['activate-multi'] ) ) : ?>
     
    583684        <div id="message" class="updated notice is-dismissible"><p><?php _e( 'All selected plugins are up to date.' ); ?></p></div>
    584685<?php elseif ( isset( $_GET['resume'] ) ) : ?>
    585686        <div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin resumed.' ); ?></p></div>
     687<?php elseif ( isset( $_GET['enabled-auto-update'] ) ) : ?>
     688        <div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin will be auto-updated.' ); ?></p></div>
     689<?php elseif ( isset( $_GET['disabled-auto-update'] ) ) : ?>
     690        <div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin will no longer be auto-updated.' ); ?></p></div>
     691<?php elseif ( isset( $_GET['enabled-auto-update-multi'] ) ) : ?>
     692        <div id="message" class="updated notice is-dismissible"><p><?php _e( 'Selected plugins will be auto-updated.' ); ?></p></div>
     693<?php elseif ( isset( $_GET['disabled-auto-update-multi'] ) ) : ?>
     694        <div id="message" class="updated notice is-dismissible"><p><?php _e( 'Selected plugins will no longer be auto-updated.' ); ?></p></div>
    586695<?php endif; ?>
    587696
    588697<div class="wrap">
  • src/wp-admin/themes.php

     
    8181                        wp_redirect( admin_url( 'themes.php?deleted=true' ) );
    8282                }
    8383                exit;
     84        } elseif ( 'enable-auto-update' === $_GET['action'] ) {
     85                if ( ! ( current_user_can( 'update_themes' ) && wp_is_auto_update_enabled_for_type( 'theme' ) ) ) {
     86                        wp_die( __( 'Sorry, you are not allowed to enable themes automatic updates.' ) );
     87                }
     88
     89                check_admin_referer( 'updates' );
     90
     91                $all_items    = wp_get_themes();
     92                $auto_updates = (array) get_site_option( 'auto_update_themes', array() );
     93
     94                $auto_updates[] = $_GET['stylesheet'];
     95                $auto_updates   = array_unique( $auto_updates );
     96                // Remove themes that have been deleted since the site option was last updated.
     97                $auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
     98
     99                update_site_option( 'auto_update_themes', $auto_updates );
     100
     101                wp_redirect( admin_url( 'themes.php?enabled-auto-update=true' ) );
     102
     103                exit;
     104        } elseif ( 'disable-auto-update' === $_GET['action'] ) {
     105                if ( ! ( current_user_can( 'update_themes' ) && wp_is_auto_update_enabled_for_type( 'theme' ) ) ) {
     106                        wp_die( __( 'Sorry, you are not allowed to disable themes automatic updates.' ) );
     107                }
     108
     109                check_admin_referer( 'updates' );
     110
     111                $all_items    = wp_get_themes();
     112                $auto_updates = (array) get_site_option( 'auto_update_themes', array() );
     113
     114                $auto_updates = array_diff( $auto_updates, array( $_GET['stylesheet'] ) );
     115                // Remove themes that have been deleted since the site option was last updated.
     116                $auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
     117
     118                update_site_option( 'auto_update_themes', $auto_updates );
     119
     120                wp_redirect( admin_url( 'themes.php?disabled-auto-update=true' ) );
     121
     122                exit;
    84123        }
    85124}
    86125
     
    228267        ?>
    229268        <div id="message6" class="error"><p><?php _e( 'Theme could not be resumed because it triggered a <strong>fatal error</strong>.' ); ?></p></div>
    230269        <?php
     270} elseif ( isset( $_GET['enabled-auto-update'] ) ) {
     271        ?>
     272        <div id="message7" class="updated notice is-dismissible"><p><?php _e( 'Theme will be auto-updated.' ); ?></p></div>
     273        <?php
     274} elseif ( isset( $_GET['disabled-auto-update'] ) ) {
     275        ?>
     276        <div id="message8" class="updated notice is-dismissible"><p><?php _e( 'Theme will no longer be auto-updated.' ); ?></p></div>
     277        <?php
    231278}
    232279
    233280$ct = wp_get_theme();
     
    581628                                        ?>
    582629                                </p>
    583630
     631                                <# if ( data.actions.autoupdate ) { #>
     632                                <p class="theme-autoupdate">
     633                                <# if ( data.autoupdate ) { #>
     634                                        <a href="{{{ data.actions.autoupdate }}}" class="toggle-auto-update" data-slug="{{ data.id }}" data-wp-action="disable">
     635                                                <span class="dashicons dashicons-update spin hidden"></span>
     636                                                <span class="label"><?php _e( 'Disable auto-updates' ); ?></span>
     637                                        </a>
     638                                <# } else { #>
     639                                        <a href="{{{ data.actions.autoupdate }}}" class="toggle-auto-update" data-slug="{{ data.id }}" data-wp-action="enable">
     640                                                <span class="dashicons dashicons-update spin hidden"></span>
     641                                                <span class="label"><?php _e( 'Enable auto-updates' ); ?></span>
     642                                        </a>
     643                                <# } #>
    584644                                <# if ( data.hasUpdate ) { #>
     645                                        <# if ( data.autoupdate) { #>
     646                                        <span class="auto-update-time"><br /><?php echo wp_get_auto_update_message(); ?></span>
     647                                        <# } else { #>
     648                                        <span class="auto-update-time hidden"><br /><?php echo wp_get_auto_update_message(); ?></span>
     649                                        <# } #>
     650                                <# } #>
     651                                        <span class="auto-updates-error hidden"><p></p></span>
     652                                </p>
     653                                <# } #>
     654
     655                                <# if ( data.hasUpdate ) { #>
    585656                                <div class="notice notice-warning notice-alt notice-large">
    586657                                        <h3 class="notice-title"><?php _e( 'Update Available' ); ?></h3>
    587658                                        {{{ data.update }}}
  • src/wp-admin/update-core.php

     
    328328
    329329        <tbody class="plugins">
    330330        <?php
     331
     332        $auto_updates = array();
     333        if ( wp_is_auto_update_enabled_for_type( 'plugin' ) ) {
     334                $auto_updates       = (array) get_site_option( 'auto_update_plugins', array() );
     335                $auto_update_notice = ' | ' . wp_get_auto_update_message();
     336        }
     337
    331338        foreach ( (array) $plugins as $plugin_file => $plugin_data ) {
    332339                $plugin_data = (object) _get_plugin_data_markup_translate( $plugin_file, (array) $plugin_data, false, true );
    333340
     
    419426                                $plugin_data->update->new_version
    420427                        );
    421428                        echo ' ' . $details . $compat . $upgrade_notice;
     429                        if ( in_array( $plugin_file, $auto_updates, true ) ) {
     430                                echo $auto_update_notice;
     431                        }
    422432                        ?>
    423433                </p></td>
    424434        </tr>
     
    478488
    479489        <tbody class="plugins">
    480490        <?php
     491        $auto_updates = array();
     492        if ( wp_is_auto_update_enabled_for_type( 'theme' ) ) {
     493                $auto_updates       = (array) get_site_option( 'auto_update_themes', array() );
     494                $auto_update_notice = ' | ' . wp_get_auto_update_message();
     495        }
     496
    481497        foreach ( $themes as $stylesheet => $theme ) {
    482498                $checkbox_id = 'checkbox_' . md5( $theme->get( 'Name' ) );
     499
    483500                ?>
    484501        <tr>
    485502                <td class="check-column">
     
    501518                                $theme->display( 'Version' ),
    502519                                $theme->update['new_version']
    503520                        );
     521                        if ( in_array( $stylesheet, $auto_updates, true ) ) {
     522                                echo $auto_update_notice;
     523                        }
    504524                        ?>
    505525                </p></td>
    506526        </tr>
  • src/wp-includes/script-loader.php

     
    15201520                                        /* translators: %s: Number of plugins. */
    15211521                                        'pluginsFound'             => __( 'Number of plugins found: %d' ),
    15221522                                        'noPluginsFound'           => __( 'No plugins found. Try a different search.' ),
     1523                                        'autoUpdatesEnable'        => __( 'Enable auto-updates' ),
     1524                                        'autoUpdatesEnabling'      => __( 'Enabling...' ),
     1525                                        'autoUpdatesEnabled'       => __( 'Auto-updates enabled' ),
     1526                                        'autoUpdatesDisable'       => __( 'Disable auto-updates' ),
     1527                                        'autoUpdatesDisabling'     => __( 'Disabling...' ),
     1528                                        'autoUpdatesDisabled'      => __( 'Auto-updates disabled' ),
     1529                                        'autoUpdatesError'         => __( 'The request could not be completed.' ),
    15231530                                ),
    15241531                        )
    15251532                );