From 42aeb320b31272724afa896517010b350c847240 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 21 May 2025 10:49:01 +0200 Subject: [PATCH 1/4] PHPStan level 9 --- composer.json | 7 +++++-- features/cron-event.feature | 8 -------- phpstan.neon.dist | 19 +++++++++++++++++++ src/Cron_Command.php | 3 +-- src/Cron_Event_Command.php | 35 ++++++++++++++++++++++++++--------- src/Cron_Schedule_Command.php | 4 +++- 6 files changed, 54 insertions(+), 22 deletions(-) create mode 100644 phpstan.neon.dist diff --git a/composer.json b/composer.json index c6c799b6..61361d1d 100644 --- a/composer.json +++ b/composer.json @@ -18,14 +18,15 @@ "wp-cli/entity-command": "^1.3 || ^2", "wp-cli/eval-command": "^2.0", "wp-cli/server-command": "^2.0", - "wp-cli/wp-cli-tests": "^4" + "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 }, @@ -62,12 +63,14 @@ "behat-rerun": "rerun-behat-tests", "lint": "run-linter-tests", "phpcs": "run-phpcs-tests", + "phpstan": "run-phpstan-tests", "phpcbf": "run-phpcbf-cleanup", "phpunit": "run-php-unit-tests", "prepare-tests": "install-package-tests", "test": [ "@lint", "@phpcs", + "@phpstan", "@phpunit", "@behat" ] diff --git a/features/cron-event.feature b/features/cron-event.feature index 48d01647..86356f20 100644 --- a/features/cron-event.feature +++ b/features/cron-event.feature @@ -81,14 +81,6 @@ Feature: Manage WP Cron events Error: No events found for hook 'wp_cli_test_event'. """ - @less-than-wp-4.9.0 - Scenario: Unschedule cron event for WP < 4.9.0, wp_unschedule_hook was not included - When I try `wp cron event unschedule wp_cli_test_event_1` - Then STDERR should be: - """ - Error: Unscheduling events is only supported from WordPress 4.9.0 onwards. - """ - Scenario: Run cron event with a registered shutdown function Given a wp-content/mu-plugins/setup_shutdown_function.php file: """ diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 00000000..f22013d9 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,19 @@ +parameters: + level: 9 + paths: + - src + - cron-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.parameter + - identifier: missingType.return diff --git a/src/Cron_Command.php b/src/Cron_Command.php index 132ef3c7..290d5050 100644 --- a/src/Cron_Command.php +++ b/src/Cron_Command.php @@ -65,7 +65,6 @@ public function test() { */ protected static function get_cron_spawn() { - $sslverify = \WP_CLI\Utils\wp_version_compare( 4.0, '<' ); $doing_wp_cron = sprintf( '%.22F', microtime( true ) ); $cron_request_array = array( @@ -75,7 +74,7 @@ protected static function get_cron_spawn() { 'timeout' => 3, 'blocking' => true, // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Calling native WordPress hook. - 'sslverify' => apply_filters( 'https_local_ssl_verify', $sslverify ), + 'sslverify' => apply_filters( 'https_local_ssl_verify', false ), ), ); diff --git a/src/Cron_Event_Command.php b/src/Cron_Event_Command.php index 62f2c7ec..7aaea9be 100644 --- a/src/Cron_Event_Command.php +++ b/src/Cron_Event_Command.php @@ -28,7 +28,9 @@ * @package wp-cli */ class Cron_Event_Command extends WP_CLI_Command { - + /** + * @var string[] + */ private $fields = array( 'hook', 'next_run_gmt', @@ -36,6 +38,9 @@ class Cron_Event_Command extends WP_CLI_Command { 'recurrence', ); + /** + * @var string + */ private static $time_format = 'Y-m-d H:i:s'; /** @@ -160,8 +165,16 @@ public function schedule( $args, $assoc_args ) { WP_CLI::warning( 'Numeric keys should be used for the hook arguments.' ); } - $hook = $args[0]; - $next_run = Utils\get_flag_value( $args, 1, 'now' ); + $hook = $args[0]; + + /** + * @var string $next_run + */ + $next_run = Utils\get_flag_value( $args, 1, 'now' ); + + /** + * @var string|false $recurrence + */ $recurrence = Utils\get_flag_value( $args, 2, false ); if ( empty( $next_run ) ) { @@ -263,10 +276,6 @@ public function unschedule( $args, $assoc_args ) { list( $hook ) = $args; - if ( Utils\wp_version_compare( '4.9.0', '<' ) ) { - WP_CLI::error( 'Unscheduling events is only supported from WordPress 4.9.0 onwards.' ); - } - $unscheduled = wp_unschedule_hook( $hook ); if ( empty( $unscheduled ) ) { @@ -455,8 +464,12 @@ protected static function get_cron_events( $is_due_now = false ) { * @return array|WP_Error An array of objects, or a WP_Error object is there are no events scheduled. */ protected static function get_selected_cron_events( $args, $assoc_args ) { - $due_now = Utils\get_flag_value( $assoc_args, 'due-now' ); - $all = Utils\get_flag_value( $assoc_args, 'all' ); + $due_now = (bool) Utils\get_flag_value( $assoc_args, 'due-now' ); + $all = (bool) Utils\get_flag_value( $assoc_args, 'all' ); + + /** + * @var string $exclude + */ $exclude = Utils\get_flag_value( $assoc_args, 'exclude' ); if ( empty( $args ) && ! $due_now && ! $all ) { @@ -549,6 +562,10 @@ private static function interval( $since ) { array( 1, 'second' ), ); + $name = 'second'; + $count = 0; + $seconds = 1; + // we only want to output two chunks of time here, eg: // x years, xx months // x days, xx hours diff --git a/src/Cron_Schedule_Command.php b/src/Cron_Schedule_Command.php index b5b29fdc..839a91f1 100644 --- a/src/Cron_Schedule_Command.php +++ b/src/Cron_Schedule_Command.php @@ -16,7 +16,9 @@ * +------------+-------------+----------+ */ class Cron_Schedule_Command extends WP_CLI_Command { - + /** + * @var string[] + */ private $fields = array( 'name', 'display', From 6ccb2296655750d0abc728bebc13bad225edc4a8 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Fri, 30 May 2025 15:44:04 +0200 Subject: [PATCH 2/4] Further fixes --- composer.json | 2 +- src/Cron_Event_Command.php | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 61361d1d..cf77fbfa 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "wp-cli/entity-command": "^1.3 || ^2", "wp-cli/eval-command": "^2.0", "wp-cli/server-command": "^2.0", - "wp-cli/wp-cli-tests": "dev-main" + "wp-cli/wp-cli-tests": "dev-add/phpstan-enhancements" }, "config": { "process-timeout": 7200, diff --git a/src/Cron_Event_Command.php b/src/Cron_Event_Command.php index 7aaea9be..2ea2df5c 100644 --- a/src/Cron_Event_Command.php +++ b/src/Cron_Event_Command.php @@ -167,14 +167,7 @@ public function schedule( $args, $assoc_args ) { $hook = $args[0]; - /** - * @var string $next_run - */ - $next_run = Utils\get_flag_value( $args, 1, 'now' ); - - /** - * @var string|false $recurrence - */ + $next_run = Utils\get_flag_value( $args, 1, 'now' ); $recurrence = Utils\get_flag_value( $args, 2, false ); if ( empty( $next_run ) ) { @@ -464,8 +457,8 @@ protected static function get_cron_events( $is_due_now = false ) { * @return array|WP_Error An array of objects, or a WP_Error object is there are no events scheduled. */ protected static function get_selected_cron_events( $args, $assoc_args ) { - $due_now = (bool) Utils\get_flag_value( $assoc_args, 'due-now' ); - $all = (bool) Utils\get_flag_value( $assoc_args, 'all' ); + $due_now = Utils\get_flag_value( $assoc_args, 'due-now' ); + $all = Utils\get_flag_value( $assoc_args, 'all' ); /** * @var string $exclude @@ -571,6 +564,9 @@ private static function interval( $since ) { // x days, xx hours // so there's only two bits of calculation below: + $i = 0; + $j = 0; + // step one: the first chunk for ( $i = 0, $j = count( $chunks ); $i < $j; $i++ ) { $seconds = $chunks[ $i ][0]; From 1205b61e8723b61d33f4d8eddcfcb456716e8b7d Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Thu, 12 Jun 2025 11:05:22 +0200 Subject: [PATCH 3/4] some cleanup --- phpstan.neon.dist | 5 ----- src/Cron_Event_Command.php | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index f22013d9..2b34fce1 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -5,14 +5,9 @@ parameters: - cron-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.parameter diff --git a/src/Cron_Event_Command.php b/src/Cron_Event_Command.php index 2ea2df5c..e789267c 100644 --- a/src/Cron_Event_Command.php +++ b/src/Cron_Event_Command.php @@ -159,6 +159,9 @@ public function list_( $args, $assoc_args ) { * # Schedule new cron event and pass arguments * $ wp cron event schedule cron_test '+1 hour' --0=first-argument --1=second-argument * Success: Scheduled event with hook 'cron_test' for 2016-05-31 11:21:35 GMT. + * + * @param array{0: string, 1?: string, 2?: string} $args Positional arguments. + * @param array $assoc_args Associative arguments. */ public function schedule( $args, $assoc_args ) { if ( count( $assoc_args ) && count( array_filter( array_keys( $assoc_args ), 'is_string' ) ) ) { From bd2d7c18bad56652bfd536a2cbf6f76696511ede Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Thu, 3 Jul 2025 16:51:49 +0200 Subject: [PATCH 4/4] Update dependencies --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index cf77fbfa..db093ebe 100644 --- a/composer.json +++ b/composer.json @@ -12,13 +12,13 @@ } ], "require": { - "wp-cli/wp-cli": "^2.12" + "wp-cli/wp-cli": "^2.13" }, "require-dev": { "wp-cli/entity-command": "^1.3 || ^2", "wp-cli/eval-command": "^2.0", "wp-cli/server-command": "^2.0", - "wp-cli/wp-cli-tests": "dev-add/phpstan-enhancements" + "wp-cli/wp-cli-tests": "^5" }, "config": { "process-timeout": 7200,