Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@
"wp-cli/entity-command": "^1.3 || ^2",
"wp-cli/language-command": "^2.0",
"wp-cli/scaffold-command": "^1.2 || ^2",
"wp-cli/wp-cli-tests": "^4.3.7"
"wp-cli/wp-cli-tests": "dev-main"
},
"config": {
"process-timeout": 7200,
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true,
"johnpbloch/wordpress-core-installer": true
"johnpbloch/wordpress-core-installer": true,
"phpstan/extension-installer": true
},
"lock": false
},
Expand Down Expand Up @@ -92,11 +93,13 @@
"lint": "run-linter-tests",
"phpcs": "run-phpcs-tests",
"phpcbf": "run-phpcbf-cleanup",
"phpstan": "run-phpstan-tests",
"phpunit": "run-php-unit-tests",
"prepare-tests": "install-package-tests",
"test": [
"@lint",
"@phpcs",
"@phpstan",
"@phpunit",
"@behat"
]
Expand Down
20 changes: 20 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
parameters:
level: 9
paths:
- src
- extension-command.php
scanDirectories:
- vendor/wp-cli/wp-cli/php
- vendor/wp-cli/wp-cli-tests
scanFiles:
- vendor/php-stubs/wordpress-stubs/wordpress-stubs.php
treatPhpDocTypesAsCertain: false
dynamicConstantNames:
- WP_DEBUG
- WP_DEBUG_LOG
- WP_DEBUG_DISPLAY
ignoreErrors:
- identifier: missingType.iterableValue
- identifier: missingType.property
- identifier: missingType.parameter
- identifier: missingType.return
11 changes: 7 additions & 4 deletions src/Plugin_AutoUpdates_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,13 @@ public function __construct() {
* $ wp plugin auto-updates enable hello
* Plugin auto-updates for 'hello' enabled.
* Success: Enabled 1 of 1 plugin auto-updates.
*
* @param array $args
* @param array $assoc_args
*/
public function enable( $args, $assoc_args ) {
$all = Utils\get_flag_value( $assoc_args, 'all', false );
$disabled_only = Utils\get_flag_value( $assoc_args, 'disabled-only', false );
$all = (bool) Utils\get_flag_value( $assoc_args, 'all', false );
$disabled_only = (bool) Utils\get_flag_value( $assoc_args, 'disabled-only', false );

$args = $this->check_optional_args_and_all( $args, $all );
if ( ! $args ) {
Expand Down Expand Up @@ -151,7 +154,7 @@ public function enable( $args, $assoc_args ) {
* Success: Disabled 1 of 1 plugin auto-updates.
*/
public function disable( $args, $assoc_args ) {
$all = Utils\get_flag_value( $assoc_args, 'all', false );
$all = (bool) Utils\get_flag_value( $assoc_args, 'all', false );
$enabled_only = Utils\get_flag_value( $assoc_args, 'enabled-only', false );

$args = $this->check_optional_args_and_all( $args, $all );
Expand Down Expand Up @@ -259,7 +262,7 @@ public function disable( $args, $assoc_args ) {
* duplicate-post
*/
public function status( $args, $assoc_args ) {
$all = Utils\get_flag_value( $assoc_args, 'all', false );
$all = (bool) Utils\get_flag_value( $assoc_args, 'all', false );
$enabled_only = Utils\get_flag_value( $assoc_args, 'enabled-only', false );
$disabled_only = Utils\get_flag_value( $assoc_args, 'disabled-only', false );

Expand Down
102 changes: 79 additions & 23 deletions src/Plugin_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
* Success: Installed 1 of 1 plugins.
*
* @package wp-cli
*
* @phpstan-type PluginInformation object{name: string, slug: non-empty-string, version: string, new_version: string, download_link: string, requires_php?: string, requires?: string, package: string}&\stdClass
*/
class Plugin_Command extends \WP_CLI\CommandWithUpgrade {

Expand Down Expand Up @@ -209,6 +211,9 @@ public function search( $args, $assoc_args ) {
}

protected function status_single( $args ) {
/**
* @var object{name: string, file: string} $plugin
*/
$plugin = $this->fetcher->get_check( $args[0] );
$file = $plugin->file;

Expand Down Expand Up @@ -345,11 +350,18 @@ protected function get_all_items() {
* Plugin 'bbpress' network activated.
* Plugin 'buddypress' network activated.
* Success: Activated 2 of 2 plugins.
*
* @param array $args
* @param array $assoc_args
*/
public function activate( $args, $assoc_args = array() ) {
$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' );
$network_wide = (bool) Utils\get_flag_value( $assoc_args, 'network', false );
$all = (bool) Utils\get_flag_value( $assoc_args, 'all', false );
$all_exclude = Utils\get_flag_value( $assoc_args, 'exclude', '' );

/**
* @var string $all_exclude
*/

$args = $this->check_optional_args_and_all( $args, $all, 'activate', $all_exclude );
if ( ! $args ) {
Expand All @@ -358,7 +370,11 @@ public function activate( $args, $assoc_args = array() ) {

$successes = 0;
$errors = 0;
$plugins = $this->fetcher->get_many( $args );

/**
* @var array<object{name: string, file: string}> $plugins
*/
$plugins = $this->fetcher->get_many( $args );
if ( count( $plugins ) < count( $args ) ) {
$errors = count( $args ) - count( $plugins );
}
Expand Down Expand Up @@ -387,7 +403,7 @@ public function activate( $args, $assoc_args = array() ) {

if ( is_wp_error( $result ) ) {
$message = $result->get_error_message();
$message = preg_replace( '/<a\s[^>]+>.*<\/a>/im', '', $message );
$message = (string) preg_replace( '/<a\s[^>]+>.*<\/a>/im', '', $message );
$message = wp_strip_all_tags( $message );
$message = str_replace( 'Error: ', '', $message );
WP_CLI::warning( "Failed to activate plugin. {$message}" );
Expand Down Expand Up @@ -438,9 +454,13 @@ public function activate( $args, $assoc_args = array() ) {
* Success: Deactivated 2 of 2 plugins.
*/
public function deactivate( $args, $assoc_args = array() ) {
$network_wide = Utils\get_flag_value( $assoc_args, 'network' );
$disable_all = Utils\get_flag_value( $assoc_args, 'all' );
$disable_all_exclude = Utils\get_flag_value( $assoc_args, 'exclude' );
$network_wide = (bool) Utils\get_flag_value( $assoc_args, 'network' );
$disable_all = (bool) Utils\get_flag_value( $assoc_args, 'all' );
$disable_all_exclude = Utils\get_flag_value( $assoc_args, 'exclude', '' );

/**
* @var string $disable_all_exclude
*/

$args = $this->check_optional_args_and_all( $args, $disable_all, 'deactivate', $disable_all_exclude );
if ( ! $args ) {
Expand Down Expand Up @@ -574,6 +594,9 @@ public function path( $args, $assoc_args ) {
$path = untrailingslashit( WP_PLUGIN_DIR );

if ( ! empty( $args ) ) {
/**
* @var object{name: string, file: string} $plugin
*/
$plugin = $this->fetcher->get_check( $args[0] );
$path .= '/' . $plugin->file;

Expand All @@ -591,6 +614,9 @@ protected function install_from_repo( $slug, $assoc_args ) {
list($wp_core_version) = explode( '-', $wp_version );
$wp_core_version = implode( '.', array_slice( explode( '.', $wp_core_version ), 0, 2 ) );

/**
* @var \WP_Error|PluginInformation $api
*/
$api = plugins_api( 'plugin_information', array( 'slug' => $slug ) );

if ( is_wp_error( $api ) ) {
Expand Down Expand Up @@ -726,7 +752,7 @@ protected function install_from_repo( $slug, $assoc_args ) {
* @alias upgrade
*/
public function update( $args, $assoc_args ) {
$all = Utils\get_flag_value( $assoc_args, 'all', false );
$all = (bool) Utils\get_flag_value( $assoc_args, 'all', false );

$args = $this->check_optional_args_and_all( $args, $all );
if ( ! $args ) {
Expand Down Expand Up @@ -755,6 +781,9 @@ protected function get_item_list() {
$auto_updates = [];
}

/**
* @var string[] $recently_active
*/
$recently_active = is_network_admin() ? get_site_option( 'recently_activated' ) : get_option( 'recently_activated' );

if ( false === $recently_active ) {
Expand Down Expand Up @@ -875,7 +904,7 @@ protected function get_item_list() {

if ( isset( $plugin_update_info->requires ) && version_compare( $wp_version, $requires, '>=' ) ) {
$reason = "This update requires WordPress version $plugin_update_info->requires, but the version installed is $wp_version.";
} elseif ( ! isset( $update_info['package'] ) ) {
} elseif ( ! isset( $plugin_update_info->package ) ) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$update_info does not exist at this point.

Introduced in #451

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ FYI @mrsdizzie

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦‍♀️ yes that is a typo since these are similarly named. I should set up PHPStan (!)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good thing that I am working on a unified setup :-)

$reason = 'Update file not provided. Contact author for more details';
} else {
$reason = 'Update not available';
Expand Down Expand Up @@ -904,7 +933,7 @@ protected function get_item_list() {
*
* @param string $plugin_name The plugin slug.
*
* @return string The status of the plugin, includes the last update date.
* @return array{status: string, last_updated: string|false, status?: string, last_updated?: string} The status of the plugin, includes the last update date.
*/
protected function get_wporg_data( $plugin_name ) {
$data = [
Expand Down Expand Up @@ -947,10 +976,12 @@ protected function get_wporg_data( $plugin_name ) {
$r_body = wp_remote_retrieve_body( $request );
if ( strpos( $r_body, 'pubDate' ) !== false ) {
// Very raw check, not validating the format or anything else.
$xml = simplexml_load_string( $r_body );
$xml_pub_date = $xml->xpath( '//pubDate' );
if ( $xml_pub_date ) {
$data['last_updated'] = wp_date( 'Y-m-d', (string) strtotime( $xml_pub_date[0] ) );
$xml = simplexml_load_string( $r_body );
if ( false !== $xml ) {
$xml_pub_date = $xml->xpath( '//pubDate' );
if ( $xml_pub_date ) {
$data['last_updated'] = wp_date( 'Y-m-d', strtotime( $xml_pub_date[0] ) ?: null );
}
}
}

Expand Down Expand Up @@ -1115,6 +1146,9 @@ public function get( $args, $assoc_args ) {
'status',
);

/**
* @var object{name: string, file: string} $plugin
*/
$plugin = $this->fetcher->get_check( $args[0] );
$file = $plugin->file;

Expand Down Expand Up @@ -1174,10 +1208,13 @@ public function get( $args, $assoc_args ) {
* Success: Uninstalled 2 of 2 plugins.
*/
public function uninstall( $args, $assoc_args = array() ) {

$all = Utils\get_flag_value( $assoc_args, 'all', false );
$all = (bool) Utils\get_flag_value( $assoc_args, 'all', false );
$all_exclude = Utils\get_flag_value( $assoc_args, 'exclude', false );

/**
* @var string $all_exclude
*/

// Check if plugin names or --all is passed.
$args = $this->check_optional_args_and_all( $args, $all, 'uninstall', $all_exclude );
if ( ! $args ) {
Expand Down Expand Up @@ -1222,6 +1259,9 @@ public function uninstall( $args, $assoc_args = array() ) {
if ( '.' !== $plugin_slug && ! empty( $plugin_translations[ $plugin_slug ] ) ) {
$translations = $plugin_translations[ $plugin_slug ];

/**
* @var \WP_Filesystem_Base $wp_filesystem
*/
global $wp_filesystem;
require_once ABSPATH . '/wp-admin/includes/file.php';
WP_Filesystem();
Expand All @@ -1233,7 +1273,11 @@ public function uninstall( $args, $assoc_args = array() ) {

$json_translation_files = glob( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '-*.json' );
if ( $json_translation_files ) {
array_map( array( $wp_filesystem, 'delete' ), $json_translation_files );
/**
* @var callable $callback
*/
$callback = array( $wp_filesystem, 'delete' );
array_map( $callback, $json_translation_files );
}
}
}
Expand All @@ -1257,6 +1301,10 @@ public function uninstall( $args, $assoc_args = array() ) {
// Remove deleted plugins from the plugin updates list.
$current = get_site_transient( $this->upgrade_transient );
if ( $current ) {
/**
* @var object{response: array<string, mixed>, checked: array<string, mixed>}&\stdClass $current
*/

// Don't remove the plugins that weren't deleted.
$deleted = array_diff( $deleted_plugin_files, $delete_errors );

Expand Down Expand Up @@ -1323,7 +1371,7 @@ public function is_installed( $args, $assoc_args = array() ) {
* @subcommand is-active
*/
public function is_active( $args, $assoc_args = array() ) {
$network_wide = Utils\get_flag_value( $assoc_args, 'network' );
$network_wide = (bool) Utils\get_flag_value( $assoc_args, 'network' );

$plugin = $this->fetcher->get( $args[0] );

Expand Down Expand Up @@ -1367,9 +1415,13 @@ public function is_active( $args, $assoc_args = array() ) {
* Success: Deleted 2 of 2 plugins.
*/
public function delete( $args, $assoc_args = array() ) {
$all = Utils\get_flag_value( $assoc_args, 'all', false );
$all = (bool) Utils\get_flag_value( $assoc_args, 'all', false );
$all_exclude = Utils\get_flag_value( $assoc_args, 'exclude', false );

/**
* @var string $all_exclude
*/

// Check if plugin names or --all is passed.
$args = $this->check_optional_args_and_all( $args, $all, 'delete', $all_exclude );
if ( ! $args ) {
Expand Down Expand Up @@ -1505,7 +1557,11 @@ public function delete( $args, $assoc_args = array() ) {
* @subcommand list
*/
public function list_( $_, $assoc_args ) {
/**
* @var string $fields
*/
$fields = Utils\get_flag_value( $assoc_args, 'fields' );

if ( ! empty( $fields ) ) {
$fields = explode( ',', $fields );
$this->check_wporg['status'] = in_array( 'wporg_status', $fields, true );
Expand Down Expand Up @@ -1578,7 +1634,7 @@ private static function get_template_path( $template ) {
/**
* Gets the details of a plugin.
*
* @param object
* @param string $file Plugin file name.
* @return array
*/
private function get_details( $file ) {
Expand All @@ -1591,8 +1647,8 @@ private function get_details( $file ) {
/**
* Performs deletion of plugin files
*
* @param $plugin - Plugin fetcher object (name, file)
* @return bool - If plugin was deleted
* @param $plugin Plugin fetcher object (name, file)
* @return bool Whether plugin was deleted
*/
private function delete_plugin( $plugin ) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
Expand Down
12 changes: 6 additions & 6 deletions src/Theme_AutoUpdates_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function __construct() {
* Success: Enabled 1 of 1 theme auto-updates.
*/
public function enable( $args, $assoc_args ) {
$all = Utils\get_flag_value( $assoc_args, 'all', false );
$all = (bool) Utils\get_flag_value( $assoc_args, 'all', false );
$disabled_only = Utils\get_flag_value( $assoc_args, 'disabled-only', false );

$args = $this->check_optional_args_and_all( $args, $all );
Expand Down Expand Up @@ -151,8 +151,8 @@ public function enable( $args, $assoc_args ) {
* Success: Disabled 1 of 1 theme auto-updates.
*/
public function disable( $args, $assoc_args ) {
$all = Utils\get_flag_value( $assoc_args, 'all', false );
$enabled_only = Utils\get_flag_value( $assoc_args, 'enabled-only', false );
$all = (bool) Utils\get_flag_value( $assoc_args, 'all', false );
$enabled_only = (bool) Utils\get_flag_value( $assoc_args, 'enabled-only', false );

$args = $this->check_optional_args_and_all( $args, $all );
if ( ! $args ) {
Expand Down Expand Up @@ -259,9 +259,9 @@ public function disable( $args, $assoc_args ) {
* twentyseventeen
*/
public function status( $args, $assoc_args ) {
$all = Utils\get_flag_value( $assoc_args, 'all', false );
$enabled_only = Utils\get_flag_value( $assoc_args, 'enabled-only', false );
$disabled_only = Utils\get_flag_value( $assoc_args, 'disabled-only', false );
$all = (bool) Utils\get_flag_value( $assoc_args, 'all', false );
$enabled_only = (bool) Utils\get_flag_value( $assoc_args, 'enabled-only', false );
$disabled_only = (bool) Utils\get_flag_value( $assoc_args, 'disabled-only', false );

if ( $enabled_only && $disabled_only ) {
WP_CLI::error(
Expand Down
Loading
Loading