diff --git a/features/plugin-install.feature b/features/plugin-install.feature index 319c0787..7eae2b28 100644 --- a/features/plugin-install.feature +++ b/features/plugin-install.feature @@ -305,3 +305,77 @@ Feature: Install WordPress plugins """ active """ + + Scenario: Install with --activate on already-active plugin should keep it activated + Given a WP install + + When I run `wp plugin install hello-dolly --activate` + Then STDOUT should contain: + """ + Plugin 'hello-dolly' activated. + """ + And the return code should be 0 + + When I run `wp plugin list --name=hello-dolly --field=status` + Then STDOUT should be: + """ + active + """ + + When I try `wp plugin install hello-dolly --activate` + Then STDERR should contain: + """ + Warning: hello-dolly: Plugin already installed. + """ + And STDOUT should contain: + """ + Activating 'hello-dolly'... + """ + And STDOUT should contain: + """ + Plugin 'hello-dolly' activated. + """ + And the return code should be 0 + + When I run `wp plugin list --name=hello-dolly --field=status` + Then STDOUT should be: + """ + active + """ + + Scenario: Install with --activate-network on already-network-active plugin should keep it activated + Given a WP multisite install + + When I run `wp plugin install hello-dolly --activate-network` + Then STDOUT should contain: + """ + Plugin 'hello-dolly' network activated. + """ + And the return code should be 0 + + When I run `wp plugin list --name=hello-dolly --field=status` + Then STDOUT should be: + """ + active-network + """ + + When I try `wp plugin install hello-dolly --activate-network` + Then STDERR should contain: + """ + Warning: hello-dolly: Plugin already installed. + """ + And STDOUT should contain: + """ + Network-activating 'hello-dolly'... + """ + And STDOUT should contain: + """ + Plugin 'hello-dolly' network activated. + """ + And the return code should be 0 + + When I run `wp plugin list --name=hello-dolly --field=status` + Then STDOUT should be: + """ + active-network + """ diff --git a/src/Plugin_Command.php b/src/Plugin_Command.php index 06875d73..68cb819b 100644 --- a/src/Plugin_Command.php +++ b/src/Plugin_Command.php @@ -391,7 +391,8 @@ public function activate( $args, $assoc_args = [] ) { // If force flag is set, deactivate and reactivate to run activation hooks. if ( $force ) { deactivate_plugins( $plugin->file, false, true ); - } else { + } elseif ( ! $this->chained_command ) { + // Only skip if not part of a chained command. WP_CLI::warning( "Plugin '{$plugin->name}' is already network active." ); continue; } @@ -401,7 +402,8 @@ public function activate( $args, $assoc_args = [] ) { // If force flag is set, deactivate and reactivate to run activation hooks. if ( $force ) { deactivate_plugins( $plugin->file, false, false ); - } else { + } elseif ( ! $this->chained_command ) { + // Only skip if not part of a chained command. WP_CLI::warning( "Plugin '{$plugin->name}' is already active." ); continue; } @@ -415,22 +417,30 @@ public function activate( $args, $assoc_args = [] ) { $result = activate_plugin( $plugin->file, '', $network_wide ); if ( is_wp_error( $result ) ) { - $message = $result->get_error_message(); - $message = (string) preg_replace( '/]+>.*<\/a>/im', '', $message ); - $message = wp_strip_all_tags( $message ); - $message = str_replace( 'Error: ', '', $message ); - WP_CLI::warning( "Failed to activate plugin. {$message}" ); - // If the error is due to unexpected output, display it for debugging - if ( 'unexpected_output' === $result->get_error_code() ) { - /** - * @var string $output - */ - $output = $result->get_error_data(); - if ( ! empty( $output ) ) { - WP_CLI::debug( "Unexpected output: {$output}", 'plugin' ); + // When called from a chained command, treat 'already_active' as success. + // This handles race conditions where WordPress may have preserved activation + // status during the install process. + if ( $this->chained_command && 'plugin_already_active' === $result->get_error_code() ) { + $this->active_output( $plugin->name, $plugin->file, $network_wide, 'activate' ); + ++$successes; + } else { + $message = $result->get_error_message(); + $message = (string) preg_replace( '/]+>.*<\/a>/im', '', $message ); + $message = wp_strip_all_tags( $message ); + $message = str_replace( 'Error: ', '', $message ); + WP_CLI::warning( "Failed to activate plugin. {$message}" ); + // If the error is due to unexpected output, display it for debugging + if ( 'unexpected_output' === $result->get_error_code() ) { + /** + * @var string $output + */ + $output = $result->get_error_data(); + if ( ! empty( $output ) ) { + WP_CLI::debug( "Unexpected output: {$output}", 'plugin' ); + } } + ++$errors; } - ++$errors; } else { $this->active_output( $plugin->name, $plugin->file, $network_wide, 'activate' ); ++$successes;