From be59c5009e357e0cb1f1b146a3f8a1aaab375819 Mon Sep 17 00:00:00 2001 From: Scott Taylor Date: Fri, 17 Oct 2014 19:16:26 +0000 Subject: [PATCH] `wp_schedule_single_event()` should not prevent scheduling a future duplicate event. It should only reject an event as a duplicate if there is already a similar event scheduled within 10 minutes of the given timestamp. Adds unit tests, fixes existing cron test. Props tellyworth. See [9181], #6966. Fixes #28213. git-svn-id: https://develop.svn.wordpress.org/trunk@29939 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/cron.php | 5 +++-- tests/phpunit/tests/cron.php | 31 +++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/wp-includes/cron.php b/src/wp-includes/cron.php index 244699c8ed..c4ce866cf6 100644 --- a/src/wp-includes/cron.php +++ b/src/wp-includes/cron.php @@ -20,10 +20,11 @@ * @param array $args Optional. Arguments to pass to the hook's callback function. */ function wp_schedule_single_event( $timestamp, $hook, $args = array()) { - // don't schedule a duplicate if there's already an identical event due in the next 10 minutes + // don't schedule a duplicate if there's already an identical event due within 10 minutes of it $next = wp_next_scheduled($hook, $args); - if ( $next && $next <= $timestamp + 10 * MINUTE_IN_SECONDS ) + if ( $next && abs( $next - $timestamp ) <= 10 * MINUTE_IN_SECONDS ) { return; + } $crons = _get_cron_array(); $event = (object) array( 'hook' => $hook, 'timestamp' => $timestamp, 'schedule' => false, 'args' => $args ); diff --git a/tests/phpunit/tests/cron.php b/tests/phpunit/tests/cron.php index 8373d042b9..2d96c2e765 100644 --- a/tests/phpunit/tests/cron.php +++ b/tests/phpunit/tests/cron.php @@ -214,20 +214,39 @@ class Tests_Cron extends WP_UnitTestCase { function test_not_duplicate_event() { // duplicate events far apart should work normally $hook = rand_str(); - $args = array(rand_str()); - $ts1 = strtotime('+30 minutes'); - $ts2 = strtotime('+3 minutes'); + $args = array( rand_str() ); + $ts1 = strtotime( '+30 minutes' ); + $ts2 = strtotime( '+3 minutes' ); // first one works wp_schedule_single_event( $ts1, $hook, $args ); // second works too wp_schedule_single_event( $ts2, $hook, $args ); - // the next event should be at +5 minutes, not +3 - $this->assertEquals( $ts2, wp_next_scheduled($hook, $args) ); + // the next event should be at +3 minutes, even though that one was scheduled second + $this->assertEquals( $ts2, wp_next_scheduled( $hook, $args ) ); wp_unschedule_event( $ts2, $hook, $args ); + // following event at +30 minutes should be there too + $this->assertEquals( $ts1, wp_next_scheduled( $hook, $args ) ); + } + + function test_not_duplicate_event_reversed() { + // duplicate events far apart should work normally regardless of order + $hook = rand_str(); + $args = array( rand_str() ); + $ts1 = strtotime( '+3 minutes' ); + $ts2 = strtotime( '+30 minutes' ); + + // first one works + wp_schedule_single_event( $ts1, $hook, $args ); + // second works too + wp_schedule_single_event( $ts2, $hook, $args ); + + // the next event should be at +3 minutes + $this->assertEquals( $ts1, wp_next_scheduled( $hook, $args ) ); + wp_unschedule_event( $ts1, $hook, $args ); // following event should be there too - $this->assertEquals( $ts1, wp_next_scheduled($hook, $args) ); + $this->assertEquals( $ts2, wp_next_scheduled( $hook, $args ) ); } }