Skip to content

Commit 15872ff

Browse files
CopilotswissspidyCopilot
authored
Add --match-args option to wp cron event delete to target specific event instances (#131)
* Initial plan * Add --match-args option to wp cron event delete for filtering by event arguments Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> Co-authored-by: Pascal Birchler <pascalb@google.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent ceb259c commit 15872ff

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

features/cron.feature

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,3 +583,68 @@ Feature: Manage WP-Cron events and schedules
583583
"""
584584
Error: Please either specify cron events, or use --all.
585585
"""
586+
587+
Scenario: Delete a specific cron event by matching args
588+
When I run `wp cron event schedule wp_cli_test_event_5 '+20 minutes' --0=banana`
589+
And I run `wp cron event schedule wp_cli_test_event_5 '+20 minutes' --0=bar`
590+
Then STDOUT should not be empty
591+
592+
When I run `wp cron event list --format=csv --fields=hook,recurrence,args`
593+
Then STDOUT should be CSV containing:
594+
| hook | recurrence | args |
595+
| wp_cli_test_event_5 | Non-repeating | ["banana"] |
596+
| wp_cli_test_event_5 | Non-repeating | ["bar"] |
597+
598+
When I run `wp cron event delete wp_cli_test_event_5 --match-args='["banana"]'`
599+
Then STDOUT should be:
600+
"""
601+
Success: Deleted a total of 1 cron event.
602+
"""
603+
604+
When I run `wp cron event list --format=csv --fields=hook,args`
605+
Then STDOUT should be CSV containing:
606+
| hook | args |
607+
| wp_cli_test_event_5 | ["bar"] |
608+
And STDOUT should not contain:
609+
"""
610+
["banana"]
611+
"""
612+
613+
When I run `wp cron event delete wp_cli_test_event_5 --match-args=bar`
614+
Then STDOUT should be:
615+
"""
616+
Success: Deleted a total of 1 cron event.
617+
"""
618+
619+
When I try `wp cron event list`
620+
Then STDOUT should not contain:
621+
"""
622+
wp_cli_test_event_5
623+
"""
624+
625+
When I run `wp cron event schedule wp_cli_test_event_5 '+20 minutes' --0=banana`
626+
Then STDOUT should not be empty
627+
628+
When I try `wp cron event delete wp_cli_test_event_5 --match-args='["banana"]' --all`
629+
Then STDERR should be:
630+
"""
631+
Error: The --match-args parameter cannot be combined with --all or --due-now.
632+
"""
633+
634+
When I try `wp cron event delete wp_cli_test_event_5 --match-args='["banana"]' --due-now`
635+
Then STDERR should be:
636+
"""
637+
Error: The --match-args parameter cannot be combined with --all or --due-now.
638+
"""
639+
640+
When I try `wp cron event delete --match-args='["banana"]'`
641+
Then STDERR should be:
642+
"""
643+
Error: The --match-args parameter requires exactly one hook name.
644+
"""
645+
646+
When I try `wp cron event delete wp_cli_test_event_5 wp_cli_test_event_5 --match-args='["banana"]'`
647+
Then STDERR should be:
648+
"""
649+
Error: The --match-args parameter requires exactly one hook name.
650+
"""

src/Cron_Event_Command.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,19 +326,65 @@ public function unschedule( $args, $assoc_args ) {
326326
* [--all]
327327
* : Delete all hooks.
328328
*
329+
* [--match-args=<args>]
330+
* : Only delete events whose arguments match the given JSON-encoded array or scalar value. Argument types must match exactly (for example, `["123"]` vs `[123]`). Requires exactly one hook name.
331+
*
329332
* ## EXAMPLES
330333
*
331334
* # Delete all scheduled cron events for the given hook
332335
* $ wp cron event delete cron_test
333336
* Success: Deleted a total of 2 cron events.
337+
*
338+
* # Delete a specific cron event by hook and arguments
339+
* $ wp cron event delete cron_test --match-args='["123"]'
340+
* Success: Deleted a total of 1 cron event.
334341
*/
335342
public function delete( $args, $assoc_args ) {
343+
$match_args = Utils\get_flag_value( $assoc_args, 'match-args' );
344+
345+
if ( null !== $match_args ) {
346+
if ( 1 !== count( $args ) ) {
347+
WP_CLI::error( 'The --match-args parameter requires exactly one hook name.' );
348+
}
349+
350+
if ( Utils\get_flag_value( $assoc_args, 'all' ) || Utils\get_flag_value( $assoc_args, 'due-now' ) ) {
351+
WP_CLI::error( 'The --match-args parameter cannot be combined with --all or --due-now.' );
352+
}
353+
354+
$trimmed_match_args = ltrim( $match_args );
355+
356+
// Only JSON-decode when the value clearly looks like JSON:
357+
// - starts with '[' for arrays
358+
// - starts with '"' for explicitly quoted strings
359+
if ( '' !== $trimmed_match_args && ( '[' === $trimmed_match_args[0] || '"' === $trimmed_match_args[0] ) ) {
360+
$decoded_args = json_decode( $match_args, true );
361+
if ( null === $decoded_args && JSON_ERROR_NONE !== json_last_error() ) {
362+
// Not valid JSON — treat as a single string argument wrapped in an array.
363+
$decoded_args = array( $match_args );
364+
} elseif ( ! is_array( $decoded_args ) ) {
365+
$decoded_args = array( $decoded_args );
366+
}
367+
} else {
368+
// Treat non-JSON-looking values as a single string argument.
369+
$decoded_args = array( $match_args );
370+
}
371+
}
372+
336373
$events = self::get_selected_cron_events( $args, $assoc_args );
337374

338375
if ( is_wp_error( $events ) ) {
339376
WP_CLI::error( $events );
340377
}
341378

379+
if ( null !== $match_args ) {
380+
$events = array_filter(
381+
$events,
382+
function ( $event ) use ( $decoded_args ) {
383+
return $event->args === $decoded_args;
384+
}
385+
);
386+
}
387+
342388
$deleted = 0;
343389
foreach ( $events as $event ) {
344390
$result = self::delete_event( $event );

0 commit comments

Comments
 (0)