From 21a6c7b050dedb94d39cefcd548cc1b937ca17c0 Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Fri, 30 Jun 2017 00:21:49 +0000 Subject: [PATCH] Cron API: Introduce `wp_unschedule_hook()` to clear all events attached to a hook. This complements `wp_clear_scheduled_hook()`, which only clears events attached with specific arguments. Props arena, mordauk, jrf. Fixes #18997. git-svn-id: https://develop.svn.wordpress.org/trunk@40965 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/cron.php | 25 ++++++++++++++++++++++++- tests/phpunit/tests/cron.php | 21 +++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/cron.php b/src/wp-includes/cron.php index f7e444b83e..69502a3e45 100644 --- a/src/wp-includes/cron.php +++ b/src/wp-includes/cron.php @@ -191,7 +191,7 @@ function wp_unschedule_event( $timestamp, $hook, $args = array() ) { } /** - * Unschedule all events attached to the specified hook. + * Unschedule all events attached to the hook with the specified arguments. * * @since 2.1.0 * @@ -221,6 +221,29 @@ function wp_clear_scheduled_hook( $hook, $args = array() ) { } } +/** + * Unschedule all events attached to the hook. + * + * Can be useful for plugins when deactivating to clean up the cron queue. + * + * @since 4.9.0 + * + * @param string $hook Action hook, the execution of which will be unscheduled. + */ +function wp_unschedule_hook( $hook ) { + $crons = _get_cron_array(); + + foreach( $crons as $timestamp => $args ) { + unset( $crons[ $timestamp ][ $hook ] ); + + if ( empty( $crons[ $timestamp ] ) ) { + unset( $crons[ $timestamp ] ); + } + } + + _set_cron_array( $crons ); +} + /** * Retrieve the next timestamp for an event. * diff --git a/tests/phpunit/tests/cron.php b/tests/phpunit/tests/cron.php index ee231d4b05..1851f013e3 100644 --- a/tests/phpunit/tests/cron.php +++ b/tests/phpunit/tests/cron.php @@ -186,7 +186,28 @@ class Tests_Cron extends WP_UnitTestCase { // wp_clear_scheduled_hook() should take args as an array like the other functions and does from WP 3.0 wp_clear_scheduled_hook($multi_hook, $multi_args); $this->assertFalse( wp_next_scheduled($multi_hook, $multi_args) ); + } + /** + * @ticket 18997 + */ + function test_unschedule_hook() { + $hook = __FUNCTION__; + $args = array( rand_str() ); + + // schedule several events with and without arguments. + wp_schedule_single_event( strtotime( '+1 hour' ), $hook ); + wp_schedule_single_event( strtotime( '+2 hour' ), $hook ); + wp_schedule_single_event( strtotime( '+3 hour' ), $hook, $args ); + wp_schedule_single_event( strtotime( '+4 hour' ), $hook, $args ); + + // make sure they're returned by wp_next_scheduled(). + $this->assertTrue( wp_next_scheduled( $hook ) > 0 ); + $this->assertTrue( wp_next_scheduled( $hook, $args ) > 0 ); + + // clear the schedule and make sure it's gone. + wp_unschedule_hook( $hook ); + $this->assertFalse( wp_next_scheduled( $hook ) ); } /**