Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
18 changes: 18 additions & 0 deletions features/plugin-update.feature
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,21 @@ Feature: Update WordPress plugins
"""
Success: Updated 2 of 2 plugins.
"""

@require-wp-5.2
Scenario: Show changed files when updating plugins
Given a WP install

When I run `wp plugin install wordpress-importer --version=0.5 --force`
Then STDOUT should not be empty

When I run `wp plugin update wordpress-importer --show-changed-files`
Then STDOUT should contain:
"""
Changed files:
"""
And STDOUT should contain:
"""
wordpress-importer
"""

18 changes: 18 additions & 0 deletions features/theme-update.feature
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,21 @@ Feature: Update WordPress themes
"""
Success: Updated 2 of 2 themes.
"""

Scenario: Show changed files when updating themes
Given a WP install
And I run `wp theme delete --all --force`

When I run `wp theme install twentytwelve --version=3.0`
Then STDOUT should not be empty

When I run `wp theme update twentytwelve --show-changed-files`
Then STDOUT should contain:
"""
Changed files:
"""
And STDOUT should contain:
"""
twentytwelve
"""

2 changes: 1 addition & 1 deletion phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
<rule ref="WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedNamespaceFound">
<exclude-pattern>*/src/WP_CLI/Fetchers/(Plugin|Theme)\.php$</exclude-pattern>
<exclude-pattern>*/src/WP_CLI/CommandWithUpgrade\.php$</exclude-pattern>
<exclude-pattern>*/src/WP_CLI/(CommandWith|DestructivePlugin|DestructiveTheme)Upgrader\.php$</exclude-pattern>
<exclude-pattern>*/src/WP_CLI/(CommandWith|DestructivePlugin|DestructiveTheme|Plugin|Theme)Upgrader\.php$</exclude-pattern>
<exclude-pattern>*/src/WP_CLI/Parse(Plugin|Theme)NameInput\.php$</exclude-pattern>
<exclude-pattern>*/src/WP_CLI/ExtensionUpgraderSkin\.php$</exclude-pattern>
</rule>
Expand Down
15 changes: 14 additions & 1 deletion src/Plugin_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public function __construct() {
}

protected function get_upgrader_class( $force ) {
return $force ? '\\WP_CLI\\DestructivePluginUpgrader' : 'Plugin_Upgrader';
return $force ? '\\WP_CLI\\DestructivePluginUpgrader' : '\\WP_CLI\\PluginUpgrader';
}

