Skip to content
39 changes: 39 additions & 0 deletions features/cron-event.feature
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,45 @@ Feature: Manage WP Cron events
Debug: Arguments:
"""

Scenario: Run cron events with --network flag on non-multisite
When I try `wp cron event run --due-now --network`
Then STDERR should be:
"""
Error: This is not a multisite installation.
"""
And the return code should be 1

Scenario: Run cron events with --network flag on multisite
Given a WP multisite subdirectory install
And I run `wp site create --slug=site2`
And I run `wp site create --slug=site3`

When I run `wp cron event schedule wp_cli_network_test now`
Then STDOUT should contain:
"""
Success: Scheduled event with hook 'wp_cli_network_test'
"""

When I run `wp --url=example.com/site2 cron event schedule wp_cli_network_test_site2 now`
Then STDOUT should contain:
"""
Success: Scheduled event with hook 'wp_cli_network_test_site2'
"""

When I run `wp cron event run --due-now --network --exclude=wp_privacy_delete_old_export_files,wp_version_check,wp_update_plugins,wp_update_themes,wp_site_health_scheduled_check,wp_update_user_counts,wp_scheduled_delete,wp_scheduled_auto_draft_delete`
Then STDOUT should contain:
"""
Executed the cron event 'wp_cli_network_test'
"""
And STDOUT should contain:
"""
Executed the cron event 'wp_cli_network_test_site2'
"""
And STDOUT should contain:
"""
Success: Executed a total of 2 cron events across 3 sites.
"""

Scenario: Confirm that cron event run in debug mode shows the start of events
When I try `wp cron event run wp_version_check --debug=cron`
Then STDOUT should contain:
Expand Down
96 changes: 84 additions & 12 deletions src/Cron_Event_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,34 +225,82 @@ public function schedule( $args, $assoc_args ) {
* [--all]
* : Run all hooks.
*
* [--network]
* : Run hooks across all sites in a multisite installation.
*
* ## EXAMPLES
*
* # Run all cron events due right now
* $ wp cron event run --due-now
* Executed the cron event 'cron_test_1' in 0.01s.
* Executed the cron event 'cron_test_2' in 0.006s.
* Success: Executed a total of 2 cron events.
*
* # Run all cron events due right now across all sites in a multisite
* $ wp cron event run --due-now --network
* Executed the cron event 'cron_test_1' in 0.01s.
* Executed the cron event 'cron_test_2' in 0.006s.
* Success: Executed a total of 2 cron events across 3 sites.
*/
public function run( $args, $assoc_args ) {

$network = Utils\get_flag_value( $assoc_args, 'network' );

if ( $network ) {
if ( ! is_multisite() ) {
WP_CLI::error( 'This is not a multisite installation.' );
}

$sites = get_sites(
array(
'fields' => 'ids',
'number' => 0,
)
);

if ( empty( $sites ) ) {
WP_CLI::error( 'No sites found in the network.' );
}

// Remove network flag before passing to get_selected_cron_events.
$network_assoc_args = $assoc_args;
unset( $network_assoc_args['network'] );

$total_executed = 0;
$site_count = count( $sites );

foreach ( $sites as $site_id ) {
switch_to_blog( $site_id );

$events = self::get_selected_cron_events( $args, $network_assoc_args );

if ( ! is_wp_error( $events ) ) {
$total_executed += self::run_events( $events );
} else {
WP_CLI::debug( sprintf( 'No events found for site %d: %s', $site_id, $events->get_error_message() ), 'cron' );
}

restore_current_blog();
}

$message = sprintf(
'Executed a total of %d %s across %d %s.',
$total_executed,
Utils\pluralize( 'cron event', $total_executed ),
$site_count,
Utils\pluralize( 'site', $site_count )
);
WP_CLI::success( $message );
return;
}

$events = self::get_selected_cron_events( $args, $assoc_args );

if ( is_wp_error( $events ) ) {
WP_CLI::error( $events );
}

$executed = 0;
foreach ( $events as $event ) {
WP_CLI::debug( sprintf( "Beginning execution of cron event '%s'.", $event->hook ), 'cron' );
$start = microtime( true );
$result = self::run_event( $event );
$total = round( microtime( true ) - $start, 3 );
++$executed;
WP_CLI::log( sprintf( "Executed the cron event '%s' in %ss.", $event->hook, $total ) );
if ( ! empty( $event->args ) ) {
WP_CLI::debug( sprintf( 'Arguments: %s', wp_json_encode( $event->args ) ), 'cron' );
}
}
$executed = self::run_events( $events );

$message = ( 1 === $executed ) ? 'Executed a total of %d cron event.' : 'Executed a total of %d cron events.';
WP_CLI::success( sprintf( $message, $executed ) );
Expand Down Expand Up @@ -344,6 +392,30 @@ public function delete( $args, $assoc_args ) {
WP_CLI::success( sprintf( $message, $deleted ) );
}

/**
* Runs multiple cron events and logs their execution.
*
* @param array $events Array of event objects to run.
* @return int The number of events executed.
*/
private static function run_events( array $events ) {
$executed = 0;

foreach ( $events as $event ) {
WP_CLI::debug( sprintf( "Beginning execution of cron event '%s'.", $event->hook ), 'cron' );
$start = microtime( true );
self::run_event( $event );
$total = round( microtime( true ) - $start, 3 );
++$executed;
WP_CLI::log( sprintf( "Executed the cron event '%s' in %ss.", $event->hook, $total ) );
if ( ! empty( $event->args ) ) {
WP_CLI::debug( sprintf( 'Arguments: %s', wp_json_encode( $event->args ) ), 'cron' );
}
}

return $executed;
}

/**
* Executes an event immediately.
*
Expand Down
Loading