Skip to content

Commit a096871

Browse files
authored
Merge pull request #480 from wp-cli/copilot/fix-active-plugins-check
Add warning in `wp plugin is-active` for missing plugin files still in active_plugins
2 parents df3fc0c + 0ed14ea commit a096871

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

features/plugin-is-active.feature

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
Feature: Check if a WordPress plugin is active
2+
3+
Background:
4+
Given a WP install
5+
6+
Scenario: Check if an active plugin is active
7+
When I run `wp plugin activate akismet`
8+
Then STDOUT should contain:
9+
"""
10+
Success:
11+
"""
12+
13+
When I run `wp plugin is-active akismet`
14+
Then the return code should be 0
15+
16+
Scenario: Check if an inactive plugin is not active
17+
When I run `wp plugin activate akismet`
18+
Then STDOUT should contain:
19+
"""
20+
Success:
21+
"""
22+
23+
When I run `wp plugin deactivate akismet`
24+
Then STDOUT should contain:
25+
"""
26+
Success:
27+
"""
28+
29+
When I try `wp plugin is-active akismet`
30+
Then the return code should be 1
31+
32+
Scenario: Check if a non-existent plugin is not active
33+
When I try `wp plugin is-active non-existent-plugin`
34+
Then the return code should be 1
35+
36+
Scenario: Warn when plugin is in active_plugins but file does not exist
37+
When I run `wp plugin activate akismet`
38+
Then STDOUT should contain:
39+
"""
40+
Success:
41+
"""
42+
43+
When I run `wp plugin is-active akismet`
44+
Then the return code should be 0
45+
46+
# Remove the plugin directory
47+
When I run `wp plugin path akismet --dir`
48+
Then save STDOUT as {PLUGIN_PATH}
49+
50+
When I run `rm -rf {PLUGIN_PATH}`
51+
Then the return code should be 0
52+
53+
# Now the plugin file is gone but still in active_plugins
54+
When I try `wp plugin is-active akismet`
55+
Then STDERR should contain:
56+
"""
57+
Warning: Plugin 'akismet' is marked as active but the plugin file does not exist.
58+
"""
59+
And the return code should be 1
60+
61+
Scenario: Warn when network-activated plugin is in active_sitewide_plugins but file does not exist
62+
Given a WP multisite install
63+
64+
When I run `wp plugin activate akismet --network`
65+
Then STDOUT should contain:
66+
"""
67+
Success:
68+
"""
69+
70+
When I run `wp plugin is-active akismet --network`
71+
Then the return code should be 0
72+
73+
# Remove the plugin directory
74+
When I run `wp plugin path akismet --dir`
75+
Then save STDOUT as {PLUGIN_PATH}
76+
77+
When I run `rm -rf {PLUGIN_PATH}`
78+
Then the return code should be 0
79+
80+
# Now the plugin file is gone but still in active_sitewide_plugins
81+
When I try `wp plugin is-active akismet --network`
82+
Then STDERR should contain:
83+
"""
84+
Warning: Plugin 'akismet' is marked as active but the plugin file does not exist.
85+
"""
86+
And the return code should be 1

src/Plugin_Command.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,10 @@ public function is_installed( $args, $assoc_args ) {
14891489
*
14901490
* Returns exit code 0 when active, 1 when not active.
14911491
*
1492+
* If the plugin does not exist but is still in WordPress's active plugins storage
1493+
* (such as the active plugins option or the sitewide plugins option for network-activated plugins),
1494+
* a warning will be emitted.
1495+
*
14921496
* ## OPTIONS
14931497
*
14941498
* <plugin>
@@ -1512,6 +1516,55 @@ public function is_active( $args, $assoc_args ) {
15121516
$plugin = $this->fetcher->get( $args[0] );
15131517

15141518
if ( ! $plugin ) {
1519+
// Plugin not found via fetcher, but it might still be in active_plugins option
1520+
// Check if it's in the active_plugins list
1521+
$input_name = $args[0];
1522+
// For network plugins: active_sitewide_plugins is an array where keys are plugin files and values are timestamps
1523+
// For regular plugins: active_plugins is an array of plugin file paths
1524+
$active_plugins = $network_wide ? get_site_option( 'active_sitewide_plugins', [] ) : get_option( 'active_plugins', [] );
1525+
1526+
// Ensure we have an array to work with
1527+
if ( ! is_array( $active_plugins ) ) {
1528+
$active_plugins = [];
1529+
}
1530+
1531+
// For network-wide plugins, extract the plugin files from the keys
1532+
if ( $network_wide ) {
1533+
$active_plugin_files = array_keys( $active_plugins );
1534+
} else {
1535+
$active_plugin_files = $active_plugins;
1536+
}
1537+
1538+
// Try to find a matching plugin file in active_plugins using the same logic as the fetcher
1539+
// This matches: exact file name, "name.php", or directory name
1540+
$found_in_active = '';
1541+
foreach ( $active_plugin_files as $plugin_file ) {
1542+
// Ensure plugin_file is a string
1543+
if ( ! is_string( $plugin_file ) ) {
1544+
continue;
1545+
}
1546+
1547+
// Check if the input matches the plugin file in various ways
1548+
// This mirrors the logic in WP_CLI\Fetchers\Plugin::get()
1549+
if (
1550+
"$input_name.php" === $plugin_file ||
1551+
$plugin_file === $input_name ||
1552+
( dirname( $plugin_file ) === $input_name && '.' !== $input_name )
1553+
) {
1554+
$found_in_active = $plugin_file;
1555+
break;
1556+
}
1557+
}
1558+
1559+
if ( $found_in_active ) {
1560+
// Plugin is in active_plugins but file doesn't exist
1561+
// Use validate_plugin to confirm the file is missing
1562+
$validation = validate_plugin( $found_in_active );
1563+
if ( is_wp_error( $validation ) ) {
1564+
WP_CLI::warning( "Plugin '{$input_name}' is marked as active but the plugin file does not exist." );
1565+
}
1566+
}
1567+
15151568
WP_CLI::halt( 1 );
15161569
}
15171570

0 commit comments

Comments
 (0)