WordPress.org

Make WordPress Core

Ticket #49693: 49693-alternative.patch

File 49693-alternative.patch, 5.8 KB (added by aidvu, 8 months ago)

Alternative approach with wp_doing_cron() check.

  • src/wp-includes/cron.php

     
    220220        }
    221221
    222222        $key = md5( serialize( $event->args ) );
     223        $crons = (array) _get_cron_array();
     224
     225        // Skip the duplicate check if we're doing cron.
     226        if ( ! wp_doing_cron() ) {
     227                foreach ( $crons as $event_timestamp => $cron ) {
     228                        // Drop if an event with the same hook, args and schedule exists.
     229                        if ( isset( $cron[ $event->hook ][ $key ] ) && $cron[ $event->hook ][ $key ]['schedule'] === $event->schedule ) {
     230                                return false;
     231                        }
     232                }
     233        }
    223234
    224         $crons = _get_cron_array();
    225235        $crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
    226236                'schedule' => $event->schedule,
    227237                'args'     => $event->args,
  • tests/phpunit/tests/cron.php

     
    534534         * @ticket 45976.
    535535         */
    536536        function test_get_scheduled_event_recurring() {
    537                 $hook     = __FUNCTION__;
    538                 $args     = array( 'arg1' );
    539                 $ts_late  = strtotime( '+30 minutes' );
    540                 $ts_next  = strtotime( '+3 minutes' );
    541                 $schedule = 'hourly';
    542                 $interval = HOUR_IN_SECONDS;
     537                $hook         = __FUNCTION__;
     538                $args         = array( 'arg1' );
     539                $ts_late      = strtotime( '+30 minutes' );
     540                $ts_next      = strtotime( '+3 minutes' );
     541                $schedule_one = 'hourly';
     542                $schedule_two = 'daily';
     543                $interval_one = HOUR_IN_SECONDS;
     544                $interval_two = DAY_IN_SECONDS;
    543545
    544546                $expected1 = (object) array(
    545547                        'hook'      => $hook,
    546548                        'timestamp' => $ts_late,
    547                         'schedule'  => $schedule,
     549                        'schedule'  => $schedule_one,
    548550                        'args'      => $args,
    549                         'interval'  => $interval,
     551                        'interval'  => $interval_one,
    550552                );
    551553
    552554                $expected2 = (object) array(
    553555                        'hook'      => $hook,
    554556                        'timestamp' => $ts_next,
    555                         'schedule'  => $schedule,
     557                        'schedule'  => $schedule_two,
    556558                        'args'      => $args,
    557                         'interval'  => $interval,
     559                        'interval'  => $interval_two,
    558560                );
    559561
    560562                // Schedule late running event.
    561                 wp_schedule_event( $ts_late, $schedule, $hook, $args );
     563                wp_schedule_event( $ts_late, $schedule_one, $hook, $args );
    562564                // Schedule next running event.
    563                 wp_schedule_event( $ts_next, $schedule, $hook, $args );
     565                wp_schedule_event( $ts_next, $schedule_two, $hook, $args );
    564566
    565567                // Late running, timestamp specified.
    566568                $this->assertEquals( $expected1, wp_get_scheduled_event( $hook, $args, $ts_late ) );
     
    680682                $this->assertTrue( wp_schedule_single_event( $ts2, $hook, $args ) );
    681683                $this->assertTrue( wp_schedule_single_event( $ts3, $hook, $args ) );
    682684        }
     685
     686        /**
     687         * Recurring events that have the same hook, args and schedule are not allowed.
     688         *
     689         * @ticket 49693
     690         */
     691        function test_duplicate_recurring_event() {
     692                $hook           = __FUNCTION__;
     693                $args           = array( 'arg1' );
     694                $timestamp      = strtotime( '+60 minutes' );
     695                $timestamp_next = strtotime( '+120 minutes' );
     696                $schedule       = 'hourly';
     697
     698                // Schedule recurring event.
     699                $this->assertNotFalse( wp_schedule_event( $timestamp, $schedule, $hook, $args ) );
     700                // Make sure the event is correctly scheduled
     701                $this->assertNotFalse( wp_get_scheduled_event( $hook, $args ) );
     702
     703                $expected = _get_cron_array();
     704
     705                // Scheduling the same recurring event (hook and args), but with different timestamp should fail.
     706                $this->assertFalse( wp_schedule_event( $timestamp_next, $schedule, $hook, $args ) );
     707
     708                // Check cron option is unchanged.
     709                $this->assertEquals( $expected, _get_cron_array() );
     710        }
     711
     712        /**
     713         * Recurring events that have the same hook but different args or schedule are allowed.
     714         *
     715         * @ticket 49693
     716         */
     717        function test_not_duplicate_recurring_event() {
     718                $hook         = __FUNCTION__;
     719                $args_one     = array( 'arg1' );
     720                $args_two     = array( 'arg2' );
     721                $timestamp    = strtotime( '+60 minutes' );
     722                $schedule_one = 'hourly';
     723                $schedule_two = 'daily';
     724
     725                // Schedule recurring event.
     726                $this->assertNotFalse( wp_schedule_event( $timestamp, $schedule_one, $hook, $args_one ) );
     727
     728                // Schedule recurring event as above, but with different schedule is allowed.
     729                $this->assertNotFalse( wp_schedule_event( $timestamp, $schedule_two, $hook, $args_one ) );
     730
     731                // Schedule recurring event as above, but with different args is allowed.
     732                $this->assertNotFalse( wp_schedule_event( $timestamp, $schedule_one, $hook, $args_two ) );
     733        }
     734
     735        /**
     736         * Make sure that rescheduling still works with the duplicate event removal when running CRON.
     737         *
     738         * @ticket 49693
     739         */
     740        function test_reschedule_recurring_event() {
     741                $hook   = __FUNCTION__;
     742                $ts_one = strtotime( '+30 minutes' );
     743
     744                // Pretend CRON is running
     745                add_filter( 'wp_doing_cron', '__return_true' );
     746
     747                // Confirm there's no events.
     748                $this->assertEmpty( _get_cron_array() );
     749
     750                // Add an event.
     751                $this->assertTrue( wp_schedule_event( $ts_one, 'hourly', $hook ) );
     752
     753                // Reschedule it.
     754                $this->assertNotFalse( wp_reschedule_event( $ts_one, 'hourly', $hook ) );
     755
     756                // Make sure the original event is still there.
     757                $this->assertNotFalse( wp_get_scheduled_event( $hook, array(), $ts_one ) );
     758
     759                // Make sure the rescheduled event is also there.
     760                $this->assertEquals( 2, count( _get_cron_array() ) );
     761        }
     762
     763        /**
     764         * Make sure that rescheduling fails if we're not running CRON.
     765         *
     766         * @ticket 49693
     767         */
     768        function test_not_reschedule_recurring_event() {
     769                $hook   = __FUNCTION__;
     770                $ts_one = strtotime( '+30 minutes' );
     771
     772                // Add an event.
     773                $this->assertTrue( wp_schedule_event( $ts_one, 'hourly', $hook ) );
     774                $expected = _get_cron_array();
     775
     776                // Rescheduling it fails because of the duplicate check.
     777                $this->assertFalse( wp_reschedule_event( $ts_one, 'hourly', $hook ) );
     778
     779                // Check cron option is unchanged.
     780                $this->assertEquals( $expected, _get_cron_array() );
     781        }
    683782}