$this->strings['folder_exists'] = __('Destination folder already exists.');
$this->strings['mkdir_failed'] = __('Could not create directory.');
$this->strings['incompatible_archive'] = __('The package could not be installed.');
+ $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.' );
$this->strings['maintenance_start'] = __('Enabling Maintenance mode…');
$this->strings['maintenance_end'] = __('Disabling Maintenance mode…');
*
* @since 2.8.0
*
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
* @param array $directories Optional. A list of directories. If any of these do
* not exist, a {@see WP_Error} object will be returned.
* Default empty array.
*
* @since 2.8.0
*
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
* @param string $package Full path to the package file.
* @param bool $delete_package Optional. Whether to delete the package file after attempting
* to unpack it. Default true.
return $working_dir;
}
+ /**
+ * Clears the directory where this item is going to be installed into.
+ *
+ * @since 4.3.0
+ *
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
+ * @param string $remote_destination The location on the remote filesystem to be cleared
+ * @return bool|WP_Error True upon success, WP_Error on failure.
+ */
+ public function clear_destination( $remote_destination ) {
+ global $wp_filesystem;
+
+ if ( ! $wp_filesystem->exists( $remote_destination ) ) {
+ return true;
+ }
+
+ // Check all files are writable before attempting to clear the destination.
+ $unwritable_files = array();
+
+ $_files = $wp_filesystem->dirlist( $remote_destination, true, true );
+
+ // Flatten the resulting array, iterate using each as we append to the array during iteration.
+ while ( $f = each( $_files ) ) {
+ $file = $f['value'];
+ $name = $f['key'];
+
+ if ( ! isset( $file['files'] ) ) {
+ continue;
+ }
+
+ foreach ( $file['files'] as $filename => $details ) {
+ $_files[ $name . '/' . $filename ] = $details;
+ }
+ }
+
+ // Check writability.
+ 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 ) );
+ if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) {
+ $unwritable_files[] = $filename;
+ }
+ }
+ }
+
+ if ( ! empty( $unwritable_files ) ) {
+ return new WP_Error( 'files_not_writable', $this->strings['files_not_writable'], implode( ', ', $unwritable_files ) );
+ }
+
+ if ( ! $wp_filesystem->delete( $remote_destination, true ) ) {
+ return new WP_Error( 'remove_old_failed', $this->strings['remove_old_failed'] );
+ }
+
+ return true;
+ }
+
/**
* Install a package.
*
*
* @since 2.8.0
*
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ * @global array $wp_theme_directories
+ *
* @param array|string $args {
* Optional. Array or string of arguments for installing a package. Default empty array.
*
}
if ( $clear_destination ) {
- //We're going to clear the destination if there's something there
+ // We're going to clear the destination if there's something there
$this->skin->feedback('remove_old');
- $removed = true;
- if ( $wp_filesystem->exists( $remote_destination ) ) {
- $removed = $wp_filesystem->delete( $remote_destination, true );
- }
+
+ $removed = $this->clear_destination( $remote_destination );
/**
* Filter whether the upgrader cleared the destination.
*
* @since 2.8.0
*
- * @param bool $removed Whether the destination was cleared.
+ * @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.
*/
$removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] );
- if ( is_wp_error($removed) ) {
+ if ( is_wp_error( $removed ) ) {
return $removed;
- } elseif ( ! $removed ) {
- return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);
}
} 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.
$options = wp_parse_args( $options, $defaults );
+ /**
+ * Filter the package options before running an update.
+ *
+ * @since 4.3.0
+ *
+ * @param array $options {
+ * Options used by the upgrader.
+ *
+ * @type string $package Package for update.
+ * @type string $destination Update location.
+ * @type bool $clear_destination Clear the destination resource.
+ * @type bool $clear_working Clear the working resource.
+ * @type bool $abort_if_destination_exists Abort if the Destination directory exists.
+ * @type bool $is_multi Whether the upgrader is running multiple times.
+ * @type array $hook_extra Extra hook arguments.
+ * }
+ */
+ $options = apply_filters( 'upgrader_package_options', $options );
+
if ( ! $options['is_multi'] ) { // call $this->header separately if running multiple times
$this->skin->header();
}
*
* @since 2.8.0
*
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
* @param bool $enable True to enable maintenance mode, false to disable.
*/
public function maintenance_mode( $enable = false ) {
*
* @since 3.3.0
*
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
* @param string $source The path to the downloaded package source.
* @return string|WP_Error The source as passed, or a {@see WP_Error} object if no plugins were found.
*/
// Check the folder contains at least 1 valid plugin.
$plugins_found = false;
- foreach ( glob( $working_directory . '*.php' ) as $file ) {
- $info = get_plugin_data($file, false, false);
- if ( !empty( $info['Name'] ) ) {
- $plugins_found = true;
- break;
+ $files = glob( $working_directory . '*.php' );
+ if ( $files ) {
+ foreach ( $files as $file ) {
+ $info = get_plugin_data( $file, false, false );
+ if ( ! empty( $info['Name'] ) ) {
+ $plugins_found = true;
+ break;
+ }
}
}
* {@see Plugin_Upgrader::upgrade()} and {@see Plugin_Upgrader::bulk_upgrade()}.
*
* @since 2.8.0
+ *
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
+ * @param bool|WP_Error $removed
+ * @param string $local_destination
+ * @param string $remote_destination
+ * @param array $plugin
+ * @return WP_Error|bool
*/
public function delete_old_plugin($removed, $local_destination, $remote_destination, $plugin) {
global $wp_filesystem;
* Hooked to the {@see 'upgrader_post_install'} filter by {@see Theme_Upgrader::install()}.
*
* @since 3.4.0
+ *
+ * @param bool $install_result
+ * @param array $hook_extra
+ * @param array $child_result
+ * @return type
*/
public function check_parent_theme_filter( $install_result, $hook_extra, $child_result ) {
// Check to see if we need to install a parent theme
* @since 3.4.0
*
* @param array $actions Preview actions.
+ * @return array
*/
public function hide_activate_preview_actions( $actions ) {
unset($actions['activate'], $actions['preview']);
*
* @since 3.3.0
*
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
* @param string $source The full path to the package source.
* @return string|WP_Error The source or a WP_Error.
*/
* {@see Theme_Upgrader::bulk_upgrade()}.
*
* @since 2.8.0
+ *
+ * @param bool|WP_Error $return
+ * @param array $theme
+ * @return bool|WP_Error
*/
public function current_before($return, $theme) {
-
if ( is_wp_error($return) )
return $return;
* and {@see Theme_Upgrader::bulk_upgrade()}.
*
* @since 2.8.0
+ *
+ * @param bool|WP_Error $return
+ * @param array $theme
+ * @return bool|WP_Error
*/
public function current_after($return, $theme) {
if ( is_wp_error($return) )
* and {@see Theme_Upgrader::bulk_upgrade()}.
*
* @since 2.8.0
+ *
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
+ * @param bool $removed
+ * @param string $local_destination
+ * @param string $remote_destination
+ * @param array $theme
+ * @return bool
*/
public function delete_old_theme( $removed, $local_destination, $remote_destination, $theme ) {
global $wp_filesystem;
}
-add_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
-
/**
* Language pack upgrader, for updating translations of plugins, themes, and core.
*
* Hooked to the {@see 'upgrader_process_complete'} action by default.
*
* @since 3.7.0
+ *
+ * @static
+ *
+ * @param false|WP_Upgrader $upgrader
*/
public static function async_upgrade( $upgrader = false ) {
// Avoid recursion.
* @param string|false $update Optional. Whether an update offer is available. Default false.
* @param array $args Optional. Other optional arguments, see
* {@see Language_Pack_Upgrader::bulk_upgrade()}. Default empty array.
- * @return array|WP_Error The result of the upgrade, or a {@see wP_Error} object instead.
+ * @return array|bool|WP_Error The result of the upgrade, or a {@see wP_Error} object instead.
*/
public function upgrade( $update = false, $args = array() ) {
if ( $update ) {
*
* @since 3.7.0
*
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
* @param array $language_updates Optional. Language pack updates. Default empty array.
* @param array $args {
* Optional. Other arguments for upgrading multiple language packs. Default empty array
* @type bool $clear_update_cache Whether to clear the update cache when done.
* Default true.
* }
- * @return array|true|false|WP_Error Will return an array of results, or true if there are no updates,
+ * @return array|bool|WP_Error Will return an array of results, or true if there are no updates,
* false or WP_Error for initial errors.
*/
public function bulk_upgrade( $language_updates = array(), $args = array() ) {
// Remove any existing upgrade filters from the plugin/theme upgraders #WP29425 & #WP29230
remove_all_filters( 'upgrader_pre_install' );
remove_all_filters( 'upgrader_clear_destination' );
- remove_all_filterS( 'upgrader_post_install' );
+ remove_all_filters( 'upgrader_post_install' );
remove_all_filters( 'upgrader_source_selection' );
add_filter( 'upgrader_source_selection', array( $this, 'check_package' ), 10, 2 );
* {@see Language_Pack_Upgrader::bulk_upgrade()}.
*
* @since 3.7.0
+ *
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ *
+ * @param string|WP_Error $source
+ * @param string $remote_source
*/
public function check_package( $source, $remote_source ) {
global $wp_filesystem;
*
* @since 3.7.0
*
- * @param object The data for an update.
+ * @param object $update The data for an update.
* @return string The name of the item being updated.
*/
public function get_name_for_update( $update ) {
*
* @since 2.8.0
*
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ * @global callback $_wp_filesystem_direct_method
+ *
* @param object $current Response object for whether WordPress is current.
* @param array $args {
* Optional. Arguments for upgrading WordPress core. Default empty array.
*
* @since 3.7.0
*
+ * @static
+ *
* @param string $offered_ver The offered version, of the format x.y.z.
* @return bool True if we should update to the offered version, otherwise false.
*/
*
* @since 3.7.0
*
+ * @global string $wp_version
+ * @global string $wp_local_package
+ *
* @return bool True if the checksums match, otherwise false.
*/
public function check_files() {
*
* @since 3.7.0
*
+ * @global wpdb $wpdb
+ *
* @param string $type The type of update being checked: 'core', 'theme',
* 'plugin', 'translation'.
* @param object $item The update offer.
*
* @param string $type The type of update being checked: 'core', 'theme', 'plugin', 'translation'.
* @param object $item The update offer.
+ *
+ * @return null|WP_Error
*/
public function update( $type, $item ) {
$skin = new Automatic_Upgrader_Skin;
* Kicks off the background update process, looping through all pending updates.
*
* @since 3.7.0
+ *
+ * @global wpdb $wpdb
+ * @global string $wp_version
*/
public function run() {
global $wpdb, $wp_version;
* If we tried to perform a core update, check if we should send an email,
* and if we need to avoid processing future updates.
*
- * @param object $update_result The result of the core update. Includes the update offer and result.
+ * @global string $wp_version
+ *
+ * @param object|WP_Error $update_result The result of the core update. Includes the update offer and result.
*/
protected function after_core_update( $update_result ) {
global $wp_version;
*
* @since 3.7.0
*
+ * @global string $wp_version
+ *
* @param string $type The type of email to send. Can be one of 'success', 'fail', 'manual', 'critical'.
* @param object $core_update The update offer that was attempted.
* @param mixed $result Optional. The result for the core update. Can be WP_Error.