Skip to content

Commit ab0aba9

Browse files
authored
Merge pull request #500 from wp-cli/copilot/fix-plugin-deactivation-after-update
Fix plugin deactivation during force install with explicit --activate flag
2 parents 7c9bfe0 + 85c39cb commit ab0aba9

File tree

2 files changed

+100
-16
lines changed

2 files changed

+100
-16
lines changed

features/plugin-install.feature

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,3 +398,77 @@ Feature: Install WordPress plugins
398398
"""
399399
active
400400
"""
401+
402+
Scenario: Install with --activate on already-active plugin should keep it activated
403+
Given a WP install
404+
405+
When I run `wp plugin install hello-dolly --activate`
406+
Then STDOUT should contain:
407+
"""
408+
Plugin 'hello-dolly' activated.
409+
"""
410+
And the return code should be 0
411+
412+
When I run `wp plugin list --name=hello-dolly --field=status`
413+
Then STDOUT should be:
414+
"""
415+
active
416+
"""
417+
418+
When I try `wp plugin install hello-dolly --activate`
419+
Then STDERR should contain:
420+
"""
421+
Warning: hello-dolly: Plugin already installed.
422+
"""
423+
And STDOUT should contain:
424+
"""
425+
Activating 'hello-dolly'...
426+
"""
427+
And STDOUT should contain:
428+
"""
429+
Plugin 'hello-dolly' activated.
430+
"""
431+
And the return code should be 0
432+
433+
When I run `wp plugin list --name=hello-dolly --field=status`
434+
Then STDOUT should be:
435+
"""
436+
active
437+
"""
438+
439+
Scenario: Install with --activate-network on already-network-active plugin should keep it activated
440+
Given a WP multisite install
441+
442+
When I run `wp plugin install hello-dolly --activate-network`
443+
Then STDOUT should contain:
444+
"""
445+
Plugin 'hello-dolly' network activated.
446+
"""
447+
And the return code should be 0
448+
449+
When I run `wp plugin list --name=hello-dolly --field=status`
450+
Then STDOUT should be:
451+
"""
452+
active-network
453+
"""
454+
455+
When I try `wp plugin install hello-dolly --activate-network`
456+
Then STDERR should contain:
457+
"""
458+
Warning: hello-dolly: Plugin already installed.
459+
"""
460+
And STDOUT should contain:
461+
"""
462+
Network-activating 'hello-dolly'...
463+
"""
464+
And STDOUT should contain:
465+
"""
466+
Plugin 'hello-dolly' network activated.
467+
"""
468+
And the return code should be 0
469+
470+
When I run `wp plugin list --name=hello-dolly --field=status`
471+
Then STDOUT should be:
472+
"""
473+
active-network
474+
"""

src/Plugin_Command.php

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,8 @@ public function activate( $args, $assoc_args = [] ) {
487487
// If force flag is set, deactivate and reactivate to run activation hooks.
488488
if ( $force ) {
489489
deactivate_plugins( $plugin->file, false, true );
490-
} else {
490+
} elseif ( ! $this->chained_command ) {
491+
// Only skip if not part of a chained command.
491492
WP_CLI::warning( "Plugin '{$plugin->name}' is already network active." );
492493
continue;
493494
}
@@ -497,7 +498,8 @@ public function activate( $args, $assoc_args = [] ) {
497498
// If force flag is set, deactivate and reactivate to run activation hooks.
498499
if ( $force ) {
499500
deactivate_plugins( $plugin->file, false, false );
500-
} else {
501+
} elseif ( ! $this->chained_command ) {
502+
// Only skip if not part of a chained command.
501503
WP_CLI::warning( "Plugin '{$plugin->name}' is already active." );
502504
continue;
503505
}
@@ -511,22 +513,30 @@ public function activate( $args, $assoc_args = [] ) {
511513
$result = activate_plugin( $plugin->file, '', $network_wide );
512514

513515
if ( is_wp_error( $result ) ) {
514-
$message = $result->get_error_message();
515-
$message = (string) preg_replace( '/<a\s[^>]+>.*<\/a>/im', '', $message );
516-
$message = wp_strip_all_tags( $message );
517-
$message = str_replace( 'Error: ', '', $message );
518-
WP_CLI::warning( "Failed to activate plugin. {$message}" );
519-
// If the error is due to unexpected output, display it for debugging
520-
if ( 'unexpected_output' === $result->get_error_code() ) {
521-
/**
522-
* @var string $output
523-
*/
524-
$output = $result->get_error_data();
525-
if ( ! empty( $output ) ) {
526-
WP_CLI::debug( "Unexpected output: {$output}", 'plugin' );
516+
// When called from a chained command, treat 'already_active' as success.
517+
// This handles race conditions where WordPress may have preserved activation
518+
// status during the install process.
519+
if ( $this->chained_command && 'plugin_already_active' === $result->get_error_code() ) {
520+
$this->active_output( $plugin->name, $plugin->file, $network_wide, 'activate' );
521+
++$successes;
522+
} else {
523+
$message = $result->get_error_message();
524+
$message = (string) preg_replace( '/<a\s[^>]+>.*<\/a>/im', '', $message );
525+
$message = wp_strip_all_tags( $message );
526+
$message = str_replace( 'Error: ', '', $message );
527+
WP_CLI::warning( "Failed to activate plugin. {$message}" );
528+
// If the error is due to unexpected output, display it for debugging
529+
if ( 'unexpected_output' === $result->get_error_code() ) {
530+
/**
531+
* @var string $output
532+
*/
533+
$output = $result->get_error_data();
534+
if ( ! empty( $output ) ) {
535+
WP_CLI::debug( "Unexpected output: {$output}", 'plugin' );
536+
}
527537
}
538+
++$errors;
528539
}
529-
++$errors;
530540
} else {
531541
$this->active_output( $plugin->name, $plugin->file, $network_wide, 'activate' );
532542
++$successes;

0 commit comments

Comments
 (0)