11<?php
22
3+ use WP_CLI \CommandWithUpgrade ;
34use WP_CLI \ParsePluginNameInput ;
45use WP_CLI \Utils ;
56use WP_CLI \WpOrgApi ;
4142 * Success: Installed 1 of 1 plugins.
4243 *
4344 * @package wp-cli
45+ *
46+ * @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
47+ * @extends CommandWithUpgrade<string,>
4448 */
45- class Plugin_Command extends \WP_CLI \CommandWithUpgrade {
46-
49+ class Plugin_Command extends CommandWithUpgrade {
4750 use ParsePluginNameInput;
4851
4952 protected $ item_type = 'plugin ' ;
@@ -66,13 +69,6 @@ class Plugin_Command extends \WP_CLI\CommandWithUpgrade {
6669 'auto_update ' ,
6770 );
6871
69- /**
70- * Plugin fetcher instance.
71- *
72- * @var \WP_CLI\Fetchers\Plugin
73- */
74- protected $ fetcher ;
75-
7672 public function __construct () {
7773 require_once ABSPATH . 'wp-admin/includes/plugin.php ' ;
7874 require_once ABSPATH . 'wp-admin/includes/plugin-install.php ' ;
@@ -209,6 +205,9 @@ public function search( $args, $assoc_args ) {
209205 }
210206
211207 protected function status_single ( $ args ) {
208+ /**
209+ * @var object{name: string, file: string} $plugin
210+ */
212211 $ plugin = $ this ->fetcher ->get_check ( $ args [0 ] );
213212 $ file = $ plugin ->file ;
214213
@@ -345,11 +344,18 @@ protected function get_all_items() {
345344 * Plugin 'bbpress' network activated.
346345 * Plugin 'buddypress' network activated.
347346 * Success: Activated 2 of 2 plugins.
347+ *
348+ * @param array $args
349+ * @param array $assoc_args
348350 */
349- public function activate ( $ args , $ assoc_args = array () ) {
351+ public function activate ( $ args , $ assoc_args = [] ) {
350352 $ network_wide = Utils \get_flag_value ( $ assoc_args , 'network ' , false );
351353 $ all = Utils \get_flag_value ( $ assoc_args , 'all ' , false );
352- $ all_exclude = Utils \get_flag_value ( $ assoc_args , 'exclude ' );
354+ $ all_exclude = Utils \get_flag_value ( $ assoc_args , 'exclude ' , '' );
355+
356+ /**
357+ * @var string $all_exclude
358+ */
353359
354360 $ args = $ this ->check_optional_args_and_all ( $ args , $ all , 'activate ' , $ all_exclude );
355361 if ( ! $ args ) {
@@ -358,7 +364,11 @@ public function activate( $args, $assoc_args = array() ) {
358364
359365 $ successes = 0 ;
360366 $ errors = 0 ;
361- $ plugins = $ this ->fetcher ->get_many ( $ args );
367+
368+ /**
369+ * @var array<object{name: string, file: string}> $plugins
370+ */
371+ $ plugins = $ this ->fetcher ->get_many ( $ args );
362372 if ( count ( $ plugins ) < count ( $ args ) ) {
363373 $ errors = count ( $ args ) - count ( $ plugins );
364374 }
@@ -387,7 +397,7 @@ public function activate( $args, $assoc_args = array() ) {
387397
388398 if ( is_wp_error ( $ result ) ) {
389399 $ message = $ result ->get_error_message ();
390- $ message = preg_replace ( '/<a\s[^>]+>.*<\/a>/im ' , '' , $ message );
400+ $ message = ( string ) preg_replace ( '/<a\s[^>]+>.*<\/a>/im ' , '' , $ message );
391401 $ message = wp_strip_all_tags ( $ message );
392402 $ message = str_replace ( 'Error: ' , '' , $ message );
393403 WP_CLI ::warning ( "Failed to activate plugin. {$ message }" );
@@ -437,10 +447,14 @@ public function activate( $args, $assoc_args = array() ) {
437447 * Plugin 'ninja-forms' deactivated.
438448 * Success: Deactivated 2 of 2 plugins.
439449 */
440- public function deactivate ( $ args , $ assoc_args = array () ) {
450+ public function deactivate ( $ args , $ assoc_args = [] ) {
441451 $ network_wide = Utils \get_flag_value ( $ assoc_args , 'network ' );
442452 $ disable_all = Utils \get_flag_value ( $ assoc_args , 'all ' );
443- $ disable_all_exclude = Utils \get_flag_value ( $ assoc_args , 'exclude ' );
453+ $ disable_all_exclude = Utils \get_flag_value ( $ assoc_args , 'exclude ' , '' );
454+
455+ /**
456+ * @var string $disable_all_exclude
457+ */
444458
445459 $ args = $ this ->check_optional_args_and_all ( $ args , $ disable_all , 'deactivate ' , $ disable_all_exclude );
446460 if ( ! $ args ) {
@@ -530,7 +544,7 @@ public function deactivate( $args, $assoc_args = array() ) {
530544 * Plugin 'akismet' activated.
531545 * Success: Toggled 1 of 1 plugins.
532546 */
533- public function toggle ( $ args , $ assoc_args = array () ) {
547+ public function toggle ( $ args , $ assoc_args ) {
534548 $ network_wide = Utils \get_flag_value ( $ assoc_args , 'network ' );
535549
536550 $ successes = 0 ;
@@ -574,6 +588,9 @@ public function path( $args, $assoc_args ) {
574588 $ path = untrailingslashit ( WP_PLUGIN_DIR );
575589
576590 if ( ! empty ( $ args ) ) {
591+ /**
592+ * @var object{name: string, file: string} $plugin
593+ */
577594 $ plugin = $ this ->fetcher ->get_check ( $ args [0 ] );
578595 $ path .= '/ ' . $ plugin ->file ;
579596
@@ -591,6 +608,9 @@ protected function install_from_repo( $slug, $assoc_args ) {
591608 list ($ wp_core_version ) = explode ( '- ' , $ wp_version );
592609 $ wp_core_version = implode ( '. ' , array_slice ( explode ( '. ' , $ wp_core_version ), 0 , 2 ) );
593610
611+ /**
612+ * @var \WP_Error|PluginInformation $api
613+ */
594614 $ api = plugins_api ( 'plugin_information ' , array ( 'slug ' => $ slug ) );
595615
596616 if ( is_wp_error ( $ api ) ) {
@@ -755,6 +775,9 @@ protected function get_item_list() {
755775 $ auto_updates = [];
756776 }
757777
778+ /**
779+ * @var string[] $recently_active
780+ */
758781 $ recently_active = is_network_admin () ? get_site_option ( 'recently_activated ' ) : get_option ( 'recently_activated ' );
759782
760783 if ( false === $ recently_active ) {
@@ -763,10 +786,11 @@ protected function get_item_list() {
763786
764787 foreach ( $ this ->get_all_plugins () as $ file => $ details ) {
765788 $ all_update_info = $ this ->get_update_info ();
766- $ update_info = ( isset ( $ all_update_info ->response [ $ file ] ) && null !== $ all_update_info ->response [ $ file ] ) ? (array ) $ all_update_info ->response [ $ file ] : null ;
767- $ name = Utils \get_plugin_name ( $ file );
768- $ wporg_info = $ this ->get_wporg_data ( $ name );
769- $ plugin_data = get_plugin_data ( WP_PLUGIN_DIR . '/ ' . $ file , false , false );
789+ // @phpstan-ignore notIdentical.alwaysTrue
790+ $ update_info = ( isset ( $ all_update_info ->response [ $ file ] ) && null !== $ all_update_info ->response [ $ file ] ) ? (array ) $ all_update_info ->response [ $ file ] : null ;
791+ $ name = Utils \get_plugin_name ( $ file );
792+ $ wporg_info = $ this ->get_wporg_data ( $ name );
793+ $ plugin_data = get_plugin_data ( WP_PLUGIN_DIR . '/ ' . $ file , false , false );
770794
771795 if ( ! isset ( $ duplicate_names [ $ name ] ) ) {
772796 $ duplicate_names [ $ name ] = array ();
@@ -875,7 +899,7 @@ protected function get_item_list() {
875899
876900 if ( isset ( $ plugin_update_info ->requires ) && version_compare ( $ wp_version , $ requires , '>= ' ) ) {
877901 $ reason = "This update requires WordPress version $ plugin_update_info ->requires , but the version installed is $ wp_version. " ;
878- } elseif ( ! isset ( $ update_info [ ' package ' ] ) ) {
902+ } elseif ( ! isset ( $ plugin_update_info -> package ) ) {
879903 $ reason = 'Update file not provided. Contact author for more details ' ;
880904 } else {
881905 $ reason = 'Update not available ' ;
@@ -904,7 +928,7 @@ protected function get_item_list() {
904928 *
905929 * @param string $plugin_name The plugin slug.
906930 *
907- * @return string The status of the plugin, includes the last update date.
931+ * @return array{status: string, last_updated: string|false, status?: string, last_updated?: string} The status of the plugin, includes the last update date.
908932 */
909933 protected function get_wporg_data ( $ plugin_name ) {
910934 $ data = [
@@ -947,10 +971,12 @@ protected function get_wporg_data( $plugin_name ) {
947971 $ r_body = wp_remote_retrieve_body ( $ request );
948972 if ( strpos ( $ r_body , 'pubDate ' ) !== false ) {
949973 // Very raw check, not validating the format or anything else.
950- $ xml = simplexml_load_string ( $ r_body );
951- $ xml_pub_date = $ xml ->xpath ( '//pubDate ' );
952- if ( $ xml_pub_date ) {
953- $ data ['last_updated ' ] = wp_date ( 'Y-m-d ' , (string ) strtotime ( $ xml_pub_date [0 ] ) );
974+ $ xml = simplexml_load_string ( $ r_body );
975+ if ( false !== $ xml ) {
976+ $ xml_pub_date = $ xml ->xpath ( '//pubDate ' );
977+ if ( $ xml_pub_date ) {
978+ $ data ['last_updated ' ] = wp_date ( 'Y-m-d ' , strtotime ( $ xml_pub_date [0 ] ) ?: null );
979+ }
954980 }
955981 }
956982
@@ -1115,6 +1141,9 @@ public function get( $args, $assoc_args ) {
11151141 'status ' ,
11161142 );
11171143
1144+ /**
1145+ * @var object{name: string, file: string} $plugin
1146+ */
11181147 $ plugin = $ this ->fetcher ->get_check ( $ args [0 ] );
11191148 $ file = $ plugin ->file ;
11201149
@@ -1173,11 +1202,14 @@ public function get( $args, $assoc_args ) {
11731202 * Uninstalled and deleted 'tinymce-templates' plugin.
11741203 * Success: Uninstalled 2 of 2 plugins.
11751204 */
1176- public function uninstall ( $ args , $ assoc_args = array () ) {
1177-
1205+ public function uninstall ( $ args , $ assoc_args = [] ) {
11781206 $ all = Utils \get_flag_value ( $ assoc_args , 'all ' , false );
11791207 $ all_exclude = Utils \get_flag_value ( $ assoc_args , 'exclude ' , false );
11801208
1209+ /**
1210+ * @var string $all_exclude
1211+ */
1212+
11811213 // Check if plugin names or --all is passed.
11821214 $ args = $ this ->check_optional_args_and_all ( $ args , $ all , 'uninstall ' , $ all_exclude );
11831215 if ( ! $ args ) {
@@ -1222,6 +1254,9 @@ public function uninstall( $args, $assoc_args = array() ) {
12221254 if ( '. ' !== $ plugin_slug && ! empty ( $ plugin_translations [ $ plugin_slug ] ) ) {
12231255 $ translations = $ plugin_translations [ $ plugin_slug ];
12241256
1257+ /**
1258+ * @var \WP_Filesystem_Base $wp_filesystem
1259+ */
12251260 global $ wp_filesystem ;
12261261 require_once ABSPATH . '/wp-admin/includes/file.php ' ;
12271262 WP_Filesystem ();
@@ -1233,7 +1268,11 @@ public function uninstall( $args, $assoc_args = array() ) {
12331268
12341269 $ json_translation_files = glob ( WP_LANG_DIR . '/plugins/ ' . $ plugin_slug . '- ' . $ translation . '-*.json ' );
12351270 if ( $ json_translation_files ) {
1236- array_map ( array ( $ wp_filesystem , 'delete ' ), $ json_translation_files );
1271+ /**
1272+ * @var callable $callback
1273+ */
1274+ $ callback = [ $ wp_filesystem , 'delete ' ];
1275+ array_map ( $ callback , $ json_translation_files );
12371276 }
12381277 }
12391278 }
@@ -1257,6 +1296,10 @@ public function uninstall( $args, $assoc_args = array() ) {
12571296 // Remove deleted plugins from the plugin updates list.
12581297 $ current = get_site_transient ( $ this ->upgrade_transient );
12591298 if ( $ current ) {
1299+ /**
1300+ * @var object{response: array<string, mixed>, checked: array<string, mixed>}&\stdClass $current
1301+ */
1302+
12601303 // Don't remove the plugins that weren't deleted.
12611304 $ deleted = array_diff ( $ deleted_plugin_files , $ delete_errors );
12621305
@@ -1292,7 +1335,7 @@ public function uninstall( $args, $assoc_args = array() ) {
12921335 *
12931336 * @subcommand is-installed
12941337 */
1295- public function is_installed ( $ args , $ assoc_args = array () ) {
1338+ public function is_installed ( $ args , $ assoc_args ) {
12961339 if ( $ this ->fetcher ->get ( $ args [0 ] ) ) {
12971340 WP_CLI ::halt ( 0 );
12981341 } else {
@@ -1322,7 +1365,7 @@ public function is_installed( $args, $assoc_args = array() ) {
13221365 *
13231366 * @subcommand is-active
13241367 */
1325- public function is_active ( $ args , $ assoc_args = array () ) {
1368+ public function is_active ( $ args , $ assoc_args ) {
13261369 $ network_wide = Utils \get_flag_value ( $ assoc_args , 'network ' );
13271370
13281371 $ plugin = $ this ->fetcher ->get ( $ args [0 ] );
@@ -1366,10 +1409,14 @@ public function is_active( $args, $assoc_args = array() ) {
13661409 * Deleted 'tinymce-templates' plugin.
13671410 * Success: Deleted 2 of 2 plugins.
13681411 */
1369- public function delete ( $ args , $ assoc_args = array () ) {
1412+ public function delete ( $ args , $ assoc_args ) {
13701413 $ all = Utils \get_flag_value ( $ assoc_args , 'all ' , false );
13711414 $ all_exclude = Utils \get_flag_value ( $ assoc_args , 'exclude ' , false );
13721415
1416+ /**
1417+ * @var string $all_exclude
1418+ */
1419+
13731420 // Check if plugin names or --all is passed.
13741421 $ args = $ this ->check_optional_args_and_all ( $ args , $ all , 'delete ' , $ all_exclude );
13751422 if ( ! $ args ) {
@@ -1505,7 +1552,11 @@ public function delete( $args, $assoc_args = array() ) {
15051552 * @subcommand list
15061553 */
15071554 public function list_ ( $ _ , $ assoc_args ) {
1555+ /**
1556+ * @var string $fields
1557+ */
15081558 $ fields = Utils \get_flag_value ( $ assoc_args , 'fields ' );
1559+
15091560 if ( ! empty ( $ fields ) ) {
15101561 $ fields = explode ( ', ' , $ fields );
15111562 $ this ->check_wporg ['status ' ] = in_array ( 'wporg_status ' , $ fields , true );
@@ -1578,7 +1629,7 @@ private static function get_template_path( $template ) {
15781629 /**
15791630 * Gets the details of a plugin.
15801631 *
1581- * @param object
1632+ * @param string $file Plugin file name.
15821633 * @return array
15831634 */
15841635 private function get_details ( $ file ) {
@@ -1591,8 +1642,8 @@ private function get_details( $file ) {
15911642 /**
15921643 * Performs deletion of plugin files
15931644 *
1594- * @param $plugin - Plugin fetcher object (name, file)
1595- * @return bool - If plugin was deleted
1645+ * @param $plugin Plugin fetcher object (name, file)
1646+ * @return bool Whether plugin was deleted
15961647 */
15971648 private function delete_plugin ( $ plugin ) {
15981649 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
0 commit comments