/**
Expand Down Expand Up @@ -707,6 +707,10 @@ protected function install_from_repo( $slug, $assoc_args ) {
* [--insecure]
* : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack.
*
* [--show-changed-files]
* : Show the list of files that were changed during the update.
* Useful for invalidating PHP-FPM opcache using external tools.
*
* ## EXAMPLES
*
* $ wp plugin update bbpress --version=dev
Expand Down Expand Up @@ -753,6 +757,15 @@ protected function install_from_repo( $slug, $assoc_args ) {
* | nginx-cache-controller | 3.1.1 | 3.2.0 | Updated |
* +------------------------+-------------+-------------+---------+
*
* # Show changed files for opcache invalidation
* $ wp plugin update akismet --show-changed-files
* Success: Updated 1 of 1 plugins.
*
* Changed files:
* /var/www/html/wp-content/plugins/akismet/akismet.php
* /var/www/html/wp-content/plugins/akismet/class.akismet.php
* ...
*
* @alias upgrade
*/
public function update( $args, $assoc_args ) {
Expand Down
15 changes: 14 additions & 1 deletion src/Theme_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public function __construct() {
}

protected function get_upgrader_class( $force ) {
return $force ? '\\WP_CLI\\DestructiveThemeUpgrader' : 'Theme_Upgrader';
return $force ? '\\WP_CLI\\DestructiveThemeUpgrader' : '\\WP_CLI\\ThemeUpgrader';
}

/**
Expand Down Expand Up @@ -691,6 +691,10 @@ public function get( $args, $assoc_args ) {
* [--insecure]
* : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack.
*
* [--show-changed-files]
* : Show the list of files that were changed during the update.
* Useful for invalidating PHP-FPM opcache using external tools.
*
* ## EXAMPLES
*
* # Update multiple themes
Expand Down Expand Up @@ -736,6 +740,15 @@ public function get( $args, $assoc_args ) {
* # Update all themes
* $ wp theme update --all
*
* # Show changed files for opcache invalidation
* $ wp theme update twentytwelve --show-changed-files
* Success: Updated 1 of 1 themes.
*
* Changed files:
* /var/www/html/wp-content/themes/twentytwelve/functions.php
* /var/www/html/wp-content/themes/twentytwelve/footer.php
* ...
*
* @alias upgrade
*/
public function update( $args, $assoc_args ) {
Expand Down
16 changes: 16 additions & 0 deletions src/WP_CLI/CommandWithUpgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,10 @@
foreach ( $items_to_update as $item ) {
$cache_manager->whitelist_package( $item['update_package'], $this->item_type, $item['name'], $item['update_version'] );
}

/**
* @var ThemeUpgrader|PluginUpgrader $upgrader
*/
$upgrader = $this->get_upgrader( $assoc_args );
// Ensure the upgrader uses the download offer present in each item.
$transient_filter = function ( $transient ) use ( $items_to_update ) {
Expand Down Expand Up @@ -559,7 +563,7 @@
$num_to_update = count( $items_to_update );
$num_updated = count(
array_filter(
$result,

Check failure on line 566 in src/WP_CLI/CommandWithUpgrade.php

View workflow job for this annotation

GitHub Actions / code-quality / PHPStan

Parameter #1 $array of function array_filter expects array, array|false given.
static function ( $result ) {
return $result && ! is_wp_error( $result );
}
Expand All @@ -569,7 +573,7 @@
if ( $num_to_update > 0 ) {
if ( ! empty( $assoc_args['format'] ) && 'summary' === $assoc_args['format'] ) {
foreach ( $items_to_update as $item_to_update => $info ) {
$message = null !== $result[ $info['update_id'] ] ? 'updated successfully' : 'did not update';

Check failure on line 576 in src/WP_CLI/CommandWithUpgrade.php

View workflow job for this annotation

GitHub Actions / code-quality / PHPStan

Cannot access offset mixed on array|false.
WP_CLI::log( "{$info['title']} {$message} from version {$info['version']} to version {$info['update_version']}" );
}
} else {
Expand All @@ -579,7 +583,7 @@
'name' => $info['name'],
'old_version' => $info['version'],
'new_version' => $info['update_version'],
'status' => ( null !== $result[ $info['update_id'] ] && ! is_wp_error( $result[ $info['update_id'] ] ) ) ? 'Updated' : 'Error',

Check failure on line 586 in src/WP_CLI/CommandWithUpgrade.php

View workflow job for this annotation

GitHub Actions / code-quality / PHPStan

Cannot access offset mixed on array|false.
];
if ( null === $result[ $info['update_id'] ] || is_wp_error( $result[ $info['update_id'] ] ) ) {
++$errors;
Expand All @@ -604,6 +608,18 @@
if ( null !== $exclude ) {
WP_CLI::log( "Skipped updates for: $exclude" );
}

// Output changed files if requested.
if ( Utils\get_flag_value( $assoc_args, 'show-changed-files' ) ) {
$changed_files = $upgrader->get_changed_files();

Check failure on line 614 in src/WP_CLI/CommandWithUpgrade.php

View workflow job for this annotation

GitHub Actions / code-quality / PHPStan

Variable $upgrader might not be defined.
if ( ! empty( $changed_files ) ) {
WP_CLI::log( '' );
WP_CLI::log( 'Changed files:' );
foreach ( $changed_files as $file ) {
WP_CLI::log( $file );
}
}
}
}

// phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore -- Whitelisting to provide backward compatibility to classes possibly extending this class.
Expand Down
2 changes: 1 addition & 1 deletion src/WP_CLI/DestructiveThemeUpgrader.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/**
* A theme upgrader class that clears the destination directory.
*/
class DestructiveThemeUpgrader extends \Theme_Upgrader {
class DestructiveThemeUpgrader extends ThemeUpgrader {

public function install_package( $args = array() ) {
parent::upgrade_strings(); // Needed for the 'remove_old' string.
Expand Down
45 changes: 45 additions & 0 deletions src/WP_CLI/PluginUpgrader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace WP_CLI;

/**
* A plugin upgrader class that tracks changed files.
*/
class PluginUpgrader extends \Plugin_Upgrader {
/**
* List of files that were changed during the update process.
*
* @var array<string>
*/
private $changed_files = [];

public function install_package( $args = array() ) {
parent::upgrade_strings(); // Needed for the 'remove_old' string.

$track_files = function ( $will_invalidate, $filepath ) {
$this->changed_files[] = $filepath;
return $will_invalidate;
};

add_filter( 'wp_opcache_invalidate_file', $track_files, 10, 2 );

$result = parent::install_package( $args );

remove_filter( 'wp_opcache_invalidate_file', $track_files );

// Remove duplicates and sort files.
$this->changed_files = array_unique( $this->changed_files );
sort( $this->changed_files );

return $result;
}

/**
* Returns a list of files that were changed during the update process.
*
* @return array<string> Changed files.
*/
public function get_changed_files() {
return $this->changed_files;
}
}
45 changes: 45 additions & 0 deletions src/WP_CLI/ThemeUpgrader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace WP_CLI;

/**
* A theme upgrader class that tracks changed files.
*/
class ThemeUpgrader extends \Theme_Upgrader {
/**
* List of files that were changed during the update process.
*
* @var array<string>
*/
private $changed_files = [];

public function install_package( $args = array() ) {
parent::upgrade_strings(); // Needed for the 'remove_old' string.

$track_files = function ( $will_invalidate, $filepath ) {
$this->changed_files[] = $filepath;
return $will_invalidate;
};

add_filter( 'wp_opcache_invalidate_file', $track_files, 10, 2 );

$result = parent::install_package( $args );

remove_filter( 'wp_opcache_invalidate_file', $track_files );

// Remove duplicates and sort files.
$this->changed_files = array_unique( $this->changed_files );
sort( $this->changed_files );

return $result;
}

/**
* Returns a list of files that were changed during the update process.
*
* @return array<string> Changed files.
*/
public function get_changed_files() {
return $this->changed_files;
}
}
Loading