Make WordPress Core

Ticket #30921: 30921.2.diff

File 30921.2.diff, 7.8 KB (added by dd32, 10 years ago)
  • src/wp-admin/includes/class-wp-upgrader.php

    class WP_Upgrader { 
    120120                $this->strings['fs_unavailable'] = __('Could not access filesystem.');
    121121                $this->strings['fs_error'] = __('Filesystem error.');
    122122                $this->strings['fs_no_root_dir'] = __('Unable to locate WordPress Root directory.');
    123123                $this->strings['fs_no_content_dir'] = __('Unable to locate WordPress Content directory (wp-content).');
    124124                $this->strings['fs_no_plugins_dir'] = __('Unable to locate WordPress Plugin directory.');
    125125                $this->strings['fs_no_themes_dir'] = __('Unable to locate WordPress Theme directory.');
    126126                /* translators: %s: directory name */
    127127                $this->strings['fs_no_folder'] = __('Unable to locate needed folder (%s).');
    128128
    129129                $this->strings['download_failed'] = __('Download failed.');
    130130                $this->strings['installing_package'] = __('Installing the latest version…');
    131131                $this->strings['no_files'] = __('The package contains no files.');
    132132                $this->strings['folder_exists'] = __('Destination folder already exists.');
    133133                $this->strings['mkdir_failed'] = __('Could not create directory.');
    134134                $this->strings['incompatible_archive'] = __('The package could not be installed.');
     135                $this->strings['files_not_writable'] = __( 'The update cannot be installed because we will be unable to copy some files. This is usually due to inconsistent file permissions.' );
    135136
    136137                $this->strings['maintenance_start'] = __('Enabling Maintenance mode…');
    137138                $this->strings['maintenance_end'] = __('Disabling Maintenance mode…');
    138139        }
    139140
    140141        /**
    141142         * Connect to the filesystem.
    142143         *
    143144         * @since 2.8.0
    144145         *
    145146         * @global WP_Filesystem_Base $wp_filesystem Subclass
    146147         *
    147148         * @param array $directories                  Optional. A list of directories. If any of these do
    148149         *                                            not exist, a {@see WP_Error} object will be returned.
    149150         *                                            Default empty array.
    class WP_Upgrader { 
    281282                if ( $delete_package )
    282283                        unlink($package);
    283284
    284285                if ( is_wp_error($result) ) {
    285286                        $wp_filesystem->delete($working_dir, true);
    286287                        if ( 'incompatible_archive' == $result->get_error_code() ) {
    287288                                return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() );
    288289                        }
    289290                        return $result;
    290291                }
    291292
    292293                return $working_dir;
    293294        }
    294295
    295296        /**
     297         * Clears the directory where this item is going to be installed into.
     298         *
     299         * @since 4.3.0
     300         *
     301         * @global WP_Filesystem_Base $wp_filesystem Subclass
     302         *
     303         * @param string $remote_destination The location on the remote filesystem to be cleared
     304         *
     305         * @return bool|WP_Error true upon success, {@see WP_Error} on failure.
     306         */
     307        function clear_destination( $remote_destination ) {
     308                global $wp_filesystem;
     309
     310                if ( ! $wp_filesystem->exists( $remote_destination ) ) {
     311                        return true;
     312                }
     313
     314                // Check all files are writable before attempting to clear the destination
     315                $unwritable_files = array();
     316
     317                $_files = $wp_filesystem->dirlist( $remote_destination, true, true );
     318                // Flatten the resulting array, iterate using each as we append to the array during iteration
     319                while ( $f = each( $_files ) ) {
     320                        $file = $f['value'];
     321                        $name = $f['key'];
     322
     323                        if ( ! isset( $file['files'] ) ) {
     324                                continue;
     325                        }
     326
     327                        foreach ( $file['files'] as $filename => $details ) {
     328                                $_files[ $name . '/' . $filename ] = $details;
     329                        }
     330                }
     331
     332                // Check writability
     333                foreach ( $_files as $filename => $file_details ) {
     334                        if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) {
     335                                // Attempt to alter permissions to allow writes and try again
     336                                $wp_filesystem->chmod( $remote_destination . $filename, ( 'd' == $file_details['type'] ? FS_CHMOD_DIR : FS_CHMOD_FILE ) );
     337                                if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) {
     338                                        $unwritable_files[] = $filename;
     339                                }
     340                        }
     341                }
     342
     343                if ( ! empty( $unwritable_files ) ) {
     344                        return new WP_Error( 'files_not_writable', $this->strings['files_not_writable'], implode( ', ', $unwritable_files ) );
     345                }
     346
     347                if ( ! $wp_filesystem->delete( $remote_destination, true ) ) {
     348                        return new WP_Error( 'remove_old_failed', $this->strings['remove_old_failed'] );
     349                }
     350
     351                return true;
     352        }
     353
     354        /**
    296355         * Install a package.
    297356         *
    298357         * Copies the contents of a package form a source directory, and installs them in
    299358         * a destination directory. Optionally removes the source. It can also optionally
    300359         * clear out the destination folder if it already exists.
    301360         *
    302361         * @since 2.8.0
    303362         *
    304363         * @global WP_Filesystem_Base $wp_filesystem Subclass
    305364         * @global array              $wp_theme_directories
    306365         *
    307366         * @param array|string $args {
    308367         *     Optional. Array or string of arguments for installing a package. Default empty array.
    309368         *
    310369         *     @type string $source                      Required path to the package source. Default empty.
    class WP_Upgrader { 
    405464                 * destination directory (WP_PLUGIN_DIR / wp-content/themes) intending
    406465                 * to copy the directory into the directory, whilst they pass the source
    407466                 * as the actual files to copy.
    408467                 */
    409468                $protected_directories = array( ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes' );
    410469
    411470                if ( is_array( $wp_theme_directories ) ) {
    412471                        $protected_directories = array_merge( $protected_directories, $wp_theme_directories );
    413472                }
    414473                if ( in_array( $destination, $protected_directories ) ) {
    415474                        $remote_destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $source ) );
    416475                        $destination = trailingslashit( $destination ) . trailingslashit( basename( $source ) );
    417476                }
    418477
    419478                if ( $clear_destination ) {
    420                         //We're going to clear the destination if there's something there
     479                        // We're going to clear the destination if there's something there
    421480                        $this->skin->feedback('remove_old');
    422                         $removed = true;
    423                         if ( $wp_filesystem->exists( $remote_destination ) ) {
    424                                 $removed = $wp_filesystem->delete( $remote_destination, true );
    425                         }
     481
     482                        $removed = $this->clear_destination( $remote_destination );
    426483
    427484                        /**
    428485                         * Filter whether the upgrader cleared the destination.
    429486                         *
    430487                         * @since 2.8.0
    431488                         *
    432                          * @param bool   $removed            Whether the destination was cleared.
     489                         * @param mixed  $removed            Whether the destination was cleared. true on success, WP_Error on failure
    433490                         * @param string $local_destination  The local package destination.
    434491                         * @param string $remote_destination The remote package destination.
    435492                         * @param array  $hook_extra         Extra arguments passed to hooked filters.
    436493                         */
    437494                        $removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] );
    438495
    439                         if ( is_wp_error($removed) ) {
     496                        if ( is_wp_error( $removed ) ) {
    440497                                return $removed;
    441                         } elseif ( ! $removed ) {
    442                                 return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);
    443498                        }
    444499                } elseif ( $args['abort_if_destination_exists'] && $wp_filesystem->exists($remote_destination) ) {
    445500                        //If we're not clearing the destination folder and something exists there already, Bail.
    446501                        //But first check to see if there are actually any files in the folder.
    447502                        $_files = $wp_filesystem->dirlist($remote_destination);
    448503                        if ( ! empty($_files) ) {
    449504                                $wp_filesystem->delete($remote_source, true); //Clear out the source files.
    450505                                return new WP_Error('folder_exists', $this->strings['folder_exists'], $remote_destination );
    451506                        }
    452507                }
    453508
    454509                //Create destination if needed
    455510                if ( ! $wp_filesystem->exists( $remote_destination ) ) {
    456511                        if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) {
    457512                                return new WP_Error( 'mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination );