WordPress.org

Make WordPress Core

Ticket #51857: 51857.5.diff

File 51857.5.diff, 7.7 KB (added by afragen, 3 months ago)

also update _copy_dir() per @dd32 rec

  • wp-admin/includes/class-wp-upgrader.php

    diff --git a/wp-admin/includes/class-wp-upgrader.php b/wp-admin/includes/class-wp-upgrader.php
    index 5faac56213..4fdb35b244 100644
    a b class WP_Upgrader { 
    594594                // Copy new version of item into place.
    595595                $result = copy_dir( $source, $remote_destination );
    596596                if ( is_wp_error( $result ) ) {
     597                        $this->extract_rollback( $destination, $args['hook_extra'] );
    597598                        if ( $args['clear_working'] ) {
    598599                                $wp_filesystem->delete( $remote_source, true );
    599600                        }
    class WP_Upgrader { 
    775776
    776777                $delete_package = ( $download != $options['package'] ); // Do not delete a "local" file.
    777778
     779                // Zip the plugin/theme being updated to rollback directory.
     780                add_filter( 'upgrader_pre_install', array( $this, 'zip_to_rollback_dir' ), 15, 2 );
     781
    778782                // Unzips the file into a temporary directory.
    779783                $working_dir = $this->unpack_package( $download, $delete_package );
    780784                if ( is_wp_error( $working_dir ) ) {
    class WP_Upgrader { 
    937941                return delete_option( $lock_name . '.lock' );
    938942        }
    939943
     944
     945        /**
     946         * Create a zip archive of the plugin/theme being upgraded into a rollback directory.
     947         *
     948         * @since 5.7.0
     949         * @uses 'upgrader_pre_install' filter.
     950         *
     951         * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
     952         * @param  bool               $true          Boolean response to 'upgrader_pre_install' filter.
     953         *                                           Default is true.
     954         * @param  array              $hook_extra    Array of data for plugin/theme being updated.
     955         *
     956         * @return bool
     957         */
     958        public function zip_to_rollback_dir( $true, $hook_extra ) {
     959                global $wp_filesystem;
     960
     961                $rollback_dir = $wp_filesystem->wp_content_dir() . 'upgrade/rollback/';
     962                $type         = key( $hook_extra );
     963                $slug         = 'plugin' === $type ? dirname( $hook_extra['plugin'] ) : $hook_extra['theme'];
     964                $src          = 'plugin' === $type ? WP_PLUGIN_DIR . "/{$slug}" : get_theme_root(). "/{$slug}";
     965                if ( $wp_filesystem->mkdir( $rollback_dir ) ) {
     966                        $path_prefix = strlen( $src ) + 1;
     967                        $zip         = new ZipArchive();
     968
     969                        if ( true === $zip->open( "{$rollback_dir}{$slug}.zip", ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) {
     970                                $files = new RecursiveIteratorIterator(
     971                                        new RecursiveDirectoryIterator( $src ),
     972                                        RecursiveIteratorIterator::LEAVES_ONLY
     973                                );
     974
     975                                foreach ( $files as $name => $file ) {
     976                                        // Skip directories (they would be added automatically).
     977                                        if ( ! $file->isDir() ) {
     978                                                // Get real and relative path for current file.
     979                                                $file_path     = $file->getRealPath();
     980                                                $relative_path = substr( $file_path, $path_prefix );
     981
     982                                                // Add current file to archive.
     983                                                $zip->addFile( $file_path, $relative_path );
     984                                        }
     985                                }
     986
     987                                $zip->close();
     988                        } else {
     989                                return new WP_Error( 'zip_rollback_failed', __( 'Zip plugin/theme to rollback directory failed.' ) );
     990                        }
     991                }
     992
     993                return $true;
     994        }
     995
     996        /**
     997         * Extract zipped rollback to original location.
     998         *
     999         * @since 5.7.0
     1000         *
     1001         * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
     1002         * @param string              $destination   File path of plugin/theme.
     1003         * @param  array              $hook_extra    Array of data for plugin/theme being updated.
     1004         *
     1005         * @return bool
     1006         */
     1007        public function extract_rollback( $destination, $hook_extra ) {
     1008                global $wp_filesystem;
     1009
     1010                // Start with a clean slate.
     1011                if ( $wp_filesystem->is_dir( $destination ) ) {
     1012                        $wp_filesystem->delete( $destination, true );
     1013                }
     1014
     1015                $rollback_dir = $wp_filesystem->wp_content_dir() . 'upgrade/rollback/';
     1016                $type         = key( $hook_extra );
     1017                $slug         = 'plugin' === $type ? dirname( $hook_extra['plugin'] ) : $hook_extra['theme'];
     1018                $src          = 'plugin' === $type ? WP_PLUGIN_DIR . "/{$slug}" : get_theme_root() . "/{$slug}";
     1019                $rollback     = $rollback_dir . "{$slug}.zip";
     1020
     1021                $zip = new \ZipArchive();
     1022                if ( true === $zip->open( "$rollback", ZipArchive::CHECKCONS ) ) {
     1023                        $zip->extractTo( "$destination" );
     1024                        $zip->close();
     1025                        return true;
     1026                } else {
     1027                        return new WP_Error( 'extract_rollback_failed', __( "Extract rollback of {$type} {$slug} failed." ) );
     1028                }
     1029        }
    9401030}
    9411031
    9421032/** Plugin_Upgrader class */
  • wp-admin/includes/file.php

    diff --git a/wp-admin/includes/file.php b/wp-admin/includes/file.php
    index 993635e460..f04acf625f 100644
    a b function _unzip_file_pclzip( $file, $to, $needed_dirs = array() ) { 
    17301730 * Assumes that WP_Filesystem() has already been called and setup.
    17311731 *
    17321732 * @since 2.5.0
     1733 * @since 5.7.0 Add $first_pass parameter.
    17331734 *
    17341735 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
    17351736 *
    1736  * @param string   $from      Source directory.
    1737  * @param string   $to        Destination directory.
    1738  * @param string[] $skip_list An array of files/folders to skip copying.
     1737 * @param string   $from       Source directory.
     1738 * @param string   $to         Destination directory.
     1739 * @param string[] $skip_list  An array of files/folders to skip copying.
     1740 * @param bool     $first_pass True on the initial call, but false on subsequent calls.
    17391741 * @return true|WP_Error True on success, WP_Error on failure.
    17401742 */
    1741 function copy_dir( $from, $to, $skip_list = array() ) {
     1743function copy_dir( $from, $to, $skip_list = array(), $first_pass = true ) {
    17421744        global $wp_filesystem;
    17431745
    17441746        $dirlist = $wp_filesystem->dirlist( $from );
    17451747
     1748        if ( ! $dirlist && $first_pass ) {
     1749                return new WP_Error( 'dirlist_failed_copy_dir', __( 'Directory listing failed.' ), basename( $to ) );
     1750        }
     1751
    17461752        $from = trailingslashit( $from );
    17471753        $to   = trailingslashit( $to );
    17481754
    function copy_dir( $from, $to, $skip_list = array() ) { 
    17761782                                }
    17771783                        }
    17781784
    1779                         $result = copy_dir( $from . $filename, $to . $filename, $sub_skip_list );
     1785                        $result = copy_dir( $from . $filename, $to . $filename, $sub_skip_list, false );
    17801786                        if ( is_wp_error( $result ) ) {
    17811787                                return $result;
    17821788                        }
  • wp-admin/includes/update-core.php

    diff --git a/wp-admin/includes/update-core.php b/wp-admin/includes/update-core.php
    index aee5436305..ebe4e8e36d 100644
    a b function update_core( $from, $to ) { 
    13331333 * @ignore
    13341334 * @since 3.2.0
    13351335 * @since 3.7.0 Updated not to use a regular expression for the skip list.
     1336 * @since 5.7.0 Add $first_pass parameter.
    13361337 *
    13371338 * @see copy_dir()
    13381339 * @link https://core.trac.wordpress.org/ticket/17173
    13391340 *
    13401341 * @global WP_Filesystem_Base $wp_filesystem
    13411342 *
    1342  * @param string   $from      Source directory.
    1343  * @param string   $to        Destination directory.
    1344  * @param string[] $skip_list Array of files/folders to skip copying.
     1343 * @param string   $from       Source directory.
     1344 * @param string   $to         Destination directory.
     1345 * @param string[] $skip_list  Array of files/folders to skip copying.
     1346 * @param bool     $first_pass True on the initial call, but false on subsequent calls.
    13451347 * @return true|WP_Error True on success, WP_Error on failure.
    13461348 */
    1347 function _copy_dir( $from, $to, $skip_list = array() ) {
     1349function _copy_dir( $from, $to, $skip_list = array(), $first_pass = true ) {
    13481350        global $wp_filesystem;
    13491351
    13501352        $dirlist = $wp_filesystem->dirlist( $from );
    13511353
     1354        if ( ! $dirlist && $first_pass ) {
     1355                return new WP_Error( 'dirlist_failed__copy_dir', __( 'Directory listing failed.' ), basename( $to ) );
     1356        }
     1357
    13521358        $from = trailingslashit( $from );
    13531359        $to   = trailingslashit( $to );
    13541360
    function _copy_dir( $from, $to, $skip_list = array() ) { 
    13881394                                }
    13891395                        }
    13901396
    1391                         $result = _copy_dir( $from . $filename, $to . $filename, $sub_skip_list );
     1397                        $result = _copy_dir( $from . $filename, $to . $filename, $sub_skip_list, false );
    13921398                        if ( is_wp_error( $result ) ) {
    13931399                                return $result;
    13941400                        }