Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion features/core-download.feature
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ Feature: Download WordPress
"""
Failed to find WordPress version
"""
And STDERR should contain:
And STDERR should not contain:
"""
Warning: Checksums not available for WordPress nightly/en_US. Please cleanup files manually.
"""
Expand Down
202 changes: 194 additions & 8 deletions src/Core_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -1108,7 +1108,7 @@
* Updating to version 3.1 (en_US)...
* Downloading update from https://wordpress.org/wordpress-3.1.zip...
* Unpacking the update...
* Warning: Checksums not available for WordPress 3.1/en_US. Please cleanup files manually.
* Cleaning up files...
* Success: WordPress updated successfully.
*
* @alias upgrade
Expand Down Expand Up @@ -1511,15 +1511,13 @@
}

$old_checksums = self::get_core_checksums( $version_from, $locale ?: 'en_US', $insecure );
if ( ! is_array( $old_checksums ) ) {
WP_CLI::warning( "{$old_checksums} Please cleanup files manually." );
return;
}

$new_checksums = self::get_core_checksums( $version_to, $locale ?: 'en_US', $insecure );
if ( ! is_array( $new_checksums ) ) {
WP_CLI::warning( "{$new_checksums} Please cleanup files manually." );

$has_checksums = is_array( $old_checksums ) && is_array( $new_checksums );

if ( ! $has_checksums ) {
// When checksums are not available, use WordPress core's $_old_files list
$this->cleanup_old_files();
return;
}

Expand Down Expand Up @@ -1613,6 +1611,194 @@
WP_CLI::log( 'No files found that need cleaning up.' );
}
}

// Additionally, clean up files from $_old_files that are not in checksums
// These should be deleted unconditionally as they are known old files
$this->cleanup_old_files_not_in_checksums( $old_checksums, $new_checksums );
}

/**
* Clean up old files using WordPress core's $_old_files list.
*
* This method is used when checksums are not available for version comparison.
* It unconditionally deletes files from the $_old_files global array maintained by WordPress core.
*/
private function cleanup_old_files() {
$old_files = $this->get_old_files_list();
if ( empty( $old_files ) ) {
WP_CLI::log( 'No files found that need cleaning up.' );
return;
}

WP_CLI::log( 'Cleaning up files...' );

$count = 0;
foreach ( $old_files as $file ) {
// wp-content should be considered user data
if ( 0 === stripos( $file, 'wp-content' ) ) {
continue;
}

$file_path = ABSPATH . $file;

// Handle both files and directories
if ( file_exists( $file_path ) ) {
if ( is_dir( $file_path ) ) {
// Remove directory recursively
if ( $this->remove_directory( $file_path ) ) {
WP_CLI::log( "Directory removed: {$file}" );
++$count;
} else {
WP_CLI::debug( "Failed to remove directory: {$file}", 'core' );
}
} else {

Check failure on line 1654 in src/Core_Command.php

View workflow job for this annotation

GitHub Actions / code-quality / PHPCS

If control structure block found as the only statement within an "else" block. Use elseif instead.
// Remove file
if ( unlink( $file_path ) ) {
WP_CLI::log( "File removed: {$file}" );
++$count;
} else {
WP_CLI::debug( "Failed to remove file: {$file}", 'core' );
}
}
}
}

if ( $count ) {
WP_CLI::log( number_format( $count ) . ' files cleaned up.' );
} else {
WP_CLI::log( 'No files found that need cleaning up.' );
}
}

/**
* Clean up old files from $_old_files that are not tracked in checksums.
*
* This method is used as a supplement when checksums ARE available.
* It unconditionally deletes files from $_old_files that are not present in either
* the old or new checksums, as these files cannot be verified for modifications.
*
* @param array $old_checksums Old checksums array.
* @param array $new_checksums New checksums array.
*/
private function cleanup_old_files_not_in_checksums( $old_checksums, $new_checksums ) {
$old_files = $this->get_old_files_list();
if ( empty( $old_files ) ) {
return;
}

// Combine all files from both checksum arrays
$all_checksum_files = array_merge( array_keys( $old_checksums ), array_keys( $new_checksums ) );
$all_checksum_files = array_unique( $all_checksum_files );

// Find files in $_old_files that are not in checksums
$files_to_remove = array_diff( $old_files, $all_checksum_files );

if ( empty( $files_to_remove ) ) {
return;
}

$count = 0;
foreach ( $files_to_remove as $file ) {
// wp-content should be considered user data
if ( 0 === stripos( $file, 'wp-content' ) ) {
continue;
}

$file_path = ABSPATH . $file;

// Handle both files and directories
if ( file_exists( $file_path ) ) {
if ( is_dir( $file_path ) ) {
// Remove directory recursively
if ( $this->remove_directory( $file_path ) ) {
WP_CLI::log( "Directory removed: {$file}" );
++$count;
} else {
WP_CLI::debug( "Failed to remove directory: {$file}", 'core' );
}
} else {

Check failure on line 1719 in src/Core_Command.php

View workflow job for this annotation

GitHub Actions / code-quality / PHPCS

If control structure block found as the only statement within an "else" block. Use elseif instead.
// Remove file
if ( unlink( $file_path ) ) {
WP_CLI::log( "File removed: {$file}" );
++$count;
} else {
WP_CLI::debug( "Failed to remove file: {$file}", 'core' );
}
}
}
}

if ( $count ) {
WP_CLI::log( number_format( $count ) . ' additional old files cleaned up.' );
}
}

/**
* Get the list of old files from WordPress core.
*
* @return array Array of old file paths, or empty array if not available.
*/
private function get_old_files_list() {
// Include WordPress core's update file to access the $_old_files list
if ( ! file_exists( ABSPATH . 'wp-admin/includes/update-core.php' ) ) {
WP_CLI::warning( 'Could not find update-core.php. Please cleanup files manually.' );
return array();
}

require_once ABSPATH . 'wp-admin/includes/update-core.php';

global $_old_files;

if ( empty( $_old_files ) || ! is_array( $_old_files ) ) {
return array();
}

return $_old_files;
}

/**
* Recursively remove a directory and its contents.
*
* @param string $dir Directory path to remove.
* @return bool True on success, false on failure.
*/
private function remove_directory( $dir ) {
if ( ! is_dir( $dir ) ) {
return false;
}

$items = scandir( $dir );
if ( false === $items ) {
WP_CLI::debug( "Failed to scan directory: {$dir}", 'core' );
return false;
}

foreach ( $items as $item ) {
if ( '.' === $item || '..' === $item ) {
continue;
}

$path = $dir . '/' . $item;

if ( is_dir( $path ) ) {
if ( ! $this->remove_directory( $path ) ) {
WP_CLI::debug( "Failed to remove subdirectory: {$path}", 'core' );
return false;
}
} else {

Check failure on line 1788 in src/Core_Command.php

View workflow job for this annotation

GitHub Actions / code-quality / PHPCS

If control structure block found as the only statement within an "else" block. Use elseif instead.
if ( ! unlink( $path ) ) {
WP_CLI::debug( "Failed to remove file in directory: {$path}", 'core' );
return false;
}
}
}

if ( ! rmdir( $dir ) ) {
WP_CLI::debug( "Failed to remove directory: {$dir}", 'core' );
return false;
}

return true;
}

private static function strip_content_dir( $zip_file ) {
Expand Down
Loading