WordPress.org

Make WordPress Core

Ticket #34676: 34676.5.diff

File 34676.5.diff, 69.6 KB (added by bookdude13, 5 months ago)

Refreshed patch 5

  • src/js/_enqueues/admin/common.js

    diff --git src/js/_enqueues/admin/common.js src/js/_enqueues/admin/common.js
    index 75c77b3bac..488bbd80aa 100644
    $document.ready( function() { 
    15961596                 * notice. Make sure it gets moved just the first time.
    15971597                 */
    15981598                if ( ! $progressDiv.hasClass( 'update-details-moved' ) ) {
    1599                         $progressDiv.insertAfter( $updateNotice ).addClass( 'update-details-moved' );
     1599                        $progressDiv.appendTo( $updateNotice ).addClass( 'update-details-moved' );
    16001600                }
    16011601
    16021602                // Toggle the progress div visibility.
  • src/wp-admin/about.php

    diff --git src/wp-admin/about.php src/wp-admin/about.php
    index ead0e82c79..730ce6b28d 100644
    require_once ABSPATH . 'wp-admin/admin-header.php'; 
    4545                <div class="about__section is-feature">
    4646                        <?php _e( 'Say hello to more and better.' ); ?>
    4747                        <br />
    48                         <?php _e( 'More ways to make your pages come alive. With easier ways to get it all done and looking better than everand boosts in speed you can feel.' ); ?>
     48                        <?php _e( 'More ways to make your pages come alive. With easier ways to get it all done and looking better than ever&mdash;and boosts in speed you can feel.' ); ?>
    4949                </div>
    5050
    5151                <div class="about__section is-feature">
    require_once ABSPATH . 'wp-admin/admin-header.php'; 
    6565                                <?php _e( 'More ways to make posts and pages come alive with your best images.' ); ?>
    6666                        </p>
    6767                        <p>
    68                                 <?php _e( 'More ways to bring your visitors in, and keep them engaged, with the richness of embedded media from the webs top services.' ); ?>
     68                                <?php _e( 'More ways to bring your visitors in, and keep them engaged, with the richness of embedded media from the web&#8217;s top services.' ); ?>
    6969                        </p>
    7070                        <p>
    71                                 <?php _e( 'More ways to make your vision real, and put blocks in the perfect place — even if a particular kind of block is new to you. More efficient processes.' ); ?>
     71                                <?php _e( 'More ways to make your vision real, and put blocks in the perfect place&mdash;even if a particular kind of block is new to you. More efficient processes.' ); ?>
    7272                        </p>
    7373                        <p>
    7474                                <?php _e( 'And more speed everywhere, so as you build sections or galleries, or just type in a line of prose, you can feel how much faster your work flows.' ); ?>
    require_once ABSPATH . 'wp-admin/admin-header.php'; 
    8686                        <div class="column is-vertically-aligned-center">
    8787                                <h2><?php _e( 'Two new blocks. And better blocks overall.' ); ?></h2>
    8888                                <ul>
    89                                         <li><?php _e( 'Two brand-new blocks: Social Links and Buttons make adding interactive features fast and easy.' ); ?></li>
     89                                        <li><?php _e( 'Two brand-new blocks: Social Icons and Buttons make adding interactive features fast and easy.' ); ?></li>
    9090                                        <li><?php _e( 'New ways with color: Gradients in the Buttons and Cover block, toolbar access to color options in Rich Text blocks, and for the first time, color options in the Group and Columns blocks.' ); ?></li>
    9191                                        <li><?php _e( 'Guess a whole lot less! Version 5.4 streamlines the whole process for placing and replacing multimedia in every block. Now it works the same way in almost every block!' ); ?></li>
    92                                         <li><?php _e( 'And if you’ve ever thought your image in the Media+Text block should link to something else — perhaps a picture of a brochure should download that brochure as a document? Well, now it can.' ); ?></li>
     92                                        <li><?php _e( 'And if you&#8217;ve ever thought your image in the Media+Text block should link to something else&mdash;perhaps a picture of a brochure should download that brochure as a document? Well, now it can.' ); ?></li>
    9393                                </ul>
    9494                        </div>
    9595                </div>
    require_once ABSPATH . 'wp-admin/admin-header.php'; 
    101101                                        <li><?php _e( 'Clearer block navigation with block breadcrumbs. And easier selection once you get there.' ); ?></li>
    102102                                        <li><?php _e( 'For when you need to navigate with the keyboard, better tabbing and focus. Plus, you can tab over to the sidebar of nearly any block.' ); ?></li>
    103103                                        <li><?php _e( 'Speed! 14% faster loading of the editor, 51% faster time-to-type!' ); ?></li>
    104                                         <li><?php _e( 'Tips are gone. In their place, a Welcome Guide window you can bring up when you need it—and only when you need it—again and again.' ); ?></li>
    105                                         <li><?php _e( 'Know at a glance whether you’re in a block’s Edit or Navigation mode. Or, if you have restricted vision, your screen reader will tell you which mode you’re in.' ); ?></li>
     104                                        <li><?php _e( 'Tips are gone. In their place, a Welcome Guide window you can bring up when you need it&mdash;and only when you need it&mdash;again and again.' ); ?></li>
     105                                        <li><?php _e( 'Know at a glance whether you&#8217;re in a block&#8217;s Edit or Navigation mode. Or, if you have restricted vision, your screen reader will tell you which mode you&#8217;re in.' ); ?></li>
    106106                                </ul>
    107                                 <p><?php _e( 'Of course, if you want to work with the very latest tools and features, install the <a href="https://wordpress.org/plugins/gutenberg/">Gutenberg plugin</a>. Youll get to be the first to use new and exciting features in the block editor, before anyone else has seen them!' ); ?></p>
     107                                <p><?php _e( 'Of course, if you want to work with the very latest tools and features, install the <a href="https://wordpress.org/plugins/gutenberg/">Gutenberg plugin</a>. You&#8217;ll get to be the first to use new and exciting features in the block editor, before anyone else has seen them!' ); ?></p>
    108108                        </div>
    109109                        <div class="column is-edge-to-edge has-accent-background-color">
    110110                                <div class="about__image aligncenter">
    require_once ABSPATH . 'wp-admin/admin-header.php'; 
    124124                                <p><?php _e( '5.4 helps with a variety of privacy issues around the world. So when users and stakeholders ask about regulatory compliance, or how your team handles user data, the answers should be a lot easier to get right.' ); ?></p>
    125125                                <p><?php _e( 'Take a look:' ); ?></p>
    126126                                <ul>
    127                                         <li><?php _e( 'Personal Data Exports include more useful data about what you’ve done in sessions. Plus, a table of contents!' ); ?></li>
    128                                         <li><?php _e( 'See where you are when you use Privacy Tools Tables, whether you’re erasing or exporting.' ); ?></li>
    129                                         <li><?php _e( 'Plus, little enhancements throughout give the Privacy tools a little cleaner look. Your eyes will thank you!' ); ?></li>
     127                                        <li><?php _e( 'Now personal data exports include users session information and users location data from the community events widget. Plus, a table of contents!' ); ?></li>
     128                                        <li><?php _e( 'See progress as you process export and erasure requests through the privacy tools.' ); ?></li>
     129                                        <li><?php _e( 'Plus, little enhancements throughout give the privacy tools a little cleaner look. Your eyes will thank you!' ); ?></li>
    130130                                </ul>
    131131                        </div>
    132132                </div>
    require_once ABSPATH . 'wp-admin/admin-header.php'; 
    139139                        <div class="column">
    140140                                <h3><?php _e( 'Add custom fields to menu items—natively' ); ?></h3>
    141141                                <p>
    142                                         <?php _e( 'Two new actions let you add custom fields to menu itemswithout a plugin and without writing custom walkers.' ); ?>
     142                                        <?php _e( 'Two new actions let you add custom fields to menu items&mdash;without a plugin and without writing custom walkers.' ); ?>
    143143                                </p>
    144144                                <p>
    145145                                        <?php
    require_once ABSPATH . 'wp-admin/admin-header.php'; 
    160160                                        ?>
    161161                                </p>
    162162                                <p>
    163                                         <?php _e( 'Check your code and see where these new actions can replace your custom code, and if youre concerned about duplication, add a check for the WordPress version.' ); ?>
     163                                        <?php _e( 'Check your code and see where these new actions can replace your custom code, and if you&#8217;re concerned about duplication, add a check for the WordPress version.' ); ?>
    164164                                </p>
    165165                        </div>
    166166                        <div class="column">
    require_once ABSPATH . 'wp-admin/admin-header.php'; 
    179179                                <?php
    180180                                printf(
    181181                                        /* translators: %s: WordPress 5.4 Field Guide link. */
    182                                         __( 'There’s lots more for developers to love in WordPress 5.4. To discover more and learn how to make these changes shine on your on your sites, themes, plugins and more, check the <a href="%s">WordPress 5.4 Field Guide.</a>' ),
     182                                        __( 'There&#8217;s lots more for developers to love in WordPress 5.4. To discover more and learn how to make these changes shine on your on your sites, themes, plugins and more, check the <a href="%s">WordPress 5.4 Field Guide</a>.' ),
    183183                                        'https://make.wordpress.org/core/?p=80034'
    184184                                );
    185185                                ?>
    186186                        </p>
    187                         <p>
    188                                 <?php _e( 'Finally, a note about tooling. If you’re a Composer fan, version 5.4 supports this more modern tooling for PHPUnit and external libraries.' ); ?>
    189                         </p>
    190187                </div>
    191188
    192189                <hr />
  • src/wp-admin/css/color-picker.css

    diff --git src/wp-admin/css/color-picker.css src/wp-admin/css/color-picker.css
    index beec82636d..387883f828 100644
     
    7171}
    7272
    7373.wp-picker-input-wrap .button.wp-picker-default,
    74 .wp-customizer .wp-picker-input-wrap .button.wp-picker-default {
     74.wp-picker-input-wrap .button.wp-picker-clear,
     75.wp-customizer .wp-picker-input-wrap .button.wp-picker-default,
     76.wp-customizer .wp-picker-input-wrap .button.wp-picker-clear {
    7577        margin-left: 6px;
    7678        padding: 0 8px;
    7779        line-height: 2.54545455; /* 28px */
     
    142144                padding: 0 5px;
    143145        }
    144146
    145         .wp-picker-input-wrap .button.wp-picker-default {
     147        .wp-picker-input-wrap .button.wp-picker-default,
     148        .wp-picker-input-wrap .button.wp-picker-clear {
    146149                padding: 0 8px;
    147150                line-height: 2.14285714; /* 30px */
    148151                min-height: 32px;
    149152        }
    150153
    151         .wp-customizer .wp-picker-input-wrap .button.wp-picker-default {
     154        .wp-customizer .wp-picker-input-wrap .button.wp-picker-default,
     155        .wp-customizer .wp-picker-input-wrap .button.wp-picker-clear {
    152156                padding: 0 8px;
    153157                font-size: 14px;
    154158                line-height: 2.14285714; /* 30px */
  • src/wp-admin/css/common.css

    diff --git src/wp-admin/css/common.css src/wp-admin/css/common.css
    index 5c97f14453..e88cba5d27 100644
    code { 
    560560        margin-left: 0;
    561561}
    562562
     563.update-php .update-maintenance-start {
     564        margin-top: 30px;
     565}
     566
     567.update-php .update-maintenance-content {
     568        border-left: 2px dashed #aaa;
     569        padding: 1px 0 20px 20px;
     570        margin: -10px 0;
     571}
     572
     573.update-php .update-maintenance-end {
     574        margin-bottom: 30px;
     575}
     576
    563577.no-js .widefat thead .check-column input,
    564578.no-js .widefat tfoot .check-column input {
    565579        display: none;
  • src/wp-admin/css/themes.css

    diff --git src/wp-admin/css/themes.css src/wp-admin/css/themes.css
    index 4b793a0fd2..fed12dcf89 100644
    body.folded .theme-browser ~ .theme-overlay .theme-wrap { 
    896896        .theme-browser .theme:nth-child(3n) {
    897897                margin-right: 0;
    898898        }
     899       
     900        .theme-overlay .theme-about {
     901                bottom: 105px;
     902        }
     903
     904        .theme-overlay .theme-actions {
     905                padding-left: 4%;
     906                padding-right: 4%;
     907        }
    899908}
    900909
    901910@media only screen and (max-width: 650px) {
  • src/wp-admin/includes/class-bulk-plugin-upgrader-skin.php

    diff --git src/wp-admin/includes/class-bulk-plugin-upgrader-skin.php src/wp-admin/includes/class-bulk-plugin-upgrader-skin.php
    index 308cacf553..7d84730931 100644
    class Bulk_Plugin_Upgrader_Skin extends Bulk_Upgrader_Skin { 
    2222                parent::add_strings();
    2323                /* translators: 1: Plugin name, 2: Number of the plugin, 3: Total number of plugins being updated. */
    2424                $this->upgrader->strings['skin_before_update_header'] = __( 'Updating Plugin %1$s (%2$d/%3$d)' );
     25                $this->upgrader->strings['bulk_download']             = __( 'Downloading plugin installers.' );
    2526        }
    2627
    2728        /**
    28          * @param string $title
     29         * Outputs copy before workload output.
     30         *
     31         * @param string $title Title or string identifier to use.
     32         *
     33         * @return void
    2934         */
    3035        public function before( $title = '' ) {
    31                 parent::before( $this->plugin_info['Title'] );
     36                $title = ( '' === $title ) ? $this->plugin_info['Title'] : $title;
     37                parent::before( $title );
    3238        }
    3339
    3440        /**
    35          * @param string $title
     41         * Outputs copy after workload output.
     42         *
     43         * @param string $title Title or string identifier to use.
     44         *
     45         * @return void
    3646         */
    3747        public function after( $title = '' ) {
    38                 parent::after( $this->plugin_info['Title'] );
     48                $title = ( $title === '' ) ? $this->plugin_info['Title'] : $title;
     49                parent::after( $title );
    3950                $this->decrement_update_count( 'plugin' );
    4051        }
    4152
    4253        /**
     54         * Outputs copy after bulk actions are all done.
     55         *
     56         * @return void
    4357         */
    4458        public function bulk_footer() {
    4559                parent::bulk_footer();
  • src/wp-admin/includes/class-bulk-theme-upgrader-skin.php

    diff --git src/wp-admin/includes/class-bulk-theme-upgrader-skin.php src/wp-admin/includes/class-bulk-theme-upgrader-skin.php
    index d3f0c914ea..c26541b779 100644
     
    1616 * @see Bulk_Upgrader_Skin
    1717 */
    1818class Bulk_Theme_Upgrader_Skin extends Bulk_Upgrader_Skin {
    19         public $theme_info = array(); // Theme_Upgrader::bulk_upgrade() will fill this in.
     19        /**
     20         * Theme information, which will be filled by Theme_Upgrader::bulk_upgrade()
     21         * @var array
     22         */
     23        public $theme_info = array();
    2024
     25        /**
     26         * Registers strings that will be used.
     27         *
     28         * @return void
     29         */
    2130        public function add_strings() {
    2231                parent::add_strings();
    2332                /* translators: 1: Theme name, 2: Number of the theme, 3: Total number of themes being updated. */
    2433                $this->upgrader->strings['skin_before_update_header'] = __( 'Updating Theme %1$s (%2$d/%3$d)' );
     34                $this->upgrader->strings['bulk_download']             = __( 'Downloading theme installers.' );
    2535        }
    2636
    2737        /**
    28          * @param string $title
     38         * Outputs copy before workload output.
     39         *
     40         * @param string $title Title or string identifier to use.
     41         *
     42         * @return void
    2943         */
    3044        public function before( $title = '' ) {
    31                 parent::before( $this->theme_info->display( 'Name' ) );
     45                $title = ( $title === '' ) ? $this->theme_info->display( 'Name' ) : $title;
     46                parent::before( $title );
    3247        }
    3348
    3449        /**
    35          * @param string $title
     50         * Outputs copy after workload output.
     51         *
     52         * @param string $title Title or string identifier to use.
     53         *
     54         * @return void
    3655         */
    3756        public function after( $title = '' ) {
    38                 parent::after( $this->theme_info->display( 'Name' ) );
     57                $title = ( $title === '' ) ? $this->theme_info->display( 'Name' ) : $title;
     58                parent::after( $title );
    3959                $this->decrement_update_count( 'theme' );
    4060        }
    4161
    4262        /**
     63         * Outputs copy after bulk actions are all done.
     64         *
     65         * @return void
    4366         */
    4467        public function bulk_footer() {
    4568                parent::bulk_footer();
  • new file src/wp-admin/includes/class-bulk-upgrade-element-base.php

    diff --git src/wp-admin/includes/class-bulk-upgrade-element-base.php src/wp-admin/includes/class-bulk-upgrade-element-base.php
    new file mode 100644
    index 0000000000..6c237616d8
    - +  
     1<?php
     2
     3/**
     4 * Abstract base class for Bulk Upgrade Elements
     5 *
     6 * @since 5.5.0
     7 */
     8abstract class WP_Bulk_Upgrade_Element_Base {
     9        /**
     10         * Is this element already up-to-date
     11         *
     12         * @var bool
     13         */
     14        protected $up_to_date = false;
     15       
     16        /**
     17         * Has the package been downloaded
     18         *
     19         * @var bool
     20         */
     21        protected $downloaded = false;
     22       
     23        /**
     24         * Was the package unpacked properly
     25         *
     26         * @var bool
     27         */
     28        protected $unpacked = false;
     29       
     30        /**
     31         * Has the package been installed
     32         *
     33         * @var bool
     34         */
     35        protected $installed = false;
     36
     37        /**
     38         * The verification status of a download
     39
     40         * @var bool|WP_Error
     41         */
     42        protected $download_verification_result = false;
     43
     44        /**
     45         * Identifier for this element (source)
     46         *
     47         * @var mixed
     48         */
     49        protected $name;
     50       
     51        /**
     52         * Upgrader to use
     53         *
     54         * @var WP_Upgrader
     55         */
     56        protected $upgrader;
     57
     58        /**
     59         * Options of current element, used throughout the process
     60         *
     61         * @var array
     62         */
     63        protected $options;
     64       
     65        /**
     66         * Info about the current element, used by the upgrader
     67         *
     68         * @var mixed
     69         */
     70        protected $info;
     71       
     72        /**
     73         * Name of the download
     74         *
     75         * @var string
     76         */
     77        protected $download;
     78       
     79        /**
     80         * Working dir for the unpacked package
     81         *
     82         * @var string
     83         */
     84        protected $working_dir;
     85
     86        /**
     87         * Final result of installation (via upgrader)
     88         *
     89         * @var mixed
     90         */
     91        protected $result;
     92
     93        /**
     94         * WP_Bulk_Upgrader_Element constructor.
     95         *
     96         * @param WP_Upgrader $upgrader
     97         * @param mixed       $name
     98         *
     99         * @since 5.5.0
     100         * @access public
     101         */
     102        public function __construct( $name, WP_Upgrader $upgrader ) {
     103                $this->name     = $name;
     104                $this->upgrader = $upgrader;
     105        }
     106
     107        /**
     108         * Retrievs the original identifier data.
     109         *
     110         * @return mixed
     111         *
     112         * @since 5.5.0
     113         * @access public
     114         */
     115        public function get_name() {
     116                return $this->name;
     117        }
     118
     119        /**
     120         * Retrieves the cummulated result of the upgrade.
     121         *
     122         * @return bool
     123         *
     124         * @since 5.5.0
     125         * @access public
     126         */
     127        public function get_result() {
     128                return isset( $this->result ) ? $this->result : $this->installed;
     129        }
     130
     131        /**
     132         * Retrieves the result index for the current result.
     133         *
     134         * @return bool|int
     135         *
     136         * @since 5.5.0
     137         * @access public
     138         */
     139        public function get_result_index() {
     140                return false;
     141        }
     142
     143        /**
     144         * Determines if it is active in the system.
     145         *
     146         * @return boolean
     147         *
     148         * @since 5.5.0
     149         * @access public
     150         */
     151        abstract public function is_active();
     152
     153        /**
     154         * Determines if it is downloaded correctly.
     155         *
     156         * @return bool
     157         *
     158         * @since 5.5.0
     159         * @access public
     160         */
     161        public function is_downloaded() {
     162                return $this->downloaded;
     163        }
     164
     165        /**
     166         * Determines if it is unpacked succesfully.
     167         *
     168         * @return bool
     169         *
     170         * @since 5.5.0
     171         * @access public
     172         */
     173        public function is_unpacked() {
     174                return $this->unpacked;
     175        }
     176
     177        /**
     178         * Determines if it is installed succesfully.
     179         *
     180         * @return bool
     181         *
     182         * @since 5.5.0
     183         * @access public
     184         */
     185        public function is_installed() {
     186                return $this->installed;
     187        }
     188
     189        /**
     190         * Determines if it is already up-to-date.
     191         *
     192         * @return bool
     193         *
     194         * @since 5.5.0
     195         * @access public
     196         */
     197        public function is_up_to_date() {
     198                return $this->up_to_date;
     199        }
     200
     201        /**
     202         * Retrieves element info.
     203         *
     204         * @return mixed
     205         *
     206         * @since 5.5.0
     207         * @access public
     208         */
     209        public function get_info() {
     210                return $this->info;
     211        }
     212
     213        /**
     214         * Applies defaults and filter to options.
     215         *
     216         * @param array $options Options to use.
     217         *
     218         * @return void
     219         *
     220         * @since 5.5.0
     221         * @access protected
     222         */
     223        protected function set_options( $options ) {
     224                $defaults = array(
     225                        'package'                     => '',
     226                        // Please always pass this.
     227                        'destination'                 => '',
     228                        // And this
     229                        'clear_destination'           => false,
     230                        'abort_if_destination_exists' => true,
     231                        // Abort if the Destination directory exists, Pass clear_destination as false please.
     232                        'clear_working'               => true,
     233                        'is_multi'                    => false,
     234                        'hook_extra'                  => array()
     235                        // Pass any extra $hook_extra args here, this will be passed to any hooked filters.
     236                );
     237
     238                $options = wp_parse_args( $options, $defaults );
     239
     240                /** This filter is documented in wp-admin/includes/class-wp-upgrader.php */
     241                $this->options = apply_filters( 'upgrader_package_options', $options );
     242        }
     243
     244        /**
     245         * Download this element.
     246         *
     247         * @return bool|string|WP_Error
     248         *
     249         * @since 5.5.0
     250         * @access public
     251         */
     252        public function download() {
     253                if ( $this->is_up_to_date() ) {
     254                        return false;
     255                }
     256
     257                // Connect to the Filesystem first.
     258                $result = $this->upgrader->fs_connect( array( WP_CONTENT_DIR, $this->options['destination'] ) );
     259                // Mainly for non-connected filesystem.
     260                if ( ! $result || is_wp_error( $result ) ) {
     261                        return $result;
     262                }
     263
     264                $this->download_verification_result = true;
     265
     266                /*
     267                 * Download the package (Note, This just returns the filename
     268                 * of the file if the package is a local file)
     269                 */
     270                $result = $this->upgrader->download_package( $this->options['package'], true );
     271
     272                if ( ! is_wp_error( $result ) ) {
     273                        $this->downloaded = true;
     274                        $this->download   = $result;
     275                } else {
     276                        $filename = $result->get_error_data( 'softfail-filename' );
     277                        if ( $filename ) {
     278                                $this->download_verification_result = $result;
     279
     280                                $result = $filename;
     281
     282                                $this->downloaded = true;
     283                                $this->download   = $result;
     284                        }
     285                }
     286
     287                return $result;
     288        }
     289
     290        /**
     291         * Unpacks this element.
     292         *
     293         * @return bool|string|WP_Error
     294         *
     295         * @since 5.5.0
     296         * @access public
     297         */
     298        public function unpack() {
     299                if ( ! $this->is_downloaded() ) {
     300                        return false;
     301                }
     302
     303                // Do not delete a "local" file
     304                $delete_package = ( $this->download !== $this->options['package'] );
     305
     306                // Unzips the file into a temporary directory.
     307                $result = $this->upgrader->unpack_package( $this->download, $delete_package );
     308                if ( ! is_wp_error( $result ) ) {
     309                        $this->unpacked    = true;
     310                        $this->working_dir = $result;
     311                }
     312
     313                return $result;
     314        }
     315
     316        /**
     317         * Installs this element.
     318         *
     319         * @return array|bool|WP_Error
     320         *
     321         * @since 5.5.0
     322         * @access public
     323         */
     324        public function install() {
     325                if ( ! $this->is_unpacked() ) {
     326                        return false;
     327                }
     328
     329                // With the given options, this installs it to the destination directory.
     330                $result = $this->upgrader->install_package( array(
     331                        'source'                      => $this->working_dir,
     332                        'destination'                 => $this->options['destination'],
     333                        'clear_destination'           => $this->options['clear_destination'],
     334                        'abort_if_destination_exists' => $this->options['abort_if_destination_exists'],
     335                        'clear_working'               => $this->options['clear_working'],
     336                        'hook_extra'                  => $this->options['hook_extra']
     337                ) );
     338
     339                $this->result = $this->upgrader->result;
     340
     341                return $result;
     342        }
     343
     344        /**
     345         * Retrieves the verification result status.
     346         *
     347         * @return bool|WP_Error
     348         *
     349         * @since  5.5.0
     350         * @access public
     351         */
     352        public function get_verification_result() {
     353                return $this->download_verification_result;
     354        }
     355}
     356 No newline at end of file
  • new file src/wp-admin/includes/class-bulk-upgrade-repository-element-base.php

    diff --git src/wp-admin/includes/class-bulk-upgrade-repository-element-base.php src/wp-admin/includes/class-bulk-upgrade-repository-element-base.php
    new file mode 100644
    index 0000000000..ef25b3d300
    - +  
     1<?php
     2
     3/**
     4 * Abstract base class for Bulk Upgrade Elements that are formatted as Plugin/Theme.
     5 *
     6 * @since 5.5.0
     7 */
     8abstract class WP_Bulk_Upgrade_Repository_Element_Base extends WP_Bulk_Upgrade_Element_Base {
     9        /**
     10         * Cache for current element type information.
     11         *
     12         * @var object
     13         */
     14        protected static $current;
     15
     16        /**
     17         * Current element response information from repository.
     18         *
     19         * @var object
     20         */
     21        protected $response;
     22
     23        /**
     24         * Retrieves the result index for the current item.
     25         *
     26         * @return mixed
     27         *
     28         * @since  5.5.0
     29         * @access public
     30         */
     31        public function get_result_index() {
     32                return $this->name;
     33        }
     34
     35        /**
     36         * Retrieves the current item.
     37         *
     38         * @return mixed
     39         *
     40         * @since 5.5.0
     41         * @access protected
     42         */
     43        abstract protected function get_current();
     44
     45        /**
     46         * Retrieves plugin repository response.
     47         *
     48         * @return bool|object Response from the respository as stdClass
     49         *
     50         * @since  5.5.0
     51         * @access protected
     52         */
     53        protected function get_response() {
     54                $current = $this->get_current();
     55
     56                if ( is_object( $current ) && is_array( $current->response ) ) {
     57                        return $this->response = isset( $current->response[ $this->name ] ) ? $current->response[ $this->name ] : false;
     58                }
     59
     60                return false;
     61        }
     62}
     63 No newline at end of file
  • new file src/wp-admin/includes/class-bulk-upgrader-base.php

    diff --git src/wp-admin/includes/class-bulk-upgrader-base.php src/wp-admin/includes/class-bulk-upgrader-base.php
    new file mode 100644
    index 0000000000..a4780a58d3
    - +  
     1<?php
     2
     3/**
     4 * Abstract base class for Bulk Upgrades.
     5 *
     6 * @since 5.5.0
     7 */
     8abstract class WP_Bulk_Upgrader_Base {
     9        /**
     10         * Upgrader to use.
     11         *
     12         * @var WP_Upgrader
     13         */
     14        protected $upgrader;
     15
     16        /**
     17         * Elements to upgrade.
     18         *
     19         * @var WP_Bulk_Upgrade_Element_Base[]
     20         */
     21        protected $elements = array();
     22
     23        /**
     24         * Current element offset used to show total progression.
     25         *
     26         * @var int
     27         */
     28        protected $current_element_offset = 0;
     29
     30        /**
     31         * WP_Bulk_Upgrader_Composite constructor.
     32         *
     33         * @param WP_Upgrader $upgrader     Upgrader to report back to
     34         * @param array       $elements     List of elements to be bulked.
     35         * @param string      $elementClass Class name to wrap elements in. Extended of WP_Bulk_Upgrader_Element.
     36         *
     37         * @since  5.5.0
     38         * @access public
     39         */
     40        public function __construct( WP_Upgrader $upgrader, array $elements, $elementClass ) {
     41                if ( ! is_string( $elementClass ) ) {
     42                        throw new InvalidArgumentException( 'Expected element class to be string, got ' . gettype( $elementClass ) );
     43                }
     44
     45                if ( ! class_exists( $elementClass ) ) {
     46                        throw new InvalidArgumentException( sprintf( 'Element class "%s" does not exist.', $elementClass ) );
     47                }
     48
     49                $this->upgrader = $upgrader;
     50
     51                if ( array() !== $elements ) {
     52                        foreach ( $elements as $element ) {
     53                                $this->elements[] = new $elementClass( $element, $upgrader );
     54                        }
     55                }
     56
     57                $this->upgrader->update_count   = count( $this->elements );
     58                $this->upgrader->update_current = false;
     59        }
     60
     61        /**
     62         * Runs the bulk upgrade.
     63         *
     64         * @return array List of results.
     65         *
     66         * @since 5.5.0
     67         * @access public
     68         */
     69        public function run() {
     70                $this->upgrader->clean_upgrade_folder();
     71
     72                $this->check_up_to_date( $this->elements );
     73
     74                // Get all elements that have an upgrade.
     75                $upgradable_elements = $this->get_upgradable_elements( $this->elements );
     76
     77                $this->upgrader->update_count = count( $upgradable_elements );
     78
     79                // Download and unpack all items with upgrades.
     80                $this->prepare_upgrade( $upgradable_elements );
     81
     82                // On multisite it is hard to determine if a plugin is active on a sub-site or not - assume all are active.
     83                if ( is_multisite() ) {
     84                        $this->upgrade( $upgradable_elements, true );
     85                } else {
     86                        // Get all non-active elements - these don't need maintenance mode enabled.
     87                        $inactive_elements = $this->get_inactive_elements( $upgradable_elements );
     88                        if ( $inactive_elements ) {
     89                                $this->upgrade( $inactive_elements, false );
     90                        }
     91
     92                        // Get all active elements - these need maintenance mode enabled.
     93                        $active_elements = $this->get_active_elements( $upgradable_elements );
     94                        if ( $active_elements ) {
     95                                $this->upgrade( $active_elements, true );
     96                        }
     97                }
     98
     99                $this->upgrader->update_current = false;
     100
     101                return $this->get_results();
     102        }
     103
     104        /**
     105         * Prepare download and unpack before installing.
     106         *
     107         * @param WP_Bulk_Upgrade_Element_Base[] $elements List of elements to prepare.
     108         *
     109         * @return void
     110         *
     111         * @since  5.5.0
     112         * @access protected
     113         */
     114        protected function prepare_upgrade( $elements ) {
     115                $skin = $this->get_skin();
     116
     117                $skin->before( 'bulk_download' );
     118                $this->download( $elements );
     119                $skin->set_result(true);
     120                $skin->after( 'bulk_download' );
     121
     122                $skin->before( 'bulk_unpack' );
     123                $this->unpack( $elements );
     124                $skin->after( 'bulk_unpack' );
     125        }
     126
     127        /**
     128         * Upgrades a list of elements.
     129         *
     130         * @param WP_Bulk_Upgrade_Element_Base[] $elements         Elements to upgrade.
     131         * @param boolean                        $maintenance_mode Enable maintenance mode.
     132         *
     133         * @return void
     134         *
     135         * @since  5.5.0
     136         * @access protected
     137         */
     138        protected function upgrade( $elements, $maintenance_mode ) {
     139                if ( $maintenance_mode ) {
     140                        $this->upgrader->maintenance_mode( true );
     141                }
     142
     143                $this->install( $elements );
     144
     145                if ( $maintenance_mode ) {
     146                        $this->upgrader->maintenance_mode( false );
     147                }
     148
     149                $this->current_element_offset += count( $elements );
     150        }
     151
     152        /**
     153         * Downloads all the elements.
     154         *
     155         * @param WP_Bulk_Upgrade_Element_Base[] $elements
     156         *
     157         * @return void
     158         *
     159         * @since  5.5.0
     160         * @access protected
     161         */
     162        protected function download( array $elements ) {
     163                /** @var $element WP_Bulk_Upgrade_Element_Base */
     164                foreach ( $elements as $element ) {
     165                        $this->set_current_element( $element, $elements );
     166
     167                        $result = $element->download();
     168                        if ( is_wp_error( $result ) ) {
     169                                $this->show_error( $result, $element );
     170                                break;
     171                        }
     172
     173                        if ( is_wp_error( $element->get_verification_result() ) ) {
     174                                $this->show_warning( $element->get_verification_result(), $element );
     175                        }
     176                }
     177        }
     178
     179        /**
     180         * Unpacks downloaded elements.
     181         *
     182         * @param WP_Bulk_Upgrade_Element_Base[] $elements Elements to unpack.
     183         *
     184         * @return void
     185         *
     186         * @since  5.5.0
     187         * @access protected
     188         */
     189        protected function unpack( array $elements ) {
     190                /** @var $element WP_Bulk_Upgrade_Element_Base */
     191                foreach ( $elements as $element ) {
     192                        $this->set_current_element( $element, $elements );
     193
     194                        $result = $element->unpack();
     195                        if ( is_wp_error( $result ) ) {
     196                                $this->show_error( $result, $element );
     197                        }
     198                }
     199        }
     200
     201        /**
     202         * Installs elements.
     203         *
     204         * @param WP_Bulk_Upgrade_Element_Base[] $elements Elements to install.
     205         *
     206         * @return void
     207         *
     208         * @since  5.5.0
     209         * @access protected
     210         */
     211        protected function install( array $elements ) {
     212                foreach ( $elements as $element ) {
     213                        $this->set_current_element( $element, $elements );
     214
     215                        $skin = $this->get_skin();
     216                        $skin->before();
     217
     218                        $result = $element->install();
     219
     220                        $skin->set_result( $result );
     221                        if ( is_wp_error( $result ) ) {
     222                                $skin->error( $result );
     223                                $skin->feedback( 'process_failed' );
     224                        } else {
     225                                // Install succeeded.
     226                                $skin->feedback( 'process_success' );
     227                        }
     228                        $skin->after();
     229
     230                        if ( is_wp_error( $result ) && $this->abort_on_error() ) {
     231                                break;
     232                        }
     233                }
     234
     235                $this->clear_current_element();
     236        }
     237
     238        /**
     239         * Retrieves the elements that have an upgrade available.
     240         *
     241         * @param WP_Bulk_Upgrade_Element_Base[] $elements List of elements to filter.
     242         *
     243         * @return array Filtered list of elements with an upgrade.
     244         *
     245         * @since  5.5.0
     246         * @access protected
     247         */
     248        protected function get_upgradable_elements( array $elements ) {
     249                return array_values( array_filter( $elements, array( $this, 'is_upgradable' ) ) );
     250        }
     251
     252        /**
     253         * Determines if an element has an update.
     254         *
     255         * @param WP_Bulk_Upgrade_Element_Base $element Element to check.
     256         *
     257         * @return bool True if an upgrade is available, otherwise False.
     258         *
     259         * @since  5.5.0
     260         * @access protected
     261         */
     262        protected function is_upgradable( WP_Bulk_Upgrade_Element_Base $element ) {
     263                return ! $element->is_up_to_date();
     264        }
     265
     266        /**
     267         * Retrieves the elements that are not active.
     268         *
     269         * @param WP_Bulk_Upgrade_Element_Base[] $elements Elements to check.
     270         *
     271         * @return array Filtered list of elements that are not active.
     272         *
     273         * @since  5.5.0
     274         * @access protected
     275         */
     276        protected function get_inactive_elements( array $elements ) {
     277                return array_values( array_filter( $elements, array( $this, 'is_inactive') ) );
     278        }
     279
     280        /**
     281         * Determines if an element is active.
     282         *
     283         * @param WP_Bulk_Upgrade_Element_Base $element Element to check.
     284         *
     285         * @return bool True if the element is not active, False otherwise.
     286         *
     287         * @since  5.5.0
     288         * @access protected
     289         */
     290        protected function is_inactive( WP_Bulk_Upgrade_Element_Base $element ) {
     291                return ! $element->is_active();
     292        }
     293
     294        /**
     295         * Retrieves a list of active elements.
     296         *
     297         * @param WP_Bulk_Upgrade_Element_Base[] $elements Elements to check.
     298         *
     299         * @return array Filtered list of elements that are active.
     300         *
     301         * @since  5.5.0
     302         * @access protected
     303         */
     304        protected function get_active_elements( array $elements ) {
     305                return array_values( array_filter( $elements, array( $this, 'is_active' ) ) );
     306        }
     307
     308        /**
     309         * Determines if an element is active.
     310         *
     311         * @param WP_Bulk_Upgrade_Element_Base $element Element to check.
     312         *
     313         * @return bool True if the element is active, False otherwise.
     314         *
     315         * @since  5.5.0
     316         * @access protected
     317         */
     318        protected function is_active( WP_Bulk_Upgrade_Element_Base $element ) {
     319                return $element->is_active();
     320        }
     321
     322        /**
     323         * Set the current element as active on the upgrader
     324         *
     325         * @param WP_Bulk_Upgrade_Element_Base $element  Element to set index of.
     326         * @param array                        $elements List to search in.
     327         *
     328         * @return int|bool Current index. False if $element not found.
     329         *
     330         * @since  5.5.0
     331         * @access protected
     332         */
     333        protected function set_current_element( $element, $elements ) {
     334                $index = array_search( $element, $elements, true );
     335
     336                if ( false === $index ) {
     337                        $this->upgrader->update_current = false;
     338                } else {
     339                        $this->upgrader->update_current = $index + 1 + $this->current_element_offset;
     340                }
     341
     342                return $this->upgrader->update_current;
     343        }
     344
     345        /**
     346         * Removes the current element.
     347         *
     348         * @return void
     349         *
     350         * @since  5.5.0
     351         * @access protected
     352         */
     353        protected function clear_current_element() {
     354                $this->upgrader->update_current = false;
     355        }
     356
     357        /**
     358         * Checks if any of the elements is already up to date.
     359         *
     360         * @param WP_Bulk_Upgrade_Element_Base[] $elements Elements to check.
     361         *
     362         * @return void
     363         *
     364         * @since  5.5.0
     365         * @access protected
     366         */
     367        protected function check_up_to_date( array $elements ) {
     368                /** @var $element WP_Bulk_Upgrade_Element_Base */
     369                foreach ( $elements as $element ) {
     370                        if ( $element->is_up_to_date() ) {
     371                                $this->set_current_element( $element, $elements );
     372
     373                                $this->handle_up_to_date( $element );
     374
     375                                $skin = $this->get_skin();
     376                                $skin->feedback( 'up_to_date' );
     377                                $skin->after();
     378                        }
     379                }
     380        }
     381
     382        /**
     383         * Handles what to do when an element is already up to date.
     384         *
     385         * @param WP_Bulk_Upgrade_Element_Base $element Relevant element.
     386         *
     387         * @return void
     388         *
     389         * @since 5.5.0
     390         * @access protected
     391         */
     392        abstract protected function handle_up_to_date( WP_Bulk_Upgrade_Element_Base $element );
     393
     394        /**
     395         * Retrieves the results of the upgrade process.
     396         *
     397         * @return array List of results.
     398         *
     399         * @since  5.5.0
     400         * @access protected
     401         */
     402        protected function get_results() {
     403                $results = array();
     404
     405                /** @var $element WP_Bulk_Upgrade_Element_Base */
     406                foreach ( $this->elements as $element ) {
     407                        $index = $element->get_result_index();
     408                        if ( false === $index ) {
     409                                $results[] = $element->get_result();
     410                        } else {
     411                                $results[ $index ] = $element->get_result();
     412                        }
     413                }
     414
     415                return $results;
     416        }
     417
     418        /**
     419         * Passes an error to the skin.
     420         *
     421         * @param string                       $error
     422         * @param WP_Bulk_Upgrade_Element_Base $element
     423         *
     424         * @return void
     425         *
     426         * @since  5.5.0
     427         * @access protected
     428         */
     429        protected function show_error( $error, WP_Bulk_Upgrade_Element_Base $element ) {
     430                $skin = $this->get_skin();
     431                if ( $skin ) {
     432                        $skin->error( $error );
     433                        $skin->after();
     434                }
     435        }
     436
     437        /**
     438         * Passes a warning to the skin.
     439         *
     440         * @param WP_Error                     $warning Warning to show.
     441         * @param WP_Bulk_Upgrade_Element_Base $element Relevant element.
     442         *
     443         * @return void
     444         *
     445         * @since  5.5.0
     446         * @access protected
     447         */
     448        protected function show_warning( WP_Error $warning, WP_Bulk_Upgrade_Element_Base $element ) {
     449                $skin = $this->get_skin();
     450                if ( $skin ) {
     451                        foreach ( $warning->get_error_messages() as $message ) {
     452                                if ( $warning->get_error_data() && is_string( $warning->get_error_data() ) ) {
     453                                        $skin->feedback( $message . ' ' . esc_html( strip_tags( $warning->get_error_data() ) ) );
     454                                } else {
     455                                        $skin->feedback( $message );
     456                                }
     457                        }
     458                }
     459        }
     460
     461        /**
     462         * Determines if we should abort when encountering an error.
     463         *
     464         * @return bool
     465         *
     466         * @since  5.5.0
     467         * @access protected
     468         */
     469        protected function abort_on_error() {
     470                // Prevent credentials auth screen from displaying multiple times.
     471                return true;
     472        }
     473
     474        /**
     475         * Shorthand retrieval of upgrader skin.
     476         *
     477         * @return WP_Upgrader_Skin
     478         *
     479         * @since  5.5.0
     480         * @access protected
     481         */
     482        protected function get_skin() {
     483                return $this->upgrader->get_skin();
     484        }
     485}
     486 No newline at end of file
  • src/wp-admin/includes/class-bulk-upgrader-skin.php

    diff --git src/wp-admin/includes/class-bulk-upgrader-skin.php src/wp-admin/includes/class-bulk-upgrader-skin.php
    index c5cbcd487e..40138fa1e9 100644
     
    1616 * @see WP_Upgrader_Skin
    1717 */
    1818class Bulk_Upgrader_Skin extends WP_Upgrader_Skin {
     19        /**
     20         * Are we in an install/upgrade loop.
     21         *
     22         * @var bool
     23         */
    1924        public $in_loop = false;
     25       
    2026        /**
     27         * Did we encounter an error while installing/upgrading.
     28         *
    2129         * @var string|false
    2230         */
    2331        public $error = false;
    2432
    2533        /**
    26          * @param array $args
     34         * @param array $args Arguments used for this skin.
    2735         */
    2836        public function __construct( $args = array() ) {
    2937                $defaults = array(
    class Bulk_Upgrader_Skin extends WP_Upgrader_Skin { 
    3644        }
    3745
    3846        /**
     47         * Register the strings that we need.
     48         *
     49         * @return void
    3950         */
    4051        public function add_strings() {
    4152                $this->upgrader->strings['skin_upgrade_start'] = __( 'The update process is starting. This process may take a while on some hosts, so please be patient.' );
    class Bulk_Upgrader_Skin extends WP_Upgrader_Skin { 
    4657                /* translators: %s: Title of an update. */
    4758                $this->upgrader->strings['skin_update_successful'] = __( '%s updated successfully.' );
    4859                $this->upgrader->strings['skin_upgrade_end']       = __( 'All updates have been completed.' );
     60                $this->upgrader->strings['bulk_download']          = __( 'Downloading items.' );
     61                $this->upgrader->strings['bulk_unpack']            = __( 'Unpacking downloaded installers.' );
    4962        }
    5063
    5164        /**
    52          * @param string $string
     65         * Outputs feedback.
     66         *
     67         * @param string $string Text to show.
    5368         * @param mixed  ...$args Optional text replacements.
     69         *
     70         * @return void
    5471         */
    5572        public function feedback( $string, ...$args ) {
     73                $original_string = $string;
     74
    5675                if ( isset( $this->upgrader->strings[ $string ] ) ) {
    5776                        $string = $this->upgrader->strings[ $string ];
    5877                }
    class Bulk_Upgrader_Skin extends WP_Upgrader_Skin { 
    6483                                $string = vsprintf( $string, $args );
    6584                        }
    6685                }
     86
    6787                if ( empty( $string ) ) {
    6888                        return;
    6989                }
    70                 if ( $this->in_loop ) {
    71                         echo "$string<br />\n";
     90               
     91                if ( 'maintenance_start' === $original_string ) {
     92                        printf( '<p class="update-maintenance-start"><strong>%s</strong></p><div class="update-maintenance-content">', $string );
     93                } elseif( 'maintenance_end' === $original_string ) {
     94                        printf( '</div><p class="update-maintenance-end"><strong>%s</strong></p>', $string );
    7295                } else {
    73                         echo "<p>$string</p>\n";
     96                        if ( $this->in_loop ) {
     97                                echo "$string<br />\n";
     98                        } else {
     99                                echo "<p>$string</p>\n";
     100                        }
    74101                }
     102
     103                $this->flush_output();
    75104        }
    76105
    77106        /**
     107         * Outputs nothing, this will be displayed within a iframe.
     108         *
     109         * @return void
    78110         */
    79111        public function header() {
    80112                // Nothing, This will be displayed within a iframe.
    81113        }
    82114
    83115        /**
     116         * Outputs nothing, this will be displayed within a iframe.
     117         *
     118         * @return void
    84119         */
    85120        public function footer() {
    86121                // Nothing, This will be displayed within a iframe.
    87122        }
    88123
    89124        /**
    90          * @param string|WP_Error $error
     125         * Shows an error.
     126         *
     127         * @param string|WP_Error $error Error that will be shown.
    91128         */
    92129        public function error( $error ) {
    93130                if ( is_string( $error ) && isset( $this->upgrader->strings[ $error ] ) ) {
    class Bulk_Upgrader_Skin extends WP_Upgrader_Skin { 
    109146        }
    110147
    111148        /**
     149         * Shows the bulk header copy.
     150         *
     151         * @return void
    112152         */
    113153        public function bulk_header() {
    114154                $this->feedback( 'skin_upgrade_start' );
    115155        }
    116156
    117157        /**
     158         * Shows the bulk footer copy.
     159         *
     160         * @return void
    118161         */
    119162        public function bulk_footer() {
    120163                $this->feedback( 'skin_upgrade_end' );
    121164        }
    122165
    123166        /**
    124          * @param string $title
     167         * Shows a header for an element.
     168         * side-effect: Flushes the output buffer.
     169         *
     170         * @param string $title Copy or string identifier to use.
     171         *
     172         * @return void
    125173         */
    126174        public function before( $title = '' ) {
    127175                $this->in_loop = true;
    128                 printf( '<h2>' . $this->upgrader->strings['skin_before_update_header'] . ' <span class="spinner waiting-' . $this->upgrader->update_current . '"></span></h2>', $title, $this->upgrader->update_current, $this->upgrader->update_count );
    129                 echo '<script type="text/javascript">jQuery(\'.waiting-' . esc_js( $this->upgrader->update_current ) . '\').css("display", "inline-block");</script>';
     176
     177                $format = $this->upgrader->strings['skin_before_update_header'];
     178
     179                $identifier = $this->upgrader->update_current;
     180                if ( isset( $this->upgrader->strings[ $title ] ) ) {
     181                        $identifier = $title;
     182                        $format = $this->upgrader->strings [ $title ];
     183                }
     184
     185                printf(
     186                        '<h2>' . $format . ' <span class="' . esc_attr( 'spinner waiting-' . $identifier ) . '"></span></h2>',
     187                        $title,
     188                        $this->upgrader->update_current,
     189                        $this->upgrader->update_count
     190                );
     191               
     192                echo '<script type="text/javascript">jQuery(\'.waiting-' . esc_js( $identifier ) . '\').css("display", "inline-block");</script>';
     193               
    130194                // This progress messages div gets moved via JavaScript when clicking on "Show details.".
    131                 echo '<div class="update-messages hide-if-js" id="progress-' . esc_attr( $this->upgrader->update_current ) . '"><p>';
     195                echo '<div class="update-messages hide-if-js" id="' . esc_attr( 'progress-' . $identifier ) . '"><p>';
    132196                $this->flush_output();
    133197        }
    134198
    135199        /**
    136          * @param string $title
     200         * Shows a footer for an element.
     201         * side-effect: Flushes the output buffer.
     202         *
     203         * @param string $title Copy or string identifier to use.
     204         *
     205         * @return void
    137206         */
    138207        public function after( $title = '' ) {
     208                $success_format = $this->upgrader->strings['skin_update_successful'];
     209                $error_format = $this->upgrader->strings['skin_update_failed_error'];
     210                $failed_format = $this->upgrader->strings['skin_update_failed'];
     211
     212                $identifier = $this->upgrader->update_current;
     213                if ( isset( $this->upgrader->strings['title'] ) ) {
     214                        $identifier = $title;
     215                        $title = $this->upgrader->strings['title'];
     216
     217                        $success_format = '';
     218                        // Remove title, just keep error message
     219                        $error_format = '%2$s';
     220                        $failed_format = '%s';
     221                }
     222
    139223                echo '</p></div>';
     224
    140225                if ( $this->error || ! $this->result ) {
    141226                        if ( $this->error ) {
    142                                 echo '<div class="error"><p>' . sprintf( $this->upgrader->strings['skin_update_failed_error'], $title, '<strong>' . $this->error . '</strong>' ) . '</p></div>';
     227                                echo '<div class="error"><p>' . sprintf( $error_format, $title, '<strong>' . $this->error . '</strong>' ) . '</p></div>';
    143228                        } else {
    144                                 echo '<div class="error"><p>' . sprintf( $this->upgrader->strings['skin_update_failed'], $title ) . '</p></div>';
     229                                echo '<div class="error"><p>' . sprintf( $failed_format, $title ) . '</p></div>';
    145230                        }
    146231
    147                         echo '<script type="text/javascript">jQuery(\'#progress-' . esc_js( $this->upgrader->update_current ) . '\').show();</script>';
     232                        echo '<script type="text/javascript">jQuery(\'#progress-' . esc_js( $identifier ) . '\').show();</script>';
    148233                }
     234               
    149235                if ( $this->result && ! is_wp_error( $this->result ) ) {
    150236                        if ( ! $this->error ) {
    151                                 echo '<div class="updated js-update-details" data-update-details="progress-' . esc_attr( $this->upgrader->update_current ) . '">' .
    152                                         '<p>' . sprintf( $this->upgrader->strings['skin_update_successful'], $title ) .
     237                                echo '<div class="updated js-update-details" data-update-details="' . esc_attr( 'progress-' . $identifier ) . '">' .
     238                                        '<p>' . sprintf( $success_format, $title ) .
    153239                                        ' <button type="button" class="hide-if-no-js button-link js-update-details-toggle" aria-expanded="false">' . __( 'Show details.' ) . '</button>' .
    154240                                        '</p></div>';
    155241                        }
    class Bulk_Upgrader_Skin extends WP_Upgrader_Skin { 
    162248        }
    163249
    164250        /**
     251         * Resets the state of this class.
     252         *
     253         * @return void
    165254         */
    166255        public function reset() {
    167256                $this->in_loop = false;
    class Bulk_Upgrader_Skin extends WP_Upgrader_Skin { 
    169258        }
    170259
    171260        /**
     261         * Flushes the output buffer.
     262         *
     263         * @return void
    172264         */
    173265        public function flush_output() {
    174266                wp_ob_end_flush_all();
  • src/wp-admin/includes/class-core-upgrader.php

    diff --git src/wp-admin/includes/class-core-upgrader.php src/wp-admin/includes/class-core-upgrader.php
    index 7c782606d3..d13b7a98c0 100644
    class Core_Upgrader extends WP_Upgrader { 
    3232                /* translators: %s: Package URL. */
    3333                $this->strings['downloading_package']   = sprintf( __( 'Downloading update from %s&#8230;' ), '<span class="code">%s</span>' );
    3434                $this->strings['unpack_package']        = __( 'Unpacking the update&#8230;' );
     35                /* translators: %1$d: Current update counter, %2$d: Total amount of updates. */
     36                $this->strings['unpack_package_bulk']   = __( 'Unpacking the update&#8230; (%1$d/%2$d)' );
    3537                $this->strings['copy_failed']           = __( 'Could not copy files.' );
    3638                $this->strings['copy_failed_space']     = __( 'Could not copy files. You may have run out of disk space.' );
    3739                $this->strings['start_rollback']        = __( 'Attempting to roll back to previous version.' );
  • src/wp-admin/includes/class-language-pack-upgrader.php

    diff --git src/wp-admin/includes/class-language-pack-upgrader.php src/wp-admin/includes/class-language-pack-upgrader.php
    index 0ae18d9e50..304a253e29 100644
    class Language_Pack_Upgrader extends WP_Upgrader { 
    116116                /* translators: %s: Package URL. */
    117117                $this->strings['downloading_package'] = sprintf( __( 'Downloading translation from %s&#8230;' ), '<span class="code">%s</span>' );
    118118                $this->strings['unpack_package']      = __( 'Unpacking the update&#8230;' );
     119                /* translators: %1$d: Current update counter, %2$d: Total amount of updates. */
     120                $this->strings['unpack_package_bulk'] = __( 'Unpacking the update&#8230; (%1$d/%2$d)' );
    119121                $this->strings['process_failed']      = __( 'Translation update failed.' );
    120122                $this->strings['process_success']     = __( 'Translation updated successfully.' );
    121123                $this->strings['remove_old']          = __( 'Removing the old version of the translation&#8230;' );
  • new file src/wp-admin/includes/class-plugin-bulk-upgrade-element.php

    diff --git src/wp-admin/includes/class-plugin-bulk-upgrade-element.php src/wp-admin/includes/class-plugin-bulk-upgrade-element.php
    new file mode 100644
    index 0000000000..649ef46173
    - +  
     1<?php
     2
     3/**
     4 * Plugin implementation of the Bulk Upgrade Element.
     5 *
     6 * @since 5.5.0
     7 */
     8class WP_Plugin_Bulk_Upgrade_Element extends WP_Bulk_Upgrade_Repository_Element_Base {
     9        /**
     10         * WP_Bulk_Upgrader_Plugin_Element constructor.
     11         *
     12         * @param string          $plugin   Current plugin
     13         * @param Plugin_Upgrader $upgrader Upgrader to use.
     14         *
     15         * @since  5.5.0
     16         * @access public
     17         */
     18        public function __construct( $plugin, Plugin_Upgrader $upgrader ) {
     19                parent::__construct( $plugin, $upgrader );
     20
     21                $this->info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true );
     22
     23                $response = $this->get_response();
     24                if ( false === $response ) {
     25                        $this->up_to_date = true;
     26
     27                        return;
     28                }
     29
     30                $options = array(
     31                        'package'           => $response->package,
     32                        'destination'       => WP_PLUGIN_DIR,
     33                        'clear_destination' => true,
     34                        'clear_working'     => true,
     35                        'is_multi'          => true,
     36                        'hook_extra'        => array(
     37                                'plugin' => $plugin
     38                        )
     39                );
     40
     41                $this->set_options( $options );
     42        }
     43
     44        /**
     45         * Determines if this plugin is activated.
     46         *
     47         * @return bool
     48         *
     49         * @since  5.5.0
     50         * @access public
     51         */
     52        public function is_active() {
     53                return is_plugin_active( $this->name );
     54        }
     55
     56        /**
     57         * Retrieves information for the plugin from the `update_plugins` transient.
     58         *
     59         * @return mixed
     60         *
     61         * @since 5.5.0
     62         * @access protected
     63         */
     64        protected function get_current() {
     65                if ( ! isset( self::$current ) ) {
     66                        self::$current = get_site_transient( 'update_plugins' );
     67                }
     68
     69                return self::$current;
     70        }
     71}
     72 No newline at end of file
  • new file src/wp-admin/includes/class-plugin-bulk-upgrader.php

    diff --git src/wp-admin/includes/class-plugin-bulk-upgrader.php src/wp-admin/includes/class-plugin-bulk-upgrader.php
    new file mode 100644
    index 0000000000..7eab0b8617
    - +  
     1<?php
     2
     3/**
     4 * Plugin Bulk Upgrader implementation.
     5 *
     6 * @since 5.5.0
     7 */
     8class WP_Plugin_Bulk_Upgrader extends WP_Bulk_Upgrader_Base {
     9        /**
     10         * WP_Plugin_Bulk_Upgrader constructor.
     11         *
     12         * @param Plugin_Upgrader $upgrader Upgrader to use.
     13         * @param array           $elements Elements to use.
     14         *
     15         * @since 5.5.0
     16         * @access public
     17         */
     18        public function __construct( Plugin_Upgrader $upgrader, array $elements = array() ) {
     19                parent::__construct( $upgrader, $elements, 'WP_Plugin_Bulk_Upgrade_Element' );
     20        }
     21
     22        /**
     23         * Communicates result to skin.
     24         *
     25         * @param WP_Bulk_Upgrade_Element_Base $element Relevant element.
     26         *
     27         * @return void
     28         *
     29         * @since 5.5.0
     30         * @access public
     31         */
     32        public function handle_up_to_date( WP_Bulk_Upgrade_Element_Base $element ) {
     33                $skin = $this->get_skin();
     34                if ( $skin instanceof WP_Upgrader_Skin ) {
     35                        $skin->set_result( 'up_to_date' );
     36                }
     37        }
     38
     39        /**
     40         * Communicate plugin info to skin
     41         *
     42         * @param WP_Bulk_Upgrade_Element_Base $element  Element to set as current.
     43         * @param array                        $elements List to search in.
     44         *
     45         * @return void
     46         *
     47         * @since 5.5.0
     48         * @access protected
     49         */
     50        protected function set_current_element( $element, $elements ) {
     51                parent::set_current_element( $element, $elements );
     52
     53                if ( ! $this->upgrader->update_current ) {
     54                        return;
     55                }
     56
     57                $skin = $this->get_skin();
     58                $skin->plugin_info = $element->get_info();
     59        }
     60}
     61 No newline at end of file
  • src/wp-admin/includes/class-plugin-upgrader.php

    diff --git src/wp-admin/includes/class-plugin-upgrader.php src/wp-admin/includes/class-plugin-upgrader.php
    index 214f371866..7d79333e9c 100644
    class Plugin_Upgrader extends WP_Upgrader { 
    4949                /* translators: %s: Package URL. */
    5050                $this->strings['downloading_package']  = sprintf( __( 'Downloading update from %s&#8230;' ), '<span class="code">%s</span>' );
    5151                $this->strings['unpack_package']       = __( 'Unpacking the update&#8230;' );
     52                /* translators: %1$d: Current update counter, %2$d: Total amount of updates. */
     53                $this->strings['unpack_package_bulk']  = __( 'Unpacking the update&#8230; (%1$d/%2$d)' );
    5254                $this->strings['remove_old']           = __( 'Removing the old version of the plugin&#8230;' );
    5355                $this->strings['remove_old_failed']    = __( 'Could not remove the old plugin.' );
    5456                $this->strings['process_failed']       = __( 'Plugin update failed.' );
    class Plugin_Upgrader extends WP_Upgrader { 
    6668                /* translators: %s: Package URL. */
    6769                $this->strings['downloading_package'] = sprintf( __( 'Downloading installation package from %s&#8230;' ), '<span class="code">%s</span>' );
    6870                $this->strings['unpack_package']      = __( 'Unpacking the package&#8230;' );
     71                /* translators: %1$d: Current package counter, %2$d: Total number of packages. */
     72                $this->strings['unpack_package_bulk'] = __( 'Unpacking the package&#8230; (%1$d/%2$d)' );
    6973                $this->strings['installing_package']  = __( 'Installing the plugin&#8230;' );
    7074                $this->strings['no_files']            = __( 'The plugin contains no files.' );
    7175                $this->strings['process_failed']      = __( 'Plugin installation failed.' );
    class Plugin_Upgrader extends WP_Upgrader { 
    233237                $this->bulk = true;
    234238                $this->upgrade_strings();
    235239
    236                 $current = get_site_transient( 'update_plugins' );
    237 
    238240                add_filter( 'upgrader_clear_destination', array( $this, 'delete_old_plugin' ), 10, 4 );
    239241
    240242                $this->skin->header();
    class Plugin_Upgrader extends WP_Upgrader { 
    248250
    249251                $this->skin->bulk_header();
    250252
    251                 /*
    252                  * Only start maintenance mode if:
    253                  * - running Multisite and there are one or more plugins specified, OR
    254                  * - a plugin with an update available is currently active.
    255                  * @todo For multisite, maintenance mode should only kick in for individual sites if at all possible.
    256                  */
    257                 $maintenance = ( is_multisite() && ! empty( $plugins ) );
    258                 foreach ( $plugins as $plugin ) {
    259                         $maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin ] ) );
    260                 }
    261                 if ( $maintenance ) {
    262                         $this->maintenance_mode( true );
    263                 }
    264 
    265                 $results = array();
    266 
    267                 $this->update_count   = count( $plugins );
    268                 $this->update_current = 0;
    269                 foreach ( $plugins as $plugin ) {
    270                         $this->update_current++;
    271                         $this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true );
    272 
    273                         if ( ! isset( $current->response[ $plugin ] ) ) {
    274                                 $this->skin->set_result( 'up_to_date' );
    275                                 $this->skin->before();
    276                                 $this->skin->feedback( 'up_to_date' );
    277                                 $this->skin->after();
    278                                 $results[ $plugin ] = true;
    279                                 continue;
    280                         }
    281 
    282                         // Get the URL to the zip file.
    283                         $r = $current->response[ $plugin ];
    284 
    285                         $this->skin->plugin_active = is_plugin_active( $plugin );
    286 
    287                         $result = $this->run(
    288                                 array(
    289                                         'package'           => $r->package,
    290                                         'destination'       => WP_PLUGIN_DIR,
    291                                         'clear_destination' => true,
    292                                         'clear_working'     => true,
    293                                         'is_multi'          => true,
    294                                         'hook_extra'        => array(
    295                                                 'plugin' => $plugin,
    296                                         ),
    297                                 )
    298                         );
    299 
    300                         $results[ $plugin ] = $this->result;
    301 
    302                         // Prevent credentials auth screen from displaying multiple times.
    303                         if ( false === $result ) {
    304                                 break;
    305                         }
    306                 } // End foreach $plugins.
    307 
    308                 $this->maintenance_mode( false );
     253                $plugin_bulk_upgrader = new WP_Plugin_Bulk_Upgrader( $this, $plugins );
     254                $results = $plugin_bulk_upgrader->run();
    309255
    310256                // Force refresh of plugin update information.
    311257                wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
  • new file src/wp-admin/includes/class-theme-bulk-upgrade-element.php

    diff --git src/wp-admin/includes/class-theme-bulk-upgrade-element.php src/wp-admin/includes/class-theme-bulk-upgrade-element.php
    new file mode 100644
    index 0000000000..2f25fe0277
    - +  
     1<?php
     2
     3/**
     4 * Theme implementation of the Bulk Upgrade Element.
     5 *
     6 * @since 5.5.0
     7 */
     8class WP_Theme_Bulk_Upgrade_Element extends WP_Bulk_Upgrade_Repository_Element_Base {
     9        /**
     10         * WP_Bulk_Upgrader_Theme_Element constructor.
     11         *
     12         * @param string         $theme    Theme to use.
     13         * @param Theme_Upgrader $upgrader Upgrader to use.
     14         *
     15         * @since 5.5.0
     16         * @access public
     17         */
     18        public function __construct( $theme, Theme_Upgrader $upgrader ) {
     19                parent::__construct( $theme, $upgrader );
     20
     21                $this->info = $upgrader->theme_info( $theme );
     22
     23                $response = $this->get_response();
     24                if ( false === $response ) {
     25                        $this->up_to_date = true;
     26
     27                        return;
     28                }
     29
     30                $options = array(
     31                        'package'           => $this->response['package'],
     32                        'destination'       => get_theme_root( $theme ),
     33                        'clear_destination' => true,
     34                        'clear_working'     => true,
     35                        'is_multi'          => true,
     36                        'hook_extra'        => array(
     37                                        'theme' => $theme
     38                        )
     39                );
     40
     41                $this->set_options( $options );
     42        }
     43
     44        /**
     45         * Determines if this theme is active.
     46         *
     47         * @return bool
     48         *
     49         * @since 5.5.0
     50         * @access public
     51         */
     52        public function is_active() {
     53                return $this->name === get_stylesheet() || $this->name === get_template();
     54        }
     55
     56        /**
     57         * Retrieves information about the theme from the `update_themes` transient.
     58         *
     59         * @return mixed
     60         *
     61         * @since 5.5.0
     62         * @access protected
     63         */
     64        protected function get_current() {
     65                if ( ! isset( self::$current ) ) {
     66                        self::$current = get_site_transient( 'update_themes' );
     67                }
     68
     69                return self::$current;
     70        }
     71}
     72 No newline at end of file
  • new file src/wp-admin/includes/class-theme-bulk-upgrader.php

    diff --git src/wp-admin/includes/class-theme-bulk-upgrader.php src/wp-admin/includes/class-theme-bulk-upgrader.php
    new file mode 100644
    index 0000000000..2b2d1ae49a
    - +  
     1<?php
     2
     3/**
     4 * Theme Bulk Upgrader implementation.
     5 *
     6 * @since 5.5.0
     7 */
     8class WP_Theme_Bulk_Upgrader extends WP_Bulk_Upgrader_Base {
     9    /**
     10     * WP_Theme_Bulk_Upgrader constructor.
     11     *
     12     * @param Theme_Upgrader                 $upgrader Upgrader to use.
     13     * @param WP_Bulk_Upgrade_Element_Base[] $elements Elements to use.
     14     *
     15     * @since  5.5.0
     16     * @access public
     17     */
     18    public function __construct( Theme_Upgrader $upgrader, array $elements = array() ) {
     19        parent::__construct( $upgrader, $elements, 'WP_Theme_Bulk_Upgrade_Element' );
     20    }
     21
     22    /**
     23     * Handles what to do for an up-to-date theme.
     24     *
     25     * @param WP_Bulk_Upgrade_Element_Base $element Element to use.
     26     *
     27     * @return void
     28     *
     29     * @since  5.5.0
     30     * @access public
     31     */
     32    public function handle_up_to_date( WP_Bulk_Upgrade_Element_Base $element ) {
     33        $skin = $this->get_skin();
     34        if ( $skin instanceof WP_Upgrader_Skin ) {
     35            $skin->set_result( true );
     36        }
     37    }
     38
     39    /**
     40     * Sets the current element on the skin.
     41     *
     42     * @param WP_Bulk_Upgrade_Element_Base $element  Element to set as current.
     43     * @param array                        $elements List to search in.
     44     *
     45     * @return void
     46     *
     47     * @since  5.5.0
     48     * @access protected
     49     */
     50    protected function set_current_element( $element, $elements ) {
     51        parent::set_current_element( $element, $elements );
     52
     53        if ( ! $this->upgrader->update_current ) {
     54            return;
     55        }
     56
     57        $skin = $this->get_skin();
     58        if ( $skin instanceof Bulk_Theme_Upgrader_Skin ) {
     59            $skin->theme_info = $element->get_info();
     60        }
     61    }
     62}
     63 No newline at end of file
  • src/wp-admin/includes/class-theme-upgrader.php

    diff --git src/wp-admin/includes/class-theme-upgrader.php src/wp-admin/includes/class-theme-upgrader.php
    index 9d561c0893..b0c8e553bd 100644
    class Theme_Upgrader extends WP_Upgrader { 
    4848                /* translators: %s: Package URL. */
    4949                $this->strings['downloading_package'] = sprintf( __( 'Downloading update from %s&#8230;' ), '<span class="code">%s</span>' );
    5050                $this->strings['unpack_package']      = __( 'Unpacking the update&#8230;' );
     51                /* translators: %1$d: Current update counter, %2$d: Total amount of updates. */
     52                $this->strings['unpack_package_bulk'] = __( 'Unpacking the update&#8230; (%1$d/%2$d)' );
    5153                $this->strings['remove_old']          = __( 'Removing the old version of the theme&#8230;' );
    5254                $this->strings['remove_old_failed']   = __( 'Could not remove the old theme.' );
    5355                $this->strings['process_failed']      = __( 'Theme update failed.' );
    class Theme_Upgrader extends WP_Upgrader { 
    6466                /* translators: %s: Package URL. */
    6567                $this->strings['downloading_package'] = sprintf( __( 'Downloading installation package from %s&#8230;' ), '<span class="code">%s</span>' );
    6668                $this->strings['unpack_package']      = __( 'Unpacking the package&#8230;' );
     69                /* translators: %1$d: Current package counter, %2$d: Total number of plugins. */
     70                $this->strings['unpack_package_bulk'] = __( 'Unpacking the package&#8230; (%1$d/%2$d)' );
    6771                $this->strings['installing_package']  = __( 'Installing the theme&#8230;' );
    6872                $this->strings['no_files']            = __( 'The theme contains no files.' );
    6973                $this->strings['process_failed']      = __( 'Theme installation failed.' );
    class Theme_Upgrader extends WP_Upgrader { 
    359363
    360364                $this->skin->bulk_header();
    361365
    362                 /*
    363                  * Only start maintenance mode if:
    364                  * - running Multisite and there are one or more themes specified, OR
    365                  * - a theme with an update available is currently in use.
    366                  * @todo For multisite, maintenance mode should only kick in for individual sites if at all possible.
    367                  */
    368                 $maintenance = ( is_multisite() && ! empty( $themes ) );
    369                 foreach ( $themes as $theme ) {
    370                         $maintenance = $maintenance || get_stylesheet() === $theme || get_template() === $theme;
    371                 }
    372                 if ( $maintenance ) {
    373                         $this->maintenance_mode( true );
    374                 }
    375 
    376                 $results = array();
    377 
    378                 $this->update_count   = count( $themes );
    379                 $this->update_current = 0;
    380                 foreach ( $themes as $theme ) {
    381                         $this->update_current++;
    382 
    383                         $this->skin->theme_info = $this->theme_info( $theme );
    384 
    385                         if ( ! isset( $current->response[ $theme ] ) ) {
    386                                 $this->skin->set_result( true );
    387                                 $this->skin->before();
    388                                 $this->skin->feedback( 'up_to_date' );
    389                                 $this->skin->after();
    390                                 $results[ $theme ] = true;
    391                                 continue;
    392                         }
    393 
    394                         // Get the URL to the zip file.
    395                         $r = $current->response[ $theme ];
    396 
    397                         $result = $this->run(
    398                                 array(
    399                                         'package'           => $r['package'],
    400                                         'destination'       => get_theme_root( $theme ),
    401                                         'clear_destination' => true,
    402                                         'clear_working'     => true,
    403                                         'is_multi'          => true,
    404                                         'hook_extra'        => array(
    405                                                 'theme' => $theme,
    406                                         ),
    407                                 )
    408                         );
    409 
    410                         $results[ $theme ] = $this->result;
    411 
    412                         // Prevent credentials auth screen from displaying multiple times.
    413                         if ( false === $result ) {
    414                                 break;
    415                         }
    416                 } // End foreach $themes.
    417 
    418                 $this->maintenance_mode( false );
     366                $theme_bulk_upgrader = new WP_Theme_Bulk_Upgrader( $this, $themes );
     367                $results = $theme_bulk_upgrader->run();
    419368
    420369                // Refresh the Theme Update information.
    421370                wp_clean_themes_cache( $parsed_args['clear_update_cache'] );
  • new file src/wp-admin/includes/class-wp-upgrader-bulk.php

    diff --git src/wp-admin/includes/class-wp-upgrader-bulk.php src/wp-admin/includes/class-wp-upgrader-bulk.php
    new file mode 100644
    index 0000000000..9fd767841f
    - +  
     1<?php
     2/**
     3 * The Bulk handlers for the WordPress Upgrader.
     4 *
     5 * @package    WordPress
     6 * @subpackage Upgrader
     7 * @since      5.5.0
     8 */
     9
     10require_once 'class-bulk-upgrade-element-base.php';
     11require_once 'class-bulk-upgrade-repository-element-base.php';
     12
     13require_once 'class-bulk-upgrader-base.php';
     14
     15require_once 'class-plugin-bulk-upgrade-element.php';
     16require_once 'class-plugin-bulk-upgrader.php';
     17
     18require_once 'class-theme-bulk-upgrade-element.php';
     19require_once 'class-theme-bulk-upgrader.php';
  • src/wp-admin/includes/class-wp-upgrader-skin.php

    diff --git src/wp-admin/includes/class-wp-upgrader-skin.php src/wp-admin/includes/class-wp-upgrader-skin.php
    index e776076d64..941f1ff63d 100644
     
    1515 */
    1616class WP_Upgrader_Skin {
    1717
     18        /**
     19         * Holds the Upgrader to use.
     20         *
     21         * @var WP_Upgrader
     22         */
    1823        public $upgrader;
    1924        public $done_header = false;
    2025        public $done_footer = false;
    class WP_Upgrader_Skin { 
    4247        }
    4348
    4449        /**
    45          * @param WP_Upgrader $upgrader
     50         * Sets the upgrader to use internally.
     51         *
     52         * @param WP_Upgrader $upgrader Upgrader to use.
    4653         */
    4754        public function set_upgrader( &$upgrader ) {
    4855                if ( is_object( $upgrader ) ) {
  • src/wp-admin/includes/class-wp-upgrader.php

    diff --git src/wp-admin/includes/class-wp-upgrader.php src/wp-admin/includes/class-wp-upgrader.php
    index a399bad07f..394418a200 100644
     
    99 * @since 2.8.0
    1010 */
    1111
     12/** WP_Upgrader_Bulk class */
     13require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-bulk.php';
     14
    1215/** WP_Upgrader_Skin class */
    1316require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skin.php';
    1417
    class WP_Upgrader { 
    120123         *                               instance.
    121124         */
    122125        public function __construct( $skin = null ) {
    123                 if ( null == $skin ) {
     126                if ( $skin === null ) {
    124127                        $this->skin = new WP_Upgrader_Skin();
    125128                } else {
    126129                        $this->skin = $skin;
    class WP_Upgrader { 
    301304        public function unpack_package( $package, $delete_package = true ) {
    302305                global $wp_filesystem;
    303306
    304                 $this->skin->feedback( 'unpack_package' );
     307                if ( $this->update_count > 1 ) {
     308                        $this->skin->feedback( 'unpack_package_bulk', $this->update_current, $this->update_count );
     309                } else {
     310                        $this->skin->feedback( 'unpack_package' );
     311                }
    305312
    306313                $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
    307314
    308                 // Clean up contents of upgrade directory beforehand.
    309                 $upgrade_files = $wp_filesystem->dirlist( $upgrade_folder );
    310                 if ( ! empty( $upgrade_files ) ) {
    311                         foreach ( $upgrade_files as $file ) {
    312                                 $wp_filesystem->delete( $upgrade_folder . $file['name'], true );
    313                         }
    314                 }
    315 
    316315                // We need a working directory - strip off any .tmp or .zip suffixes.
    317316                $working_dir = $upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' );
    318317
    class WP_Upgrader { 
    708707                 */
    709708                $options = apply_filters( 'upgrader_package_options', $options );
    710709
    711                 if ( ! $options['is_multi'] ) { // Call $this->header separately if running multiple times.
    712                         $this->skin->header();
    713                 }
     710                $this->skin->header();
    714711
    715712                // Connect to the filesystem first.
    716713                $res = $this->fs_connect( array( WP_CONTENT_DIR, $options['destination'] ) );
     714
    717715                // Mainly for non-connected filesystem.
    718716                if ( ! $res ) {
    719717                        if ( ! $options['is_multi'] ) {
    class WP_Upgrader { 
    733731                        return $res;
    734732                }
    735733
     734                $this->clean_upgrade_folder();
     735
    736736                /*
    737737                 * Download the package (Note, This just returns the filename
    738738                 * of the file if the package is a local file)
    class WP_Upgrader { 
    931931                return delete_option( $lock_name . '.lock' );
    932932        }
    933933
     934        /**
     935        * Clears optional remnants of previous upgrades.
     936        *
     937        * @since 5.5.0
     938        * @access public
     939        *
     940        * @global WP_Filesystem_Base $wp_filesystem Subclass
     941        */
     942        public function clean_upgrade_folder() {
     943                /** @var WP_Filesystem_Base $wp_filesystem */
     944                global $wp_filesystem;
     945
     946                // Clean up contents of upgrade directory.
     947                $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
     948                $upgrade_files  = $wp_filesystem->dirlist( $upgrade_folder );
     949                if ( ! empty( $upgrade_files ) ) {
     950                        foreach ( $upgrade_files as $file ) {
     951                                $wp_filesystem->delete( $upgrade_folder . $file['name'], true );
     952                        }
     953                }
     954        }
     955
     956        /**
     957        * Retrieves the used skin.
     958        *
     959        * @return WP_Upgrader_Skin The used skin.
     960        *
     961        * @since  5.5.0
     962        * @access public
     963        */
     964        public function get_skin() {
     965                return $this->skin;
     966        }
     967
    934968}
    935969
    936970/** Plugin_Upgrader class */
  • src/wp-admin/menu.php

    diff --git src/wp-admin/menu.php src/wp-admin/menu.php
    index 77cf7d68bd..1064e7b85c 100644
     
    99/**
    1010 * Constructs the admin menu.
    1111 *
    12  * The elements in the array are :
    13  *     0: Menu item name
     12 * The elements in the array are:
     13 *     0: Menu item name.
    1414 *     1: Minimum level or capability required.
    15  *     2: The URL of the item's file
    16  *     3: Class
    17  *     4: ID
    18  *     5: Icon for top level menu
     15 *     2: The URL of the item's file.
     16 *     3: Page title.
     17 *     4: Classes.
     18 *     5: ID.
     19 *     6: Icon for top level menu.
    1920 *
    2021 * @global array $menu
    2122 */
  • src/wp-content/themes/twentytwenty/style-rtl.css

    diff --git src/wp-content/themes/twentytwenty/style-rtl.css src/wp-content/themes/twentytwenty/style-rtl.css
    index e7d7e7d503..99e9a47f89 100644
    figure.wp-block-table.is-style-stripes { 
    35113511        letter-spacing: normal;
    35123512}
    35133513
     3514.entry-content h1,
     3515.entry-content h2,
     3516.entry-content h3,
     3517.entry-content h4,
     3518.entry-content h5,
     3519.entry-content h6,
    35143520.entry-content cite,
    35153521.entry-content figcaption,
    3516 .entry-content .wp-caption-text {
     3522.entry-content table,
     3523.entry-content address,
     3524.entry-content .wp-caption-text,
     3525.entry-content .wp-block-file {
    35173526        font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, sans-serif;
    35183527}
    35193528
    35203529@supports ( font-variation-settings: normal ) {
    35213530
     3531        .entry-content h1,
     3532        .entry-content h2,
     3533        .entry-content h3,
     3534        .entry-content h4,
     3535        .entry-content h5,
     3536        .entry-content h6,
    35223537        .entry-content cite,
    35233538        .entry-content figcaption,
    3524         .entry-content .wp-caption-text {
     3539        .entry-content table,
     3540        .entry-content address,
     3541        .entry-content .wp-caption-text,
     3542        .entry-content .wp-block-file {
    35253543                font-family: "Inter var", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, sans-serif;
    35263544        }
    35273545}
  • src/wp-content/themes/twentytwenty/style.css

    diff --git src/wp-content/themes/twentytwenty/style.css src/wp-content/themes/twentytwenty/style.css
    index a07102ae5f..54fa2261fd 100644
    figure.wp-block-table.is-style-stripes { 
    35333533        letter-spacing: normal;
    35343534}
    35353535
     3536.entry-content h1,
     3537.entry-content h2,
     3538.entry-content h3,
     3539.entry-content h4,
     3540.entry-content h5,
     3541.entry-content h6,
    35363542.entry-content cite,
    35373543.entry-content figcaption,
    3538 .entry-content .wp-caption-text {
     3544.entry-content table,
     3545.entry-content address,
     3546.entry-content .wp-caption-text,
     3547.entry-content .wp-block-file {
    35393548        font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, sans-serif;
    35403549}
    35413550
    35423551@supports ( font-variation-settings: normal ) {
    35433552
     3553        .entry-content h1,
     3554        .entry-content h2,
     3555        .entry-content h3,
     3556        .entry-content h4,
     3557        .entry-content h5,
     3558        .entry-content h6,
    35443559        .entry-content cite,
    35453560        .entry-content figcaption,
    3546         .entry-content .wp-caption-text {
     3561        .entry-content table,
     3562        .entry-content address,
     3563        .entry-content .wp-caption-text,
     3564        .entry-content .wp-block-file {
    35473565                font-family: "Inter var", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, sans-serif;
    35483566        }
    35493567}
  • src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php

    diff --git src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php
    index b62f6f55a8..14478786cf 100644
    class WP_REST_Themes_Controller extends WP_REST_Controller { 
    349349                                                        'type'        => 'boolean',
    350350                                                ),
    351351                                                'disable-custom-gradients'  => array(
    352                                                         'description' => __( 'Whether the theme disables custom graidients.' ),
     352                                                        'description' => __( 'Whether the theme disables custom gradients.' ),
    353353                                                        'type'        => 'boolean',
    354354                                                ),
    355355                                                'editor-color-palette'      => array(
  • tests/phpunit/tests/post.php

    diff --git tests/phpunit/tests/post.php tests/phpunit/tests/post.php
    index d4672212cc..ca18c41b0e 100644
    class Tests_Post extends WP_UnitTestCase { 
    10041004         */
    10051005        function test_utf8mb3_post_saves_with_emoji() {
    10061006                global $wpdb;
    1007                 $_wpdb = new WpdbExposedMethodsForTesting();
    10081007
    1009                 if ( 'utf8' !== $_wpdb->get_col_charset( $wpdb->posts, 'post_title' ) ) {
     1008                if ( 'utf8' !== $wpdb->get_col_charset( $wpdb->posts, 'post_title' ) ) {
    10101009                        $this->markTestSkipped( 'This test is only useful with the utf8 character set' );
    10111010                }
    10121011