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; + } +}