diff --git a/features/plugin-update.feature b/features/plugin-update.feature
index 1cf5e248..66f5b8ac 100644
--- a/features/plugin-update.feature
+++ b/features/plugin-update.feature
@@ -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
+ """
+
diff --git a/features/theme-update.feature b/features/theme-update.feature
index adc546b0..8c68a259 100644
--- a/features/theme-update.feature
+++ b/features/theme-update.feature
@@ -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
+ """
+
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 96cef65a..c78b63b5 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -59,7 +59,7 @@
*/src/WP_CLI/Fetchers/(Plugin|Theme)\.php$
*/src/WP_CLI/CommandWithUpgrade\.php$
- */src/WP_CLI/(CommandWith|DestructivePlugin|DestructiveTheme)Upgrader\.php$
+ */src/WP_CLI/(CommandWith|DestructivePlugin|DestructiveTheme|Plugin|Theme)Upgrader\.php$
*/src/WP_CLI/Parse(Plugin|Theme)NameInput\.php$
*/src/WP_CLI/ExtensionUpgraderSkin\.php$
diff --git a/src/Plugin_Command.php b/src/Plugin_Command.php
index 5ce246ac..10773a31 100644
--- a/src/Plugin_Command.php
+++ b/src/Plugin_Command.php
@@ -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';
}
/**
@@ -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
@@ -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 ) {
diff --git a/src/Theme_Command.php b/src/Theme_Command.php
index e18b17e8..9d4392d7 100644
--- a/src/Theme_Command.php
+++ b/src/Theme_Command.php
@@ -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';
}
/**
@@ -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
@@ -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 ) {
diff --git a/src/WP_CLI/CommandWithUpgrade.php b/src/WP_CLI/CommandWithUpgrade.php
index 8326c168..bb48e6e8 100755
--- a/src/WP_CLI/CommandWithUpgrade.php
+++ b/src/WP_CLI/CommandWithUpgrade.php
@@ -527,6 +527,10 @@ function ( $item ) {
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 ) {
@@ -604,6 +608,18 @@ static function ( $result ) {
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();
+ 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.
diff --git a/src/WP_CLI/DestructiveThemeUpgrader.php b/src/WP_CLI/DestructiveThemeUpgrader.php
index 699d6dc0..0d89af7a 100644
--- a/src/WP_CLI/DestructiveThemeUpgrader.php
+++ b/src/WP_CLI/DestructiveThemeUpgrader.php
@@ -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.
diff --git a/src/WP_CLI/PluginUpgrader.php b/src/WP_CLI/PluginUpgrader.php
new file mode 100644
index 00000000..45fa3cf4
--- /dev/null
+++ b/src/WP_CLI/PluginUpgrader.php
@@ -0,0 +1,45 @@
+
+ */
+ 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 Changed files.
+ */
+ public function get_changed_files() {
+ return $this->changed_files;
+ }
+}
diff --git a/src/WP_CLI/ThemeUpgrader.php b/src/WP_CLI/ThemeUpgrader.php
new file mode 100644
index 00000000..e4a1ac4a
--- /dev/null
+++ b/src/WP_CLI/ThemeUpgrader.php
@@ -0,0 +1,45 @@
+
+ */
+ 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 Changed files.
+ */
+ public function get_changed_files() {
+ return $this->changed_files;
+ }
+}