From dec35ffc45ae83c0fd6143df045a6291e6489d88 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:29:33 +0000 Subject: [PATCH 1/8] Initial plan From 62abd24ba3b53b8e7867c521857651d24407ecc6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:38:28 +0000 Subject: [PATCH 2/8] Add --force flag to plugin activate and wire it up with plugin install Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Plugin_Command.php | 27 +++++++++++++++++++++++---- src/WP_CLI/CommandWithUpgrade.php | 13 +++++++++++-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/Plugin_Command.php b/src/Plugin_Command.php index c257debbc..2d571d407 100644 --- a/src/Plugin_Command.php +++ b/src/Plugin_Command.php @@ -321,6 +321,9 @@ protected function get_all_items() { * [--network] * : If set, the plugin will be activated for the entire multisite network. * + * [--force] + * : If set, the plugin activation hooks will be run even if the plugin is already active. + * * ## EXAMPLES * * # Activate plugin @@ -345,6 +348,11 @@ protected function get_all_items() { * Plugin 'buddypress' network activated. * Success: Activated 2 of 2 plugins. * + * # Force re-running activation hooks for an already active plugin. + * $ wp plugin activate hello --force + * Plugin 'hello' activated. + * Success: Activated 1 of 1 plugins. + * * @param array $args * @param array $assoc_args */ @@ -352,6 +360,7 @@ public function activate( $args, $assoc_args = [] ) { $network_wide = Utils\get_flag_value( $assoc_args, 'network', false ); $all = Utils\get_flag_value( $assoc_args, 'all', false ); $all_exclude = Utils\get_flag_value( $assoc_args, 'exclude', '' ); + $force = Utils\get_flag_value( $assoc_args, 'force', false ); /** * @var string $all_exclude @@ -379,13 +388,23 @@ public function activate( $args, $assoc_args = [] ) { } // Network-active is the highest level of activation status. if ( 'active-network' === $status ) { - WP_CLI::warning( "Plugin '{$plugin->name}' is already network active." ); - continue; + // If force flag is set, deactivate and reactivate to run activation hooks. + if ( $force ) { + deactivate_plugins( $plugin->file, false, true ); + } else { + WP_CLI::warning( "Plugin '{$plugin->name}' is already network active." ); + continue; + } } // Don't reactivate active plugins, but do let them become network-active. if ( ! $network_wide && 'active' === $status ) { - WP_CLI::warning( "Plugin '{$plugin->name}' is already active." ); - continue; + // If force flag is set, deactivate and reactivate to run activation hooks. + if ( $force ) { + deactivate_plugins( $plugin->file, false, false ); + } else { + WP_CLI::warning( "Plugin '{$plugin->name}' is already active." ); + continue; + } } // Plugins need to be deactivated before being network activated. diff --git a/src/WP_CLI/CommandWithUpgrade.php b/src/WP_CLI/CommandWithUpgrade.php index 52f9f5bf5..12d17f27c 100755 --- a/src/WP_CLI/CommandWithUpgrade.php +++ b/src/WP_CLI/CommandWithUpgrade.php @@ -314,14 +314,23 @@ public function install( $args, $assoc_args ) { if ( true === $allow_activation && count( $extension ) > 0 ) { $this->chained_command = true; + $force = Utils\get_flag_value( $assoc_args, 'force', false ); if ( Utils\get_flag_value( $assoc_args, 'activate-network' ) ) { WP_CLI::log( "Network-activating '$slug'..." ); - $this->activate( array( $slug ), array( 'network' => true ) ); + $activate_args = array( 'network' => true ); + if ( $force ) { + $activate_args['force'] = true; + } + $this->activate( array( $slug ), $activate_args ); } if ( Utils\get_flag_value( $assoc_args, 'activate' ) ) { WP_CLI::log( "Activating '$slug'..." ); - $this->activate( array( $slug ) ); + $activate_args = array(); + if ( $force ) { + $activate_args['force'] = true; + } + $this->activate( array( $slug ), $activate_args ); } $this->chained_command = false; } From 22f703d3dc2e740842acfc896fd4fb4e168d055b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:40:00 +0000 Subject: [PATCH 3/8] Add tests for --force flag with plugin activate and install Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/plugin-activate.feature | 44 +++++++++++++++++++++++++ features/plugin-install.feature | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/features/plugin-activate.feature b/features/plugin-activate.feature index a479e8017..6d0e250cf 100644 --- a/features/plugin-activate.feature +++ b/features/plugin-activate.feature @@ -177,3 +177,47 @@ Feature: Activate WordPress plugins Debug (plugin): Unexpected output: Unexpected output from plugin activation """ And the return code should be 1 + + Scenario: Force activate an already active plugin to re-run activation hooks + Given a wp-content/plugins/force-test.php file: + """ + Date: Wed, 4 Feb 2026 16:42:43 +0000 Subject: [PATCH 4/8] Address code review feedback - improve documentation and add error suppression in tests Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/plugin-activate.feature | 2 +- features/plugin-install.feature | 2 +- src/Plugin_Command.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/features/plugin-activate.feature b/features/plugin-activate.feature index 6d0e250cf..1ca93c0a1 100644 --- a/features/plugin-activate.feature +++ b/features/plugin-activate.feature @@ -189,7 +189,7 @@ Feature: Activate WordPress plugins */ register_activation_hook( __FILE__, function() { - file_put_contents( WP_CONTENT_DIR . '/activation-test.txt', 'Activation hook was run' ); + @file_put_contents( WP_CONTENT_DIR . '/activation-test.txt', 'Activation hook was run' ); }); """ diff --git a/features/plugin-install.feature b/features/plugin-install.feature index 25c1caa8b..6097d67dd 100644 --- a/features/plugin-install.feature +++ b/features/plugin-install.feature @@ -319,7 +319,7 @@ Feature: Install WordPress plugins */ register_activation_hook( __FILE__, function() { - file_put_contents( WP_CONTENT_DIR . '/install-activation-test.txt', 'Activation hook was run' ); + @file_put_contents( WP_CONTENT_DIR . '/install-activation-test.txt', 'Activation hook was run' ); }); """ diff --git a/src/Plugin_Command.php b/src/Plugin_Command.php index 2d571d407..022e1bad0 100644 --- a/src/Plugin_Command.php +++ b/src/Plugin_Command.php @@ -322,7 +322,7 @@ protected function get_all_items() { * : If set, the plugin will be activated for the entire multisite network. * * [--force] - * : If set, the plugin activation hooks will be run even if the plugin is already active. + * : If set, deactivates and reactivates the plugin to re-run activation hooks, even if already active. * * ## EXAMPLES * From 5b4b9e83568f8580c9549221612cc318d096dff5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 19:26:14 +0000 Subject: [PATCH 5/8] Fix failing tests - correct expected output and use zip for install test Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/plugin-activate.feature | 8 ++++++-- features/plugin-install.feature | 11 +++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/features/plugin-activate.feature b/features/plugin-activate.feature index 1ca93c0a1..62326bbd5 100644 --- a/features/plugin-activate.feature +++ b/features/plugin-activate.feature @@ -206,11 +206,15 @@ Feature: Activate WordPress plugins # Try activating without --force (should skip) When I try `wp plugin activate force-test` - Then STDERR should be: + Then STDERR should contain: """ Warning: Plugin 'force-test' is already active. - Error: No plugins activated. """ + And STDOUT should be: + """ + Success: Plugin already activated. + """ + And the return code should be 0 And the wp-content/activation-test.txt file should not exist # Now try with --force (should re-run activation hooks) diff --git a/features/plugin-install.feature b/features/plugin-install.feature index 6097d67dd..2c9247d9b 100644 --- a/features/plugin-install.feature +++ b/features/plugin-install.feature @@ -308,7 +308,7 @@ Feature: Install WordPress plugins Scenario: Force reinstall and activate an already active plugin to re-run activation hooks Given a WP install - And a wp-content/plugins/install-force-test.php file: + And a wp-content/plugins/install-force-test/install-force-test.php file: """ Date: Mon, 16 Feb 2026 21:54:55 +0000 Subject: [PATCH 6/8] Simplify install test - use activate --force instead of reinstalling from zip Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/plugin-install.feature | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/features/plugin-install.feature b/features/plugin-install.feature index 2c9247d9b..c3344196e 100644 --- a/features/plugin-install.feature +++ b/features/plugin-install.feature @@ -306,7 +306,7 @@ Feature: Install WordPress plugins active """ - Scenario: Force reinstall and activate an already active plugin to re-run activation hooks + Scenario: Force activate an already active plugin to re-run activation hooks Given a WP install And a wp-content/plugins/install-force-test/install-force-test.php file: """ @@ -333,32 +333,9 @@ Feature: Install WordPress plugins # Remove the file to test if it gets recreated with --force When I run `rm wp-content/install-activation-test.txt` - # Create a zip of the plugin for reinstallation - When I run `cd wp-content/plugins && zip -r /tmp/install-force-test.zip install-force-test` - - # Try install --activate without --force (should skip activation hooks) - When I run `wp plugin install /tmp/install-force-test.zip --activate` - Then STDOUT should contain: - """ - Unpacking the package... - """ - And STDOUT should contain: - """ - Activating 'install-force-test'... - """ - And STDERR should contain: - """ - Warning: Plugin 'install-force-test' is already active. - """ - And the wp-content/install-activation-test.txt file should not exist - - # Now try install --activate --force (should re-run activation hooks) - When I run `wp plugin install /tmp/install-force-test.zip --activate --force` + # Now try activate --force (should re-run activation hooks) + When I run `wp plugin activate install-force-test --force` Then STDOUT should contain: - """ - Activating 'install-force-test'... - """ - And STDOUT should contain: """ Plugin 'install-force-test' activated. """ From 2a4d8b33481dd6491a4ce02ada833a7f21f41b30 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 07:31:20 +0000 Subject: [PATCH 7/8] Fix --all --force interaction and remove duplicate test Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/plugin-install.feature | 36 --------------------------------- src/Plugin_Command.php | 2 +- 2 files changed, 1 insertion(+), 37 deletions(-) diff --git a/features/plugin-install.feature b/features/plugin-install.feature index c3344196e..319c0787a 100644 --- a/features/plugin-install.feature +++ b/features/plugin-install.feature @@ -305,39 +305,3 @@ Feature: Install WordPress plugins """ active """ - - Scenario: Force activate an already active plugin to re-run activation hooks - Given a WP install - And a wp-content/plugins/install-force-test/install-force-test.php file: - """ - get_status( $plugin->file ); - if ( $all && in_array( $status, [ 'active', 'active-network' ], true ) ) { + if ( $all && ! $force && in_array( $status, [ 'active', 'active-network' ], true ) ) { continue; } // Network-active is the highest level of activation status. From 515161ca0cd0e07a9249fc744e9e6ac607d32257 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 17 Feb 2026 10:55:03 +0100 Subject: [PATCH 8/8] Apply suggestion from @swissspidy --- features/plugin-activate.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/plugin-activate.feature b/features/plugin-activate.feature index 62326bbd5..f387573d4 100644 --- a/features/plugin-activate.feature +++ b/features/plugin-activate.feature @@ -205,7 +205,7 @@ Feature: Activate WordPress plugins When I run `rm wp-content/activation-test.txt` # Try activating without --force (should skip) - When I try `wp plugin activate force-test` + And I try `wp plugin activate force-test` Then STDERR should contain: """ Warning: Plugin 'force-test' is already active.