diff -r 3d4e9c994f10 -r a86126ab1dd4 wp/wp-admin/includes/class-wp-upgrader.php --- a/wp/wp-admin/includes/class-wp-upgrader.php Tue Oct 22 16:11:46 2019 +0200 +++ b/wp/wp-admin/includes/class-wp-upgrader.php Tue Dec 15 13:49:49 2020 +0100 @@ -76,17 +76,17 @@ * * @since 2.8.0 * - * @var WP_Error|array $result { - * @type string $source The full path to the source the files were installed from. - * @type string $source_files List of all the files in the source directory. - * @type string $destination The full path to the installation destination folder. - * @type string $destination_name The name of the destination folder, or empty if `$destination` - * and `$local_destination` are the same. - * @type string $local_destination The full local path to the destination folder. This is usually - * the same as `$destination`. - * @type string $remote_destination The full remote path to the destination folder - * (i.e., from `$wp_filesystem`). - * @type bool $clear_destination Whether the destination folder was cleared. + * @var array|WP_Error $result { + * @type string $source The full path to the source the files were installed from. + * @type string $source_files List of all the files in the source directory. + * @type string $destination The full path to the installation destination folder. + * @type string $destination_name The name of the destination folder, or empty if `$destination` + * and `$local_destination` are the same. + * @type string $local_destination The full local path to the destination folder. This is usually + * the same as `$destination`. + * @type string $remote_destination The full remote path to the destination folder + * (i.e., from `$wp_filesystem`). + * @type bool $clear_destination Whether the destination folder was cleared. * } */ public $result = array(); @@ -116,7 +116,7 @@ * * @since 2.8.0 * - * @param WP_Upgrader_Skin $skin The upgrader skin to use. Default is a WP_Upgrader_Skin. + * @param WP_Upgrader_Skin $skin The upgrader skin to use. Default is a WP_Upgrader_Skin * instance. */ public function __construct( $skin = null ) { @@ -153,7 +153,7 @@ $this->strings['fs_no_content_dir'] = __( 'Unable to locate WordPress content directory (wp-content).' ); $this->strings['fs_no_plugins_dir'] = __( 'Unable to locate WordPress plugin directory.' ); $this->strings['fs_no_themes_dir'] = __( 'Unable to locate WordPress theme directory.' ); - /* translators: %s: directory name */ + /* translators: %s: Directory name. */ $this->strings['fs_no_folder'] = __( 'Unable to locate needed folder (%s).' ); $this->strings['download_failed'] = __( 'Download failed.' ); @@ -175,17 +175,18 @@ * * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. * - * @param array $directories Optional. A list of directories. If any of these do - * not exist, a WP_Error object will be returned. - * Default empty array. - * @param bool $allow_relaxed_file_ownership Whether to allow relaxed file ownership. - * Default false. + * @param string[] $directories Optional. Array of directories. If any of these do + * not exist, a WP_Error object will be returned. + * Default empty array. + * @param bool $allow_relaxed_file_ownership Whether to allow relaxed file ownership. + * Default false. * @return bool|WP_Error True if able to connect, false or a WP_Error otherwise. */ public function fs_connect( $directories = array(), $allow_relaxed_file_ownership = false ) { global $wp_filesystem; - if ( false === ( $credentials = $this->skin->request_filesystem_credentials( false, $directories[0], $allow_relaxed_file_ownership ) ) ) { + $credentials = $this->skin->request_filesystem_credentials( false, $directories[0], $allow_relaxed_file_ownership ); + if ( false === $credentials ) { return false; } @@ -194,7 +195,7 @@ if ( is_object( $wp_filesystem ) && $wp_filesystem->errors->has_errors() ) { $error = $wp_filesystem->errors; } - // Failed to connect, Error and request again + // Failed to connect. Error and request again. $this->skin->request_filesystem_credentials( $error, $directories[0], $allow_relaxed_file_ownership ); return false; } @@ -237,37 +238,40 @@ } } return true; - } //end fs_connect(); + } /** * Download a package. * * @since 2.8.0 + * @since 5.5.0 Added the `$hook_extra` parameter. * * @param string $package The URI of the package. If this is the full path to an * existing local file, it will be returned untouched. * @param bool $check_signatures Whether to validate file signatures. Default false. + * @param array $hook_extra Extra arguments to pass to the filter hooks. Default empty array. * @return string|WP_Error The full path to the downloaded package file, or a WP_Error object. */ - public function download_package( $package, $check_signatures = false ) { - + public function download_package( $package, $check_signatures = false, $hook_extra = array() ) { /** * Filters whether to return the package. * * @since 3.7.0 + * @since 5.5.0 Added the `$hook_extra` parameter. * - * @param bool $reply Whether to bail without returning the package. - * Default false. - * @param string $package The package file name. - * @param WP_Upgrader $this The WP_Upgrader instance. + * @param bool $reply Whether to bail without returning the package. + * Default false. + * @param string $package The package file name. + * @param WP_Upgrader $this The WP_Upgrader instance. + * @param array $hook_extra Extra arguments passed to hooked filters. */ - $reply = apply_filters( 'upgrader_pre_download', false, $package, $this ); + $reply = apply_filters( 'upgrader_pre_download', false, $package, $this, $hook_extra ); if ( false !== $reply ) { return $reply; } - if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) { //Local file or remote? - return $package; //must be a local file.. + if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) { // Local file or remote? + return $package; // Must be a local file. } if ( empty( $package ) ) { @@ -304,7 +308,7 @@ $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/'; - //Clean up contents of upgrade directory beforehand. + // Clean up contents of upgrade directory beforehand. $upgrade_files = $wp_filesystem->dirlist( $upgrade_folder ); if ( ! empty( $upgrade_files ) ) { foreach ( $upgrade_files as $file ) { @@ -312,15 +316,15 @@ } } - // We need a working directory - Strip off any .tmp or .zip suffixes + // We need a working directory - strip off any .tmp or .zip suffixes. $working_dir = $upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' ); - // Clean up working directory + // Clean up working directory. if ( $wp_filesystem->is_dir( $working_dir ) ) { $wp_filesystem->delete( $working_dir, true ); } - // Unzip package to working directory + // Unzip package to working directory. $result = unzip_file( $package, $working_dir ); // Once extracted, delete the package if required. @@ -330,7 +334,7 @@ if ( is_wp_error( $result ) ) { $wp_filesystem->delete( $working_dir, true ); - if ( 'incompatible_archive' == $result->get_error_code() ) { + if ( 'incompatible_archive' === $result->get_error_code() ) { return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() ); } return $result; @@ -345,9 +349,9 @@ * @since 4.9.0 * @access protected * - * @param array $nested_files Array of files as returned by WP_Filesystem::dirlist() - * @param string $path Relative path to prepend to child nodes. Optional. - * @return array $files A flattened array of the $nested_files specified. + * @param array $nested_files Array of files as returned by WP_Filesystem::dirlist(). + * @param string $path Relative path to prepend to child nodes. Optional. + * @return array A flattened array of the $nested_files specified. */ protected function flatten_dirlist( $nested_files, $path = '' ) { $files = array(); @@ -355,11 +359,11 @@ foreach ( $nested_files as $name => $details ) { $files[ $path . $name ] = $details; - // Append children recursively + // Append children recursively. if ( ! empty( $details['files'] ) ) { $children = $this->flatten_dirlist( $details['files'], $path . $name . '/' ); - // Merge keeping possible numeric keys, which array_merge() will reindex from 0..n + // Merge keeping possible numeric keys, which array_merge() will reindex from 0..n. $files = $files + $children; } } @@ -387,7 +391,7 @@ return true; } - // Flatten the file list to iterate over + // Flatten the file list to iterate over. $files = $this->flatten_dirlist( $files ); // Check all files are writable before attempting to clear the destination. @@ -397,7 +401,7 @@ foreach ( $files as $filename => $file_details ) { if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) { // Attempt to alter permissions to allow writes and try again. - $wp_filesystem->chmod( $remote_destination . $filename, ( 'd' == $file_details['type'] ? FS_CHMOD_DIR : FS_CHMOD_FILE ) ); + $wp_filesystem->chmod( $remote_destination . $filename, ( 'd' === $file_details['type'] ? FS_CHMOD_DIR : FS_CHMOD_FILE ) ); if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) { $unwritable_files[] = $filename; } @@ -449,8 +453,8 @@ global $wp_filesystem, $wp_theme_directories; $defaults = array( - 'source' => '', // Please always pass this - 'destination' => '', // and this + 'source' => '', // Please always pass this. + 'destination' => '', // ...and this. 'clear_destination' => false, 'clear_working' => false, 'abort_if_destination_exists' => true, @@ -464,7 +468,7 @@ $destination = $args['destination']; $clear_destination = $args['clear_destination']; - @set_time_limit( 300 ); + set_time_limit( 300 ); if ( empty( $source ) || empty( $destination ) ) { return new WP_Error( 'bad_request', $this->strings['bad_request'] ); @@ -489,19 +493,23 @@ return $res; } - //Retain the Original source and destinations + // Retain the original source and destinations. $remote_source = $args['source']; $local_destination = $destination; $source_files = array_keys( $wp_filesystem->dirlist( $remote_source ) ); $remote_destination = $wp_filesystem->find_folder( $local_destination ); - //Locate which directory to copy to the new folder, This is based on the actual folder holding the files. - if ( 1 == count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) { //Only one folder? Then we want its contents. + // Locate which directory to copy to the new folder. This is based on the actual folder holding the files. + if ( 1 === count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) { + // Only one folder? Then we want its contents. $source = trailingslashit( $args['source'] ) . trailingslashit( $source_files[0] ); } elseif ( count( $source_files ) == 0 ) { - return new WP_Error( 'incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files'] ); // There are no files? - } else { // It's only a single file, the upgrader will use the folder name of this file as the destination folder. Folder name is based on zip filename. + // There are no files? + return new WP_Error( 'incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files'] ); + } else { + // It's only a single file, the upgrader will use the folder name of this file as the destination folder. + // Folder name is based on zip filename. $source = trailingslashit( $args['source'] ); } @@ -540,7 +548,7 @@ $protected_directories = array_merge( $protected_directories, $wp_theme_directories ); } - if ( in_array( $destination, $protected_directories ) ) { + if ( in_array( $destination, $protected_directories, true ) ) { $remote_destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $source ) ); $destination = trailingslashit( $destination ) . trailingslashit( basename( $source ) ); } @@ -556,10 +564,10 @@ * * @since 2.8.0 * - * @param mixed $removed Whether the destination was cleared. true on success, WP_Error on failure - * @param string $local_destination The local package destination. - * @param string $remote_destination The remote package destination. - * @param array $hook_extra Extra arguments passed to hooked filters. + * @param true|WP_Error $removed Whether the destination was cleared. true upon success, WP_Error on failure. + * @param string $local_destination The local package destination. + * @param string $remote_destination The remote package destination. + * @param array $hook_extra Extra arguments passed to hooked filters. */ $removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] ); @@ -567,21 +575,22 @@ return $removed; } } elseif ( $args['abort_if_destination_exists'] && $wp_filesystem->exists( $remote_destination ) ) { - //If we're not clearing the destination folder and something exists there already, Bail. - //But first check to see if there are actually any files in the folder. + // If we're not clearing the destination folder and something exists there already, bail. + // But first check to see if there are actually any files in the folder. $_files = $wp_filesystem->dirlist( $remote_destination ); if ( ! empty( $_files ) ) { - $wp_filesystem->delete( $remote_source, true ); //Clear out the source files. + $wp_filesystem->delete( $remote_source, true ); // Clear out the source files. return new WP_Error( 'folder_exists', $this->strings['folder_exists'], $remote_destination ); } } - //Create destination if needed + // Create destination if needed. if ( ! $wp_filesystem->exists( $remote_destination ) ) { if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) { return new WP_Error( 'mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination ); } } + // Copy new version of item into place. $result = copy_dir( $source, $remote_destination ); if ( is_wp_error( $result ) ) { @@ -591,13 +600,13 @@ return $result; } - //Clear the Working folder? + // Clear the working folder? if ( $args['clear_working'] ) { $wp_filesystem->delete( $remote_source, true ); } $destination_name = basename( str_replace( $local_destination, '', $destination ) ); - if ( '.' == $destination_name ) { + if ( '.' === $destination_name ) { $destination_name = ''; } @@ -619,7 +628,7 @@ return $res; } - //Bombard the calling function will all the info which we've just used. + // Bombard the calling function will all the info which we've just used. return $this->result; } @@ -653,16 +662,16 @@ * @type array $hook_extra Extra arguments to pass to the filter hooks called by * WP_Upgrader::run(). * } - * @return array|false|WP_error The result from self::install_package() on success, otherwise a WP_Error, + * @return array|false|WP_Error The result from self::install_package() on success, otherwise a WP_Error, * or false if unable to connect to the filesystem. */ public function run( $options ) { $defaults = array( 'package' => '', // Please always pass this. - 'destination' => '', // And this + 'destination' => '', // ...and this. 'clear_destination' => false, - 'abort_if_destination_exists' => true, // Abort if the Destination directory exists, Pass clear_destination as false please + 'abort_if_destination_exists' => true, // Abort if the destination directory exists. Pass clear_destination as false please. 'clear_working' => true, 'is_multi' => false, 'hook_extra' => array(), // Pass any extra $hook_extra args here, this will be passed to any hooked filters. @@ -702,11 +711,11 @@ */ $options = apply_filters( 'upgrader_package_options', $options ); - if ( ! $options['is_multi'] ) { // call $this->header separately if running multiple times + if ( ! $options['is_multi'] ) { // Call $this->header separately if running multiple times. $this->skin->header(); } - // Connect to the Filesystem first. + // Connect to the filesystem first. $res = $this->fs_connect( array( WP_CONTENT_DIR, $options['destination'] ) ); // Mainly for non-connected filesystem. if ( ! $res ) { @@ -731,15 +740,15 @@ * Download the package (Note, This just returns the filename * of the file if the package is a local file) */ - $download = $this->download_package( $options['package'], true ); + $download = $this->download_package( $options['package'], true, $options['hook_extra'] ); // Allow for signature soft-fail. // WARNING: This may be removed in the future. if ( is_wp_error( $download ) && $download->get_error_data( 'softfail-filename' ) ) { // Don't output the 'no signature could be found' failure message for now. - if ( 'signature_verification_no_signature' != $download->get_error_code() || WP_DEBUG ) { - // Outout the failure error as a normal feedback, and not as an error: + if ( 'signature_verification_no_signature' !== $download->get_error_code() || WP_DEBUG ) { + // Output the failure error as a normal feedback, and not as an error. $this->skin->feedback( $download->get_error_message() ); // Report this failure back to WordPress.org for debugging purposes. @@ -764,7 +773,7 @@ return $download; } - $delete_package = ( $download != $options['package'] ); // Do not delete a "local" file + $delete_package = ( $download != $options['package'] ); // Do not delete a "local" file. // Unzips the file into a temporary directory. $working_dir = $this->unpack_package( $download, $delete_package ); @@ -792,7 +801,10 @@ $this->skin->set_result( $result ); if ( is_wp_error( $result ) ) { $this->skin->error( $result ); - $this->skin->feedback( 'process_failed' ); + + if ( ! method_exists( $this->skin, 'hide_process_failed' ) || ! $this->skin->hide_process_failed( $result ) ) { + $this->skin->feedback( 'process_failed' ); + } } else { // Installation succeeded. $this->skin->feedback( 'process_success' ); @@ -856,7 +868,7 @@ $file = $wp_filesystem->abspath() . '.maintenance'; if ( $enable ) { $this->skin->feedback( 'maintenance_start' ); - // Create maintenance file to signal that we are upgrading + // Create maintenance file to signal that we are upgrading. $maintenance_string = ''; $wp_filesystem->delete( $file ); $wp_filesystem->put_contents( $file, $maintenance_string, FS_CHMOD_FILE );