Skip to content

Commit 6763178

Browse files
authored
Merge pull request #541 from wp-cli/claude/akismet-test-failure-gq0g7i
Fix plugin install detection when update info unavailable
2 parents fe0f651 + 471b95f commit 6763178

2 files changed

Lines changed: 80 additions & 3 deletions

File tree

‎features/plugin-install.feature‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,53 @@ Feature: Install WordPress plugins
165165
"""
166166
And the return code should be 1
167167

168+
Scenario: Installed plugin is detected even without available update information
169+
Given a WP install
170+
# `install_plugin_install_status()` falls back to an "install" status if the
171+
# WordPress.org API does not offer an update for an outdated plugin.
172+
And a wp-content/mu-plugins/no-plugin-updates.php file:
173+
"""
174+
<?php
175+
/**
176+
* Plugin Name: Hide Plugin Updates
177+
* Description: Simulates the WordPress.org API not offering any plugin updates
178+
* Author: WP-CLI tests
179+
*/
180+
add_filter(
181+
'site_transient_update_plugins',
182+
function ( $updates ) {
183+
if ( is_object( $updates ) ) {
184+
$updates->response = array();
185+
}
186+
return $updates;
187+
},
188+
PHP_INT_MAX
189+
);
190+
"""
191+
And a wp-content/plugins/debug-bar/debug-bar.php file:
192+
"""
193+
<?php
194+
/**
195+
* Plugin Name: Debug Bar
196+
* Version: 0.1
197+
*/
198+
"""
199+
200+
When I try `wp plugin install debug-bar`
201+
Then STDOUT should be:
202+
"""
203+
Success: Plugin already installed.
204+
"""
205+
And STDERR should be:
206+
"""
207+
Warning: debug-bar: Plugin already installed.
208+
"""
209+
And STDERR should not contain:
210+
"""
211+
Destination folder already exists
212+
"""
213+
And the return code should be 0
214+
168215
Scenario: Paths aren't backslashed when destination folder already exists
169216
Given a WP install
170217

‎src/Plugin_Command.php‎

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -778,9 +778,15 @@ protected function install_from_repo( $slug, $assoc_args ) {
778778

779779
$status = install_plugin_install_status( $api );
780780

781-
if ( ! Utils\get_flag_value( $assoc_args, 'force' ) && 'install' !== $status['status'] ) {
782-
// We know this will fail, so avoid a needless download of the package.
783-
return new WP_Error( 'already_installed', 'Plugin already installed.' );
781+
if ( ! Utils\get_flag_value( $assoc_args, 'force' ) ) {
782+
$is_installed = 'install' !== $status['status']
783+
|| $this->is_plugin_installed( $slug )
784+
|| $this->is_plugin_installed( $api->slug );
785+
786+
if ( $is_installed ) {
787+
// We know this will fail, so avoid a needless download of the package.
788+
return new WP_Error( 'already_installed', 'Plugin already installed.' );
789+
}
784790
}
785791

786792
WP_CLI::log( sprintf( 'Installing %s (%s)', html_entity_decode( $api->name, ENT_QUOTES ), $api->version ) );
@@ -798,6 +804,30 @@ protected function install_from_repo( $slug, $assoc_args ) {
798804
return $result;
799805
}
800806

807+
/**
808+
* Checks whether a plugin with the given slug is already installed.
809+
*
810+
* `install_plugin_install_status()` reports an 'install' status for a plugin
811+
* that is already installed when the WordPress.org API does not provide any
812+
* update information for the installed version. This happens for example for
813+
* the Akismet plugin that is bundled with WordPress, whenever the bundled
814+
* version is outdated but no update is being offered for it.
815+
*
816+
* Checking the file system as well makes sure such a plugin is reported as
817+
* being already installed instead of the installation failing with a
818+
* "Destination folder already exists" error.
819+
*
820+
* @param string $slug Plugin slug.
821+
* @return bool Whether the plugin folder holds an installed plugin.
822+
*/
823+
private function is_plugin_installed( $slug ) {
824+
if ( ! is_dir( WP_PLUGIN_DIR . '/' . $slug ) ) {
825+
return false;
826+
}
827+
828+
return count( get_plugins( '/' . $slug ) ) > 0;
829+
}
830+
801831
/**
802832
* Updates one or more plugins.
803833
*

0 commit comments

Comments
 (0)