WordPress.org

Make WordPress Core

Ticket #51857: 51857.6.diff

File 51857.6.diff, 7.6 KB (added by afragen, 8 weeks ago)

bubble up error for extract_rollback

  • 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..f139bcd138 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                        $rollback_result = $this->extract_rollback( $destination, $args['hook_extra'] );
     598                        if ( is_wp_error( $rollback_result ) ) {
     599                                $result->merge_from( $rollback_result );
     600                        }
    597601                        if ( $args['clear_working'] ) {
    598602                                $wp_filesystem->delete( $remote_source, true );
    599603                        }
    class WP_Upgrader { 
    775779
    776780                $delete_package = ( $download != $options['package'] ); // Do not delete a "local" file.
    777781
     782                // Zip the plugin/theme being updated to rollback directory.
     783                add_filter( 'upgrader_pre_install', array( $this, 'zip_to_rollback_dir' ), 15, 2 );
     784
    778785                // Unzips the file into a temporary directory.
    779786                $working_dir = $this->unpack_package( $download, $delete_package );
    780787                if ( is_wp_error( $working_dir ) ) {
    class WP_Upgrader { 
    937944                return delete_option( $lock_name . '.lock' );
    938945        }
    939946
     947
     948        /**
     949         * Create a zip archive of the plugin/theme being upgraded into a rollback directory.
     950         *
     951         * @since 5.7.0
     952         * @uses 'upgrader_pre_install' filter.
     953         *
     954         * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
     955         * @param  bool               $response      Boolean response to 'upgrader_pre_install' filter.
     956         *                                           Default is true.
     957         * @param  array              $hook_extra    Array of data for plugin/theme being updated.
     958         *
     959         * @return bool|WP_Error
     960         */
     961        public function zip_to_rollback_dir( $response, $hook_extra ) {
     962                global $wp_filesystem;
     963
     964                $rollback_dir = $wp_filesystem->wp_content_dir() . 'upgrade/rollback/';
     965                $type         = key( $hook_extra );
     966                $slug         = 'plugin' === $type ? dirname( $hook_extra['plugin'] ) : $hook_extra['theme'];
     967                $src          = 'plugin' === $type ? WP_PLUGIN_DIR . "/{$slug}" : get_theme_root(). "/{$slug}";
     968                if ( $wp_filesystem->mkdir( $rollback_dir ) ) {
     969                        $path_prefix = strlen( $src ) + 1;
     970                        $zip         = new ZipArchive();
     971
     972                        if ( true === $zip->open( "{$rollback_dir}{$slug}.zip", ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) {
     973                                $files = new RecursiveIteratorIterator(
     974                                        new RecursiveDirectoryIterator( $src ),
     975                                        RecursiveIteratorIterator::LEAVES_ONLY
     976                                );
     977
     978                                foreach ( $files as $name => $file ) {
     979                                        // Skip directories (they would be added automatically).
     980                                        if ( ! $file->isDir() ) {
     981                                                // Get real and relative path for current file.
     982                                                $file_path     = $file->getRealPath();
     983                                                $relative_path = substr( $file_path, $path_prefix );
     984
     985                                                // Add current file to archive.
     986                                                $zip->addFile( $file_path, $relative_path );
     987                                        }
     988                                }
     989
     990                                $zip->close();
     991                        } else {
     992                                return new WP_Error( 'zip_rollback_failed', __( 'Zip plugin/theme to rollback directory failed.' ) );
     993                        }
     994                }
     995
     996                return $response;
     997        }
     998
     999        /**
     1000         * Extract zipped rollback to original location.
     1001         *
     1002         * @since 5.7.0
     1003         *
     1004         * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
     1005         * @param  string             $destination   File path of plugin/theme.
     1006         * @param  array              $hook_extra    Array of data for plugin/theme being updated.
     1007         *
     1008         * @return bool|WP_Error
     1009         */
     1010        public function extract_rollback( $destination, $hook_extra ) {
     1011                global $wp_filesystem;
     1012
     1013                // Start with a clean slate.
     1014                if ( $wp_filesystem->is_dir( $destination ) ) {
     1015                        $wp_filesystem->delete( $destination, true );
     1016                }
     1017
     1018                $rollback_dir = $wp_filesystem->wp_content_dir() . 'upgrade/rollback/';
     1019                $type         = key( $hook_extra );
     1020                $slug         = 'plugin' === $type ? dirname( $hook_extra['plugin'] ) : $hook_extra['theme'];
     1021                $rollback     = $rollback_dir . "{$slug}.zip";
     1022
     1023                $result = unzip_file( $rollback, $destination );
     1024                if ( is_wp_error( $result ) ) {
     1025                        return new WP_Error( 'extract_rollback_failed', __( "Extract rollback of {$type} {$slug} failed." ) );
     1026                }
     1027        }
    9401028}
    9411029
    9421030/** 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                        }