rebase on oct-10-2023

This commit is contained in:
Rachit Bhargava
2023-10-10 17:23:21 -04:00
parent d37566ffb6
commit d096058d7d
4789 changed files with 254611 additions and 307223 deletions

View File

@@ -112,6 +112,26 @@ class WP_Upgrader {
*/
public $update_current = 0;
/**
* Stores the list of plugins or themes added to temporary backup directory.
*
* Used by the rollback functions.
*
* @since 6.3.0
* @var array
*/
private $temp_backups = array();
/**
* Stores the list of plugins or themes to be restored from temporary backup directory.
*
* Used by the rollback functions.
*
* @since 6.3.0
* @var array
*/
private $temp_restores = array();
/**
* Construct the upgrader with a skin.
*
@@ -129,20 +149,38 @@ class WP_Upgrader {
}
/**
* Initialize the upgrader.
* Initializes the upgrader.
*
* This will set the relationship between the skin being used and this upgrader,
* and also add the generic strings to `WP_Upgrader::$strings`.
*
* Additionally, it will schedule a weekly task to clean up the temporary backup directory.
*
* @since 2.8.0
* @since 6.3.0 Added the `schedule_temp_backup_cleanup()` task.
*/
public function init() {
$this->skin->set_upgrader( $this );
$this->generic_strings();
if ( ! wp_installing() ) {
$this->schedule_temp_backup_cleanup();
}
}
/**
* Add the generic strings to WP_Upgrader::$strings.
* Schedules the cleanup of the temporary backup directory.
*
* @since 6.3.0
*/
protected function schedule_temp_backup_cleanup() {
if ( false === wp_next_scheduled( 'wp_delete_temp_updater_backups' ) ) {
wp_schedule_event( time(), 'weekly', 'wp_delete_temp_updater_backups' );
}
}
/**
* Adds the generic strings to WP_Upgrader::$strings.
*
* @since 2.8.0
*/
@@ -151,7 +189,7 @@ class WP_Upgrader {
$this->strings['fs_unavailable'] = __( 'Could not access filesystem.' );
$this->strings['fs_error'] = __( 'Filesystem error.' );
$this->strings['fs_no_root_dir'] = __( 'Unable to locate WordPress root directory.' );
$this->strings['fs_no_content_dir'] = __( 'Unable to locate WordPress content directory (wp-content).' );
$this->strings['fs_no_content_dir'] = sprintf( __( 'Unable to locate WordPress content directory (%s).' ), '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. */
@@ -167,10 +205,19 @@ class WP_Upgrader {
$this->strings['maintenance_start'] = __( 'Enabling Maintenance mode…' );
$this->strings['maintenance_end'] = __( 'Disabling Maintenance mode…' );
/* translators: %s: upgrade-temp-backup */
$this->strings['temp_backup_mkdir_failed'] = sprintf( __( 'Could not create the %s directory.' ), 'upgrade-temp-backup' );
/* translators: %s: upgrade-temp-backup */
$this->strings['temp_backup_move_failed'] = sprintf( __( 'Could not move the old version to the %s directory.' ), 'upgrade-temp-backup' );
/* translators: %s: The plugin or theme slug. */
$this->strings['temp_backup_restore_failed'] = __( 'Could not restore the original version of %s.' );
/* translators: %s: The plugin or theme slug. */
$this->strings['temp_backup_delete_failed'] = __( 'Could not delete the temporary backup directory for %s.' );
}
/**
* Connect to the filesystem.
* Connects to the filesystem.
*
* @since 2.8.0
*
@@ -242,7 +289,7 @@ class WP_Upgrader {
}
/**
* Download a package.
* Downloads a package.
*
* @since 2.8.0
* @since 5.2.0 Added the `$check_signatures` parameter.
@@ -292,7 +339,7 @@ class WP_Upgrader {
}
/**
* Unpack a compressed package file.
* Unpacks a compressed package file.
*
* @since 2.8.0
*
@@ -308,6 +355,10 @@ class WP_Upgrader {
$this->skin->feedback( 'unpack_package' );
if ( ! $wp_filesystem->wp_content_dir() ) {
return new WP_Error( 'fs_no_content_dir', $this->strings['fs_no_content_dir'] );
}
$upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
// Clean up contents of upgrade directory beforehand.
@@ -346,7 +397,7 @@ class WP_Upgrader {
}
/**
* Flatten the results of WP_Filesystem_Base::dirlist() for iterating over.
* Flattens the results of WP_Filesystem_Base::dirlist() for iterating over.
*
* @since 4.9.0
* @access protected
@@ -512,8 +563,10 @@ class WP_Upgrader {
// 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.
/*
* 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'] );
}
@@ -534,6 +587,16 @@ class WP_Upgrader {
return $source;
}
if ( ! empty( $args['hook_extra']['temp_backup'] ) ) {
$temp_backup = $this->move_to_temp_backup_dir( $args['hook_extra']['temp_backup'] );
if ( is_wp_error( $temp_backup ) ) {
return $temp_backup;
}
$this->temp_backups[] = $args['hook_extra']['temp_backup'];
}
// Has the source location changed? If so, we need a new source_files list.
if ( $source !== $remote_source ) {
$source_files = array_keys( $wp_filesystem->dirlist( $source ) );
@@ -580,8 +643,10 @@ class WP_Upgrader {
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.
@@ -614,7 +679,7 @@ class WP_Upgrader {
$result = copy_dir( $source, $remote_destination );
}
// Clear the working folder?
// Clear the working directory?
if ( $args['clear_working'] ) {
$wp_filesystem->delete( $remote_source, true );
}
@@ -651,7 +716,7 @@ class WP_Upgrader {
}
/**
* Run an upgrade/installation.
* Runs an upgrade/installation.
*
* Attempts to download the package (if it is not a local file), unpack it, and
* install it in the destination folder.
@@ -760,8 +825,10 @@ class WP_Upgrader {
*/
$download = $this->download_package( $options['package'], true, $options['hook_extra'] );
// Allow for signature soft-fail.
// WARNING: This may be removed in the future.
/*
* 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.
@@ -827,7 +894,19 @@ class WP_Upgrader {
$result = apply_filters( 'upgrader_install_package_result', $result, $options['hook_extra'] );
$this->skin->set_result( $result );
if ( is_wp_error( $result ) ) {
if ( ! empty( $options['hook_extra']['temp_backup'] ) ) {
$this->temp_restores[] = $options['hook_extra']['temp_backup'];
/*
* Restore the backup on shutdown.
* Actions running on `shutdown` are immune to PHP timeouts,
* so in case the failure was due to a PHP timeout,
* it will still be able to properly restore the previous version.
*/
add_action( 'shutdown', array( $this, 'restore_temp_backup' ) );
}
$this->skin->error( $result );
if ( ! method_exists( $this->skin, 'hide_process_failed' ) || ! $this->skin->hide_process_failed( $result ) ) {
@@ -840,6 +919,12 @@ class WP_Upgrader {
$this->skin->after();
// Clean up the backup kept in the temporary backup directory.
if ( ! empty( $options['hook_extra']['temp_backup'] ) ) {
// Delete the backup on `shutdown` to avoid a PHP timeout.
add_action( 'shutdown', array( $this, 'delete_temp_backup' ), 100, 0 );
}
if ( ! $options['is_multi'] ) {
/**
@@ -881,7 +966,7 @@ class WP_Upgrader {
}
/**
* Toggle maintenance mode for the site.
* Toggles maintenance mode for the site.
*
* Creates/deletes the maintenance file to enable/disable maintenance mode.
*
@@ -966,6 +1051,170 @@ class WP_Upgrader {
public static function release_lock( $lock_name ) {
return delete_option( $lock_name . '.lock' );
}
/**
* Moves the plugin or theme being updated into a temporary backup directory.
*
* @since 6.3.0
*
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
*
* @param string[] $args {
* Array of data for the temporary backup.
*
* @type string $slug Plugin or theme slug.
* @type string $src Path to the root directory for plugins or themes.
* @type string $dir Destination subdirectory name. Accepts 'plugins' or 'themes'.
* }
*
* @return bool|WP_Error True on success, false on early exit, otherwise WP_Error.
*/
public function move_to_temp_backup_dir( $args ) {
global $wp_filesystem;
if ( empty( $args['slug'] ) || empty( $args['src'] ) || empty( $args['dir'] ) ) {
return false;
}
/*
* Skip any plugin that has "." as its slug.
* A slug of "." will result in a `$src` value ending in a period.
*
* On Windows, this will cause the 'plugins' folder to be moved,
* and will cause a failure when attempting to call `mkdir()`.
*/
if ( '.' === $args['slug'] ) {
return false;
}
if ( ! $wp_filesystem->wp_content_dir() ) {
return new WP_Error( 'fs_no_content_dir', $this->strings['fs_no_content_dir'] );
}
$dest_dir = $wp_filesystem->wp_content_dir() . 'upgrade-temp-backup/';
$sub_dir = $dest_dir . $args['dir'] . '/';
// Create the temporary backup directory if it does not exist.
if ( ! $wp_filesystem->is_dir( $sub_dir ) ) {
if ( ! $wp_filesystem->is_dir( $dest_dir ) ) {
$wp_filesystem->mkdir( $dest_dir, FS_CHMOD_DIR );
}
if ( ! $wp_filesystem->mkdir( $sub_dir, FS_CHMOD_DIR ) ) {
// Could not create the backup directory.
return new WP_Error( 'fs_temp_backup_mkdir', $this->strings['temp_backup_mkdir_failed'] );
}
}
$src_dir = $wp_filesystem->find_folder( $args['src'] );
$src = trailingslashit( $src_dir ) . $args['slug'];
$dest = $dest_dir . trailingslashit( $args['dir'] ) . $args['slug'];
// Delete the temporary backup directory if it already exists.
if ( $wp_filesystem->is_dir( $dest ) ) {
$wp_filesystem->delete( $dest, true );
}
// Move to the temporary backup directory.
$result = move_dir( $src, $dest, true );
if ( is_wp_error( $result ) ) {
return new WP_Error( 'fs_temp_backup_move', $this->strings['temp_backup_move_failed'] );
}
return true;
}
/**
* Restores the plugin or theme from temporary backup.
*
* @since 6.3.0
*
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
*
* @return bool|WP_Error True on success, false on early exit, otherwise WP_Error.
*/
public function restore_temp_backup() {
global $wp_filesystem;
$errors = new WP_Error();
foreach ( $this->temp_restores as $args ) {
if ( empty( $args['slug'] ) || empty( $args['src'] ) || empty( $args['dir'] ) ) {
return false;
}
if ( ! $wp_filesystem->wp_content_dir() ) {
$errors->add( 'fs_no_content_dir', $this->strings['fs_no_content_dir'] );
return $errors;
}
$src = $wp_filesystem->wp_content_dir() . 'upgrade-temp-backup/' . $args['dir'] . '/' . $args['slug'];
$dest_dir = $wp_filesystem->find_folder( $args['src'] );
$dest = trailingslashit( $dest_dir ) . $args['slug'];
if ( $wp_filesystem->is_dir( $src ) ) {
// Cleanup.
if ( $wp_filesystem->is_dir( $dest ) && ! $wp_filesystem->delete( $dest, true ) ) {
$errors->add(
'fs_temp_backup_delete',
sprintf( $this->strings['temp_backup_restore_failed'], $args['slug'] )
);
continue;
}
// Move it.
$result = move_dir( $src, $dest, true );
if ( is_wp_error( $result ) ) {
$errors->add(
'fs_temp_backup_delete',
sprintf( $this->strings['temp_backup_restore_failed'], $args['slug'] )
);
continue;
}
}
}
return $errors->has_errors() ? $errors : true;
}
/**
* Deletes a temporary backup.
*
* @since 6.3.0
*
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
*
* @return bool|WP_Error True on success, false on early exit, otherwise WP_Error.
*/
public function delete_temp_backup() {
global $wp_filesystem;
$errors = new WP_Error();
foreach ( $this->temp_backups as $args ) {
if ( empty( $args['slug'] ) || empty( $args['dir'] ) ) {
return false;
}
if ( ! $wp_filesystem->wp_content_dir() ) {
$errors->add( 'fs_no_content_dir', $this->strings['fs_no_content_dir'] );
return $errors;
}
$temp_backup_dir = $wp_filesystem->wp_content_dir() . "upgrade-temp-backup/{$args['dir']}/{$args['slug']}";
if ( ! $wp_filesystem->delete( $temp_backup_dir, true ) ) {
$errors->add(
'temp_backup_delete_failed',
sprintf( $this->strings['temp_backup_delete_failed'] ),
$args['slug']
);
continue;
}
}
return $errors->has_errors() ? $errors : true;
}
}
/** Plugin_Upgrader class */