WordPress.org

Make WordPress Core

Ticket #45976: 45976.2.diff

File 45976.2.diff, 8.2 KB (added by peterwilsoncc, 5 months ago)
  • src/wp-includes/cron.php

    diff --git a/src/wp-includes/cron.php b/src/wp-includes/cron.php
    index c6bb637092..8437ad4110 100644
    a b function wp_unschedule_hook( $hook ) { 
    481481/**
    482482 * Retrieve a scheduled event.
    483483 *
    484  * Retrieve the full event object for a given event.
     484 * Retrieve the full event object for a given event, if no timestamp is specified the next
     485 * scheduled event is returned.
    485486 *
    486487 * @since 5.1.0
    487488 *
    function wp_unschedule_hook( $hook ) { 
    493494 * @return bool|object The event object. False if the event does not exist.
    494495 */
    495496function wp_get_scheduled_event( $hook, $args = array(), $timestamp = null ) {
    496         if ( ! $timestamp ) {
    497                 // Get the next scheduled event.
    498                 $timestamp = wp_next_scheduled( $hook, $args );
    499         }
    500 
    501497        /**
    502498         * Filter to preflight or hijack retrieving a scheduled event.
    503499         *
    function wp_get_scheduled_event( $hook, $args = array(), $timestamp = null ) { 
    514510         * @param array     $args      Array containing each separate argument to pass to the hook's callback function.
    515511         *                             Although not passed to a callback, these arguments are used to uniquely identify the
    516512         *                             event.
    517          * @param int       $timestamp Unix timestamp (UTC) of the event.
     513         * @param int|null  $timestamp Unix timestamp (UTC) of the event. Null to retrieve next scheduled event.
    518514         */
    519515        $pre = apply_filters( 'pre_get_scheduled_event', null, $hook, $args, $timestamp );
    520516        if ( null !== $pre ) {
    521517                return $pre;
    522518        }
    523519
    524         $crons = _get_cron_array();
    525         $key   = md5( serialize( $args ) );
     520        if ( null !== $timestamp && ! is_numeric( $timestamp ) ) {
     521                return false;
     522        }
    526523
    527         if ( ! $timestamp || ! isset( $crons[ $timestamp ] ) ) {
    528                 // No such event.
     524        $crons = _get_cron_array();
     525        if ( empty( $crons ) ) {
    529526                return false;
    530527        }
    531528
    532         if ( ! isset( $crons[ $timestamp ][ $hook ] ) || ! isset( $crons[ $timestamp ][ $hook ][ $key ] ) ) {
     529        $key = md5( serialize( $args ) );
     530
     531        if ( ! $timestamp ) {
     532                // Get next event.
     533                $next = false;
     534                foreach ( $crons as $timestamp => $cron ) {
     535                        if ( isset( $cron[ $hook ][ $key ] ) ) {
     536                                $next = $timestamp;
     537                                break;
     538                        }
     539                }
     540                if ( ! $next ) {
     541                        return false;
     542                }
     543
     544                $timestamp = $next;
     545        } elseif ( ! isset( $crons[ $timestamp ][ $hook ][ $key ] ) ) {
    533546                return false;
    534547        }
    535548
    function wp_get_scheduled_event( $hook, $args = array(), $timestamp = null ) { 
    551564 * Retrieve the next timestamp for an event.
    552565 *
    553566 * @since 2.1.0
    554  * @since 5.1.0 {@see 'pre_next_scheduled'} and {@see 'next_scheduled'} filters added.
    555567 *
    556568 * @param string $hook Action hook of the event.
    557569 * @param array  $args Optional. Array containing each separate argument to pass to the hook's callback function.
    function wp_get_scheduled_event( $hook, $args = array(), $timestamp = null ) { 
    560572 * @return false|int The Unix timestamp of the next time the event will occur. False if the event doesn't exist.
    561573 */
    562574function wp_next_scheduled( $hook, $args = array() ) {
    563         /**
    564          * Filter to preflight or hijack retrieving the next scheduled event timestamp.
    565          *
    566          * Returning a non-null value will short-circuit the normal retrieval
    567          * process, causing the function to return the filtered value instead.
    568          *
    569          * Pass the timestamp of the next event if it exists, false if not.
    570          *
    571          * @since 5.1.0
    572          *
    573          * @param null|bool $pre       Value to return instead. Default null to continue unscheduling the event.
    574          * @param string    $hook      Action hook of the event.
    575          * @param array     $args      Arguments to pass to the hook's callback function.
    576          */
    577         $pre = apply_filters( 'pre_next_scheduled', null, $hook, $args );
    578         if ( null !== $pre ) {
    579                 return $pre;
    580         }
    581 
    582         $crons = _get_cron_array();
    583         $key   = md5( serialize( $args ) );
    584         $next  = false;
    585 
    586         if ( ! empty( $crons ) ) {
    587                 foreach ( $crons as $timestamp => $cron ) {
    588                         if ( isset( $cron[ $hook ][ $key ] ) ) {
    589                                 $next = $timestamp;
    590                                 break;
    591                         }
    592                 }
     575        $next_event = wp_get_scheduled_event( $hook, $args );
     576        if ( ! $next_event ) {
     577                return false;
    593578        }
    594579
    595         /**
    596          * Filter the next scheduled event timestamp.
    597          *
    598          * @since 5.1.0
    599          *
    600          * @param int|bool $next The UNIX timestamp when the scheduled event will next occur, or false if not found.
    601          * @param string   $hook Action hook to execute when cron is run.
    602          * @param array    $args Arguments to be passed to the callback function. Used for deduplicating events.
    603          */
    604         return apply_filters( 'next_scheduled', $next, $hook, $args );
     580        return $next_event->timestamp;
    605581}
    606582
    607583/**
  • tests/phpunit/tests/cron.php

    diff --git a/tests/phpunit/tests/cron.php b/tests/phpunit/tests/cron.php
    index 8b9878e53c..f4885374db 100644
    a b class Tests_Cron extends WP_UnitTestCase { 
    458458         */
    459459        function test_pre_scheduled_event_hooks() {
    460460                add_filter( 'pre_get_scheduled_event', array( $this, 'filter_pre_scheduled_event_hooks' ) );
    461                 add_filter( 'pre_next_scheduled', array( $this, 'filter_pre_scheduled_event_hooks' ) );
    462461
    463462                $actual  = wp_get_scheduled_event( 'preflight_event', array(), $this->plus_thirty_minutes );
    464463                $actual2 = wp_next_scheduled( 'preflight_event', array() );
    class Tests_Cron extends WP_UnitTestCase { 
    471470                );
    472471
    473472                $this->assertEquals( $expected, $actual );
    474                 $this->assertEquals( $expected, $actual2 );
     473                $this->assertEquals( $expected->timestamp, $actual2 );
    475474        }
    476475
    477476        function filter_pre_scheduled_event_hooks() {
    class Tests_Cron extends WP_UnitTestCase { 
    482481                        'args'      => array(),
    483482                );
    484483        }
     484
     485        /**
     486         * Ensure wp_get_scheduled_event() returns the expected one off events.
     487         *
     488         * When no timestamp is specified, the next event should be returned.
     489         * When a timestamp is specified, a particular event should be returned.
     490         *
     491         * @ticket 45976.
     492         */
     493        function test_get_scheduled_event_singles() {
     494                $hook    = __FUNCTION__;
     495                $args    = array( 'arg1' );
     496                $ts_late = strtotime( '+30 minutes' );
     497                $ts_next = strtotime( '+3 minutes' );
     498
     499                $expected1 = (object) array(
     500                        'hook'      => $hook,
     501                        'timestamp' => $ts_late,
     502                        'schedule'  => false,
     503                        'args'      => $args,
     504                );
     505
     506                $expected2 = (object) array(
     507                        'hook'      => $hook,
     508                        'timestamp' => $ts_next,
     509                        'schedule'  => false,
     510                        'args'      => $args,
     511                );
     512
     513                // Schedule late running event.
     514                wp_schedule_single_event( $ts_late, $hook, $args );
     515                // Schedule next running event.
     516                wp_schedule_single_event( $ts_next, $hook, $args );
     517
     518                // Late running, timestamp specified.
     519                $this->assertEquals( $expected1, wp_get_scheduled_event( $hook, $args, $ts_late ) );
     520
     521                // Next running, timestamp specified.
     522                $this->assertEquals( $expected2, wp_get_scheduled_event( $hook, $args, $ts_next ) );
     523
     524                // Next running, no timestamp specified.
     525                $this->assertEquals( $expected2, wp_get_scheduled_event( $hook, $args ) );
     526        }
     527
     528        /**
     529         * Ensure wp_get_scheduled_event() returns the expected recurring events.
     530         *
     531         * When no timestamp is specified, the next event should be returned.
     532         * When a timestamp is specified, a particular event should be returned.
     533         *
     534         * @ticket 45976.
     535         */
     536        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;
     543
     544                $expected1 = (object) array(
     545                        'hook'      => $hook,
     546                        'timestamp' => $ts_late,
     547                        'schedule'  => $schedule,
     548                        'args'      => $args,
     549                        'interval'  => $interval,
     550                );
     551
     552                $expected2 = (object) array(
     553                        'hook'      => $hook,
     554                        'timestamp' => $ts_next,
     555                        'schedule'  => $schedule,
     556                        'args'      => $args,
     557                        'interval'  => $interval,
     558                );
     559
     560                // Schedule late running event.
     561                wp_schedule_event( $ts_late, $schedule, $hook, $args );
     562                // Schedule next running event.
     563                wp_schedule_event( $ts_next, $schedule, $hook, $args );
     564
     565                // Late running, timestamp specified.
     566                $this->assertEquals( $expected1, wp_get_scheduled_event( $hook, $args, $ts_late ) );
     567
     568                // Next running, timestamp specified.
     569                $this->assertEquals( $expected2, wp_get_scheduled_event( $hook, $args, $ts_next ) );
     570
     571                // Next running, no timestamp specified.
     572                $this->assertEquals( $expected2, wp_get_scheduled_event( $hook, $args ) );
     573        }
    485574}