<?php
/**
- * A File upgrader class for WordPress.
+ * Upgrade API: WP_Upgrader, Plugin_Upgrader, Theme_Upgrader, Language_Pack_Upgrader,
+ * Core_Upgrader, File_Upload_Upgrader, and WP_Automatic_Updater classes
*
- * This set of classes are designed to be used to upgrade/install a local set of files on the filesystem via the Filesystem Abstraction classes.
- *
- * @link https://core.trac.wordpress.org/ticket/7875 consolidate plugin/theme/core upgrade/install functions
+ * This set of classes are designed to be used to upgrade/install a local set of files
+ * on the filesystem via the Filesystem Abstraction classes.
*
* @package WordPress
* @subpackage Upgrader
require ABSPATH . 'wp-admin/includes/class-wp-upgrader-skins.php';
/**
- * WordPress Upgrader class for Upgrading/Installing a local set of files via the Filesystem Abstraction classes from a Zip file.
+ * Core class used for upgrading/installing a local set of files via
+ * the Filesystem Abstraction classes from a Zip file.
*
- * @package WordPress
- * @subpackage Upgrader
* @since 2.8.0
*/
class WP_Upgrader {
* The error/notification strings used to update the user on the progress.
*
* @since 2.8.0
+ * @access public
* @var string $strings
*/
public $strings = array();
* The upgrader skin being used.
*
* @since 2.8.0
+ * @access public
* @var WP_Upgrader_Skin $skin
*/
public $skin = null;
* it.
*
* @since 2.8.0
+ * @access public
+ *
* @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.
* Set by the bulk update methods.
*
* @since 3.0.0
+ * @access public
* @var int $update_count
*/
public $update_count = 0;
* Used by the bulk update methods, and incremented for each update.
*
* @since 3.0.0
+ * @access public
* @var int
*/
public $update_current = 0;
* Construct the upgrader with a skin.
*
* @since 2.8.0
+ * @access public
*
* @param WP_Upgrader_Skin $skin The upgrader skin to use. Default is a {@see WP_Upgrader_Skin}
* instance.
* and also add the generic strings to `WP_Upgrader::$strings`.
*
* @since 2.8.0
+ * @access public
*/
public function init() {
$this->skin->set_upgrader($this);
* Add the generic strings to WP_Upgrader::$strings.
*
* @since 2.8.0
+ * @access public
*/
public function generic_strings() {
$this->strings['bad_request'] = __('Invalid Data provided.');
$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…');
* Connect to the filesystem.
*
* @since 2.8.0
+ * @access public
+ *
+ * @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.
* Download a package.
*
* @since 2.8.0
+ * @access public
*
* @param string $package The URI of the package. If this is the full path to an
* existing local file, it will be returned untouched.
* Filter whether to return the package.
*
* @since 3.7.0
+ * @access public
*
* @param bool $reply Whether to bail without returning the package.
* Default false.
* Unpack a compressed package file.
*
* @since 2.8.0
+ * @access public
+ *
+ * @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
$wp_filesystem->delete($upgrade_folder . $file['name'], true);
}
- //We need a working directory
- $working_dir = $upgrade_folder . basename($package, '.zip');
+ // 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
if ( $wp_filesystem->is_dir($working_dir) )
return $working_dir;
}
+ /**
+ * Clears the directory where this item is going to be installed into.
+ *
+ * @since 4.3.0
+ * @access public
+ *
+ * @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.
*
* clear out the destination folder if it already exists.
*
* @since 2.8.0
+ * @access public
+ *
+ * @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.
* @param array $hook_extra Extra arguments passed to hooked filters.
*/
$res = apply_filters( 'upgrader_pre_install', true, $args['hook_extra'] );
+
if ( is_wp_error( $res ) ) {
return $res;
}
$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 foldername of this file as the destination folder. foldername is based on zip filename.
+ } 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'] );
}
* Filter the source file location for the upgrade package.
*
* @since 2.8.0
+ * @since 4.4.0 The $hook_extra parameter became available.
*
* @param string $source File source location.
- * @param string $remote_source Remove file source location.
+ * @param string $remote_source Remote file source location.
* @param WP_Upgrader $this WP_Upgrader instance.
+ * @param array $hook_extra Extra arguments passed to hooked filters.
*/
- $source = apply_filters( 'upgrader_source_selection', $source, $remote_source, $this );
+ $source = apply_filters( 'upgrader_source_selection', $source, $remote_source, $this, $args['hook_extra'] );
+
if ( is_wp_error( $source ) ) {
return $source;
}
if ( $source !== $remote_source ) {
$source_files = array_keys( $wp_filesystem->dirlist( $source ) );
}
+
/*
* Protection against deleting files in any important base directories.
* Theme_Upgrader & Plugin_Upgrader also trigger this, as they pass the
if ( is_array( $wp_theme_directories ) ) {
$protected_directories = array_merge( $protected_directories, $wp_theme_directories );
}
+
if ( in_array( $destination, $protected_directories ) ) {
$remote_destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $source ) );
$destination = trailingslashit( $destination ) . trailingslashit( basename( $source ) );
}
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;
- } else if ( ! $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.
$destination_name = '';
}
- $this->result = compact('local_source', 'source', 'source_name', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination', 'delete_source_dir');
+ $this->result = compact( 'source', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination' );
/**
* Filter the install response after the installation has finished.
* install it in the destination folder.
*
* @since 2.8.0
+ * @access public
*
* @param array $options {
* Array or string of arguments for upgrading/installing a package.
* @type array $hook_extra Extra arguments to pass to the filter hooks called by
* {@see WP_Upgrader::run()}.
* }
- *
* @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.
*/
$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();
}
return $res;
}
- //Download the package (Note, This just returns the filename of the file if the package is a local file)
+ /*
+ * 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'] );
if ( is_wp_error($download) ) {
$this->skin->error($download);
$delete_package = ( $download != $options['package'] ); // Do not delete a "local" file
- //Unzips the file into a temporary directory
+ // Unzips the file into a temporary directory.
$working_dir = $this->unpack_package( $download, $delete_package );
if ( is_wp_error($working_dir) ) {
$this->skin->error($working_dir);
return $working_dir;
}
- //With the given options, this installs it to the destination directory.
+ // With the given options, this installs it to the destination directory.
$result = $this->install_package( array(
'source' => $working_dir,
'destination' => $options['destination'],
$this->skin->error($result);
$this->skin->feedback('process_failed');
} else {
- //Install Succeeded
+ // Install succeeded.
$this->skin->feedback('process_success');
}
* Creates/deletes the maintenance file to enable/disable maintenance mode.
*
* @since 2.8.0
+ * @access public
+ *
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
*
* @param bool $enable True to enable maintenance mode, false to disable.
*/
$maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
$wp_filesystem->delete($file);
$wp_filesystem->put_contents($file, $maintenance_string, FS_CHMOD_FILE);
- } else if ( !$enable && $wp_filesystem->exists($file) ) {
+ } elseif ( ! $enable && $wp_filesystem->exists( $file ) ) {
$this->skin->feedback('maintenance_end');
$wp_filesystem->delete($file);
}
}
/**
- * Plugin Upgrader class for WordPress Plugins, It is designed to upgrade/install plugins from a local zip, remote zip URL, or uploaded zip file.
+ * Core class used for upgrading/installing plugins.
+ *
+ * It is designed to upgrade/install plugins from a local zip, remote zip URL,
+ * or uploaded zip file.
*
- * @package WordPress
- * @subpackage Upgrader
* @since 2.8.0
+ *
+ * @see WP_Upgrader
*/
class Plugin_Upgrader extends WP_Upgrader {
* Plugin upgrade result.
*
* @since 2.8.0
+ * @access public
* @var array|WP_Error $result
+ *
* @see WP_Upgrader::$result
*/
public $result;
* Whether a bulk upgrade/install is being performed.
*
* @since 2.9.0
+ * @access public
* @var bool $bulk
*/
public $bulk = false;
* Initialize the upgrade strings.
*
* @since 2.8.0
+ * @access public
*/
public function upgrade_strings() {
$this->strings['up_to_date'] = __('The plugin is at the latest version.');
$this->strings['remove_old_failed'] = __('Could not remove the old plugin.');
$this->strings['process_failed'] = __('Plugin update failed.');
$this->strings['process_success'] = __('Plugin updated successfully.');
+ $this->strings['process_bulk_success'] = __('Plugins updated successfully.');
}
/**
* Initialize the install strings.
*
* @since 2.8.0
+ * @access public
*/
public function install_strings() {
$this->strings['no_package'] = __('Install package not available.');
*
* @since 2.8.0
* @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional.
+ * @access public
*
* @param string $package The full local path or URI of the package.
* @param array $args {
* @type bool $clear_update_cache Whether to clear the plugin updates cache if successful.
* Default true.
* }
- *
* @return bool|WP_Error True if the install was successful, false or a WP_Error otherwise.
*/
public function install( $package, $args = array() ) {
$this->install_strings();
add_filter('upgrader_source_selection', array($this, 'check_package') );
+ // Clear cache so wp_update_plugins() knows about the new plugin.
+ add_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9, 0 );
$this->run( array(
'package' => $package,
)
) );
+ remove_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9 );
remove_filter('upgrader_source_selection', array($this, 'check_package') );
if ( ! $this->result || is_wp_error($this->result) )
*
* @since 2.8.0
* @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional.
+ * @access public
*
* @param string $plugin The basename path to the main plugin file.
* @param array $args {
- * Optional. Other arguments for upgrading a plugin package. Defualt empty array.
+ * Optional. Other arguments for upgrading a plugin package. Default empty array.
*
* @type bool $clear_update_cache Whether to clear the plugin updates cache if successful.
* Default true.
*
* @since 2.8.0
* @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional.
+ * @access public
*
- * @param string $plugins Array of the basename paths of the plugins' main files.
- * @param array $args {
+ * @param array $plugins Array of the basename paths of the plugins' main files.
+ * @param array $args {
* Optional. Other arguments for upgrading several plugins at once. Default empty array.
*
* @type bool $clear_update_cache Whether to clear the plugin updates cache if successful.
* Default true.
* }
- *
* @return array|false An array of results indexed by plugin file, or false if unable to connect to the filesystem.
*/
public function bulk_upgrade( $plugins, $args = array() ) {
$this->skin->bulk_header();
- // Only start maintenance mode if:
- // - running Multisite and there are one or more plugins specified, OR
- // - a plugin with an update available is currently active.
- // @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible.
+ /*
+ * Only start maintenance mode if:
+ * - running Multisite and there are one or more plugins specified, OR
+ * - a plugin with an update available is currently active.
+ * @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible.
+ */
$maintenance = ( is_multisite() && ! empty( $plugins ) );
foreach ( $plugins as $plugin )
$maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin] ) );
continue;
}
- // Get the URL to the zip file
+ // Get the URL to the zip file.
$r = $current->response[ $plugin ];
$this->skin->plugin_active = is_plugin_active($plugin);
// Cleanup our hooks, in case something else does a upgrade on this connection.
remove_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'));
- // Force refresh of plugin update information
+ // Force refresh of plugin update information.
wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
return $results;
* {@see Plugin_Upgrader::install()}.
*
* @since 3.3.0
+ * @access public
+ *
+ * @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.
+ * @return string|WP_Error The source as passed, or a {@see WP_Error} object
+ * if no plugins were found.
*/
public function check_package($source) {
global $wp_filesystem;
// 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;
+ }
}
}
* This isn't used internally in the class, but is called by the skins.
*
* @since 2.8.0
+ * @access public
*
* @return string|false The full path to the main plugin file, or false.
*/
*
* @since 2.8.0
* @since 4.1.0 Added a return value.
+ * @access public
*
* @param bool|WP_Error $return Upgrade offer return.
* @param array $plugin Plugin package arguments.
* {@see Plugin_Upgrader::upgrade()} and {@see Plugin_Upgrader::bulk_upgrade()}.
*
* @since 2.8.0
+ * @access public
+ *
+ * @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;
}
/**
- * Theme Upgrader class for WordPress Themes, It is designed to upgrade/install themes from a local zip, remote zip URL, or uploaded zip file.
+ * Core class used for upgrading/installing themes.
+ *
+ * It is designed to upgrade/install themes from a local zip, remote zip URL,
+ * or uploaded zip file.
*
- * @package WordPress
- * @subpackage Upgrader
* @since 2.8.0
+ *
+ * @see WP_Upgrader
*/
class Theme_Upgrader extends WP_Upgrader {
* Result of the theme upgrade offer.
*
* @since 2.8.0
- * @var array|WP_Erorr $result
+ * @access public
+ * @var array|WP_Error $result
* @see WP_Upgrader::$result
*/
public $result;
/**
- * Whether multiple plugins are being upgraded/installed in bulk.
+ * Whether multiple themes are being upgraded/installed in bulk.
*
* @since 2.9.0
+ * @access public
* @var bool $bulk
*/
public $bulk = false;
* Initialize the upgrade strings.
*
* @since 2.8.0
+ * @access public
*/
public function upgrade_strings() {
$this->strings['up_to_date'] = __('The theme is at the latest version.');
* Initialize the install strings.
*
* @since 2.8.0
+ * @access public
*/
public function install_strings() {
$this->strings['no_package'] = __('Install package not available.');
* Hooked to the {@see 'upgrader_post_install'} filter by {@see Theme_Upgrader::install()}.
*
* @since 3.4.0
+ * @access public
+ *
+ * @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
* a child theme and installing the parent theme fails.
*
* @since 3.4.0
+ * @access public
*
* @param array $actions Preview actions.
+ * @return array
*/
public function hide_activate_preview_actions( $actions ) {
unset($actions['activate'], $actions['preview']);
*
* @since 2.8.0
* @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
+ * @access public
*
* @param string $package The full local path or URI of the package.
* @param array $args {
add_filter('upgrader_source_selection', array($this, 'check_package') );
add_filter('upgrader_post_install', array($this, 'check_parent_theme_filter'), 10, 3);
+ // Clear cache so wp_update_themes() knows about the new theme.
+ add_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9, 0 );
$this->run( array(
'package' => $package,
),
) );
+ remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 );
remove_filter('upgrader_source_selection', array($this, 'check_package') );
remove_filter('upgrader_post_install', array($this, 'check_parent_theme_filter'));
*
* @since 2.8.0
* @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
+ * @access public
*
* @param string $theme The theme slug.
* @param array $args {
*
* @since 3.0.0
* @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
+ * @access public
*
- * @param string $themes The theme slugs.
- * @param array $args {
+ * @param array $themes The theme slugs.
+ * @param array $args {
* Optional. Other arguments for upgrading several themes at once. Default empty array.
*
* @type bool $clear_update_cache Whether to clear the update cache if successful.
* files.
*
* @since 3.3.0
+ * @access public
+ *
+ * @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.
return $source;
// A proper archive should have a style.css file in the single subdirectory
- if ( ! file_exists( $working_directory . 'style.css' ) )
- return new WP_Error( 'incompatible_archive_theme_no_style', $this->strings['incompatible_archive'], __( 'The theme is missing the <code>style.css</code> stylesheet.' ) );
+ if ( ! file_exists( $working_directory . 'style.css' ) ) {
+ return new WP_Error( 'incompatible_archive_theme_no_style', $this->strings['incompatible_archive'],
+ /* translators: %s: style.css */
+ sprintf( __( 'The theme is missing the %s stylesheet.' ),
+ '<code>style.css</code>'
+ )
+ );
+ }
$info = get_file_data( $working_directory . 'style.css', array( 'Name' => 'Theme Name', 'Template' => 'Template' ) );
- if ( empty( $info['Name'] ) )
- return new WP_Error( 'incompatible_archive_theme_no_name', $this->strings['incompatible_archive'], __( "The <code>style.css</code> stylesheet doesn't contain a valid theme header." ) );
+ if ( empty( $info['Name'] ) ) {
+ return new WP_Error( 'incompatible_archive_theme_no_name', $this->strings['incompatible_archive'],
+ /* translators: %s: style.css */
+ sprintf( __( 'The %s stylesheet doesn’t contain a valid theme header.' ),
+ '<code>style.css</code>'
+ )
+ );
+ }
// If it's not a child theme, it must have at least an index.php to be legit.
- if ( empty( $info['Template'] ) && ! file_exists( $working_directory . 'index.php' ) )
- return new WP_Error( 'incompatible_archive_theme_no_index', $this->strings['incompatible_archive'], __( 'The theme is missing the <code>index.php</code> file.' ) );
+ if ( empty( $info['Template'] ) && ! file_exists( $working_directory . 'index.php' ) ) {
+ return new WP_Error( 'incompatible_archive_theme_no_index', $this->strings['incompatible_archive'],
+ /* translators: %s: index.php */
+ sprintf( __( 'The theme is missing the %s file.' ),
+ '<code>index.php</code>'
+ )
+ );
+ }
return $source;
}
* {@see Theme_Upgrader::bulk_upgrade()}.
*
* @since 2.8.0
+ * @access public
+ *
+ * @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
+ * @access public
+ *
+ * @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
+ * @access public
+ *
+ * @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;
*
* @since 2.8.0
* @since 3.0.0 The `$theme` argument was added.
+ * @access public
*
* @param string $theme The directory name of the theme. This is optional, and if not supplied,
* the directory name from the last result will be used.
}
-add_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
-
/**
- * Language pack upgrader, for updating translations of plugins, themes, and core.
+ * Core class used for updating/installing language packs (translations)
+ * for plugins, themes, and core.
*
- * @package WordPress
- * @subpackage Upgrader
* @since 3.7.0
+ *
+ * @see WP_Upgrader
*/
class Language_Pack_Upgrader extends WP_Upgrader {
* Result of the language pack upgrade.
*
* @since 3.7.0
+ * @access public
* @var array|WP_Error $result
* @see WP_Upgrader::$result
*/
* Whether a bulk upgrade/install is being performed.
*
* @since 3.7.0
+ * @access public
* @var bool $bulk
*/
public $bulk = true;
/**
- * Asynchronously upgrade language packs after other upgrades have been made.
+ * Asynchronously upgrades language packs after other upgrades have been made.
*
* Hooked to the {@see 'upgrader_process_complete'} action by default.
*
* @since 3.7.0
+ * @access public
+ * @static
+ *
+ * @param false|WP_Upgrader $upgrader Optional. WP_Upgrader instance or false. If `$upgrader` is
+ * a Language_Pack_Upgrader instance, the method will bail to
+ * avoid recursion. Otherwise unused. Default false.
*/
public static function async_upgrade( $upgrader = false ) {
// Avoid recursion.
return;
}
- // Avoid messing with VCS installs, at least for now.
- // Noted: this is not the ideal way to accomplish this.
+ /*
+ * Avoid messing with VCS installs, at least for now.
+ * Noted: this is not the ideal way to accomplish this.
+ */
$check_vcs = new WP_Automatic_Updater;
if ( $check_vcs->is_vcs_checkout( WP_CONTENT_DIR ) ) {
return;
return;
}
- $skin = new Language_Pack_Upgrader_Skin( array(
- 'skip_header_footer' => true,
- ) );
+ // Re-use the automatic upgrader skin if the parent upgrader is using it.
+ if ( $upgrader && $upgrader->skin instanceof Automatic_Upgrader_Skin ) {
+ $skin = $upgrader->skin;
+ } else {
+ $skin = new Language_Pack_Upgrader_Skin( array(
+ 'skip_header_footer' => true,
+ ) );
+ }
$lp_upgrader = new Language_Pack_Upgrader( $skin );
$lp_upgrader->bulk_upgrade( $language_updates );
* Initialize the upgrade strings.
*
* @since 3.7.0
+ * @access public
*/
public function upgrade_strings() {
$this->strings['starting_upgrade'] = __( 'Some of your translations need updating. Sit tight for a few more seconds while we update them as well.' );
* Upgrade a language pack.
*
* @since 3.7.0
+ * @access public
*
* @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 ) {
* Bulk upgrade language packs.
*
* @since 3.7.0
+ * @access public
+ *
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
*
* @param array $language_updates Optional. Language pack updates. Default empty array.
* @param array $args {
* @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
+ * @access public
+ *
+ * @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;
$mo = true;
}
- if ( ! $mo || ! $po )
+ if ( ! $mo || ! $po ) {
return new WP_Error( 'incompatible_archive_pomo', $this->strings['incompatible_archive'],
- __( 'The language pack is missing either the <code>.po</code> or <code>.mo</code> files.' ) );
+ /* translators: 1: .po 2: .mo */
+ sprintf( __( 'The language pack is missing either the %1$s or %2$s files.' ),
+ '<code>.po</code>',
+ '<code>.mo</code>'
+ )
+ );
+ }
return $source;
}
* Get the name of an item being updated.
*
* @since 3.7.0
+ * @access public
*
- * @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 ) {
switch ( $update->type ) {
case 'core':
return 'WordPress'; // Not translated
- break;
+
case 'theme':
$theme = wp_get_theme( $update->slug );
if ( $theme->exists() )
break;
case 'plugin':
$plugin_data = get_plugins( '/' . $update->slug );
- $plugin_data = array_shift( $plugin_data );
+ $plugin_data = reset( $plugin_data );
if ( $plugin_data )
return $plugin_data['Name'];
break;
}
/**
- * Core Upgrader class for WordPress. It allows for WordPress to upgrade itself in combination with the wp-admin/includes/update-core.php file
+ * Core class used for updating core.
+ *
+ * It allows for WordPress to upgrade itself in combination with
+ * the wp-admin/includes/update-core.php file.
*
- * @package WordPress
- * @subpackage Upgrader
* @since 2.8.0
+ *
+ * @see WP_Upgrader
*/
class Core_Upgrader extends WP_Upgrader {
* Initialize the upgrade strings.
*
* @since 2.8.0
+ * @access public
*/
public function upgrade_strings() {
$this->strings['up_to_date'] = __('WordPress is at the latest version.');
* Upgrade WordPress core.
*
* @since 2.8.0
+ * @access public
+ *
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
+ * @global callable $_wp_filesystem_direct_method
*
* @param object $current Response object for whether WordPress is current.
* @param array $args {
* Determines if this WordPress Core version should update to an offered version or not.
*
* @since 3.7.0
+ * @access public
+ *
+ * @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.
}
/**
- * Compare the disk file checksums agains the expected checksums.
+ * Compare the disk file checksums against the expected checksums.
*
* @since 3.7.0
+ * @access public
+ *
+ * @global string $wp_version
+ * @global string $wp_local_package
*
* @return bool True if the checksums match, otherwise false.
*/
}
/**
- * Upgrade Skin helper for File uploads. This class handles the upload process and passes it as if it's a local file to the Upgrade/Installer functions.
+ * Core class used for handling file uploads.
+ *
+ * This class handles the upload process and passes it as if it's a local file
+ * to the Upgrade/Installer functions.
*
- * @package WordPress
- * @subpackage Upgrader
* @since 2.8.0
*/
class File_Upload_Upgrader {
* The full path to the file package.
*
* @since 2.8.0
+ * @access public
* @var string $package
*/
public $package;
* The name of the file.
*
* @since 2.8.0
+ * @access public
* @var string $filename
*/
public $filename;
* The ID of the attachment post for this file.
*
* @since 3.3.0
+ * @access public
* @var int $id
*/
public $id = 0;
* Construct the upgrader for a form.
*
* @since 2.8.0
+ * @access public
*
* @param string $form The name of the form the file was uploaded from.
* @param string $urlholder The name of the `GET` parameter that holds the filename.
* Delete the attachment/uploaded file.
*
* @since 3.2.2
+ * @access public
*
* @return bool Whether the cleanup was successful.
*/
}
/**
- * The WordPress automatic background updater.
+ * Core class used for handling automatic background updates.
*
- * @package WordPress
- * @subpackage Upgrader
* @since 3.7.0
*/
class WP_Automatic_Updater {
* Tracks update results during processing.
*
* @var array
+ * @access protected
*/
protected $update_results = array();
* Whether the entire automatic updater is disabled.
*
* @since 3.7.0
+ * @access public
*/
public function is_disabled() {
// Background updates are disabled if you don't want file changes.
if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS )
return true;
- if ( defined( 'WP_INSTALLING' ) )
+ if ( wp_installing() )
return true;
// More fine grained control can be done through the WP_AUTO_UPDATE_CORE constant and filters.
* how things get updated.
*
* @since 3.7.0
+ * @access public
*
* @param string $context The filesystem path to check, in addition to ABSPATH.
*/
* Tests to see if we can and should update a specific item.
*
* @since 3.7.0
+ * @access public
+ *
+ * @global wpdb $wpdb WordPress database abstraction object.
*
* @param string $type The type of update being checked: 'core', 'theme',
* 'plugin', 'translation'.
* Notifies an administrator of a core update.
*
* @since 3.7.0
+ * @access protected
*
* @param object $item The update offer.
*/
* Update an item, if appropriate.
*
* @since 3.7.0
+ * @access public
*
* @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;
if ( ! $this->should_update( $type, $item, $context ) )
return false;
+ /**
+ * Fires immediately prior to an auto-update.
+ *
+ * @since 4.4.0
+ *
+ * @param string $type The type of update being checked: 'core', 'theme', 'plugin', or 'translation'.
+ * @param object $item The update offer.
+ * @param string $context The filesystem context (a path) against which filesystem access and status
+ * should be checked.
+ */
+ do_action( 'pre_auto_update', $type, $item, $context );
+
$upgrader_item = $item;
switch ( $type ) {
case 'core':
* Kicks off the background update process, looping through all pending updates.
*
* @since 3.7.0
+ * @access public
+ *
+ * @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.
+ * @since Unknown
+ * @access protected
+ *
+ * @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;
* Sends an email upon the completion or failure of a background core update.
*
* @since 3.7.0
+ * @access protected
+ *
+ * @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.
* Prepares and sends an email of a full log of background update results, useful for debugging and geekery.
*
* @since 3.7.0
+ * @access protected
*/
protected function send_debug_email() {
$update_count = 0;
$site_title = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
if ( $failures ) {
- $body[] = trim( __( "
-BETA TESTING?
+ $body[] = trim( __(
+"BETA TESTING?
=============
This debugging email is sent when you are using a development version of WordPress.
$subject = sprintf( __( '[%s] Background updates have finished' ), $site_title );
}
- $body[] = trim( __( '
-UPDATE LOG
+ $body[] = trim( __(
+'UPDATE LOG
==========' ) );
$body[] = '';