Make WordPress Core

Changeset 50143


Ignore:
Timestamp:
02/02/2021 01:47:46 PM (6 years ago)
Author:
johnbillion
Message:

Cron API: Introduce a $wp_error parameter to functions that write to the cron array.

This allows the functions to return a WP_Error object containing more information in case of a problem, instead of just boolean false.

The various pre_ filters in these functions are also updated so they can return or be passed a WP_Error object.

Fixes #49961

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/cron.php

    r50135 r50143  
    2424 * @since 5.1.0 Return value modified to boolean indicating success or failure,
    2525 *              {@see 'pre_schedule_event'} filter added to short-circuit the function.
     26 * @since 5.7.0 The `$wp_error` parameter was added.
    2627 *
    2728 * @link https://developer.wordpress.org/reference/functions/wp_schedule_single_event/
    … …  
    3334 *                           to the callback as an individual parameter. The array keys
    3435 *                           are ignored. Default: empty array.
    35  * @return bool True if event successfully scheduled. False for failure.
    36  */
    37 function wp_schedule_single_event( $timestamp, $hook, $args = array() ) {
     36 * @param bool   $wp_error   Optional. Whether to return a WP_Error on failure. Default false.
     37 * @return bool|WP_Error True if event successfully scheduled. False or WP_Error on failure.
     38 */
     39function wp_schedule_single_event( $timestamp, $hook, $args = array(), $wp_error = false ) {
    3840        // Make sure timestamp is a positive integer.
    3941        if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
     42                if ( $wp_error ) {
     43                        return new WP_Error(
     44                                'invalid_timestamp',
     45                                __( 'Event timestamp must be a valid Unix timestamp.' )
     46                        );
     47                }
     48
    4049                return false;
    4150        }
    … …  
    6372         * filter to check if another plugin has disallowed the event before scheduling.
    6473         *
    65          * Return true if the event was scheduled, false if not.
     74         * Return true if the event was scheduled, false or a WP_Error if not.
    6675         *
    6776         * @since 5.1.0
    68          *
    69          * @param null|bool $pre   Value to return instead. Default null to continue adding the event.
    70          * @param stdClass  $event {
     77         * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
     78         *
     79         * @param null|bool|WP_Error $pre      Value to return instead. Default null to continue adding the event.
     80         * @param stdClass           $event    {
    7181         *     An object containing an event's data.
    7282         *
    … …  
    7787         *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
    7888         * }
    79          */
    80         $pre = apply_filters( 'pre_schedule_event', null, $event );
     89         * @param bool               $wp_error Whether to return a WP_Error on failure.
     90         */
     91        $pre = apply_filters( 'pre_schedule_event', null, $event, $wp_error );
     92
    8193        if ( null !== $pre ) {
     94                if ( $wp_error && false === $pre ) {
     95                        return new WP_Error(
     96                                'pre_schedule_event_false',
     97                                __( 'A plugin prevented the event from being scheduled.' )
     98                        );
     99                }
     100
     101                if ( ! $wp_error && is_wp_error( $pre ) ) {
     102                        return false;
     103                }
     104
    82105                return $pre;
    83106        }
    … …  
    126149
    127150        if ( $duplicate ) {
     151                if ( $wp_error ) {
     152                        return new WP_Error(
     153                                'duplicate_event',
     154                                __( 'A duplicate event already exists.' )
     155                        );
     156                }
     157
    128158                return false;
    129159        }
    … …  
    148178        // A plugin disallowed this event.
    149179        if ( ! $event ) {
     180                if ( $wp_error ) {
     181                        return new WP_Error(
     182                                'schedule_event_false',
     183                                __( 'A plugin disallowed this event.' )
     184                        );
     185                }
     186
    150187                return false;
    151188        }
    … …  
    156193        );
    157194        uksort( $crons, 'strnatcasecmp' );
    158         return _set_cron_array( $crons );
     195
     196        return _set_cron_array( $crons, $wp_error );
    159197}
    160198
    … …  
    180218 * @since 5.1.0 Return value modified to boolean indicating success or failure,
    181219 *              {@see 'pre_schedule_event'} filter added to short-circuit the function.
     220 * @since 5.7.0 The `$wp_error` parameter was added.
    182221 *
    183222 * @link https://developer.wordpress.org/reference/functions/wp_schedule_event/
    … …  
    191230 *                           to the callback as an individual parameter. The array keys
    192231 *                           are ignored. Default: empty array.
    193  * @return bool True if event successfully scheduled. False for failure.
    194  */
    195 function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array() ) {
     232 * @param bool   $wp_error   Optional. Whether to return a WP_Error on failure. Default false.
     233 * @return bool|WP_Error True if event successfully scheduled. False or WP_Error on failure.
     234 */
     235function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array(), $wp_error = false ) {
    196236        // Make sure timestamp is a positive integer.
    197237        if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
     238                if ( $wp_error ) {
     239                        return new WP_Error(
     240                                'invalid_timestamp',
     241                                __( 'Event timestamp must be a valid Unix timestamp.' )
     242                        );
     243                }
     244
    198245                return false;
    199246        }
    … …  
    202249
    203250        if ( ! isset( $schedules[ $recurrence ] ) ) {
     251                if ( $wp_error ) {
     252                        return new WP_Error(
     253                                'invalid_schedule',
     254                                __( 'Event schedule does not exist.' )
     255                        );
     256                }
     257
    204258                return false;
    205259        }
    … …  
    214268
    215269        /** This filter is documented in wp-includes/cron.php */
    216         $pre = apply_filters( 'pre_schedule_event', null, $event );
     270        $pre = apply_filters( 'pre_schedule_event', null, $event, $wp_error );
     271
    217272        if ( null !== $pre ) {
     273                if ( $wp_error && false === $pre ) {
     274                        return new WP_Error(
     275                                'pre_schedule_event_false',
     276                                __( 'A plugin prevented the event from being scheduled.' )
     277                        );
     278                }
     279
     280                if ( ! $wp_error && is_wp_error( $pre ) ) {
     281                        return false;
     282                }
     283
    218284                return $pre;
    219285        }
    … …  
    224290        // A plugin disallowed this event.
    225291        if ( ! $event ) {
     292                if ( $wp_error ) {
     293                        return new WP_Error(
     294                                'schedule_event_false',
     295                                __( 'A plugin disallowed this event.' )
     296                        );
     297                }
     298
    226299                return false;
    227300        }
    … …  
    236309        );
    237310        uksort( $crons, 'strnatcasecmp' );
    238         return _set_cron_array( $crons );
     311
     312        return _set_cron_array( $crons, $wp_error );
    239313}
    240314
    … …  
    251325 * @since 5.1.0 Return value modified to boolean indicating success or failure,
    252326 *              {@see 'pre_reschedule_event'} filter added to short-circuit the function.
     327 * @since 5.7.0 The `$wp_error` parameter was added.
    253328 *
    254329 * @param int    $timestamp  Unix timestamp (UTC) for when the event was scheduled.
    … …  
    260335 *                           to the callback as an individual parameter. The array keys
    261336 *                           are ignored. Default: empty array.
    262  * @return bool True if event successfully rescheduled. False for failure.
    263  */
    264 function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) {
     337 * @param bool   $wp_error   Optional. Whether to return a WP_Error on failure. Default false.
     338 * @return bool|WP_Error True if event successfully rescheduled. False or WP_Error on failure.
     339 */
     340function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array(), $wp_error = false ) {
    265341        // Make sure timestamp is a positive integer.
    266342        if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
     343                if ( $wp_error ) {
     344                        return new WP_Error(
     345                                'invalid_timestamp',
     346                                __( 'Event timestamp must be a valid Unix timestamp.' )
     347                        );
     348                }
     349
    267350                return false;
    268351        }
    … …  
    302385         *
    303386         * @since 5.1.0
    304          *
    305          * @param null|bool $pre   Value to return instead. Default null to continue adding the event.
    306          * @param stdClass  $event {
     387         * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
     388         *
     389         * @param null|bool|WP_Error $pre      Value to return instead. Default null to continue adding the event.
     390         * @param stdClass           $event    {
    307391         *     An object containing an event's data.
    308392         *
    … …  
    313397         *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
    314398         * }
     399         * @param bool               $wp_error Whether to return a WP_Error on failure.
    315400         */
    316401        $pre = apply_filters( 'pre_reschedule_event', null, $event );
     402
    317403        if ( null !== $pre ) {
     404                if ( $wp_error && false === $pre ) {
     405                        return new WP_Error(
     406                                'pre_reschedule_event_false',
     407                                __( 'A plugin prevented the event from being rescheduled.' )
     408                        );
     409                }
     410
     411                if ( ! $wp_error && is_wp_error( $pre ) ) {
     412                        return false;
     413                }
     414
    318415                return $pre;
    319416        }
    … …  
    321418        // Now we assume something is wrong and fail to schedule.
    322419        if ( 0 == $interval ) {
     420                if ( $wp_error ) {
     421                        return new WP_Error(
     422                                'invalid_schedule',
     423                                __( 'Event schedule does not exist.' )
     424                        );
     425                }
     426
    323427                return false;
    324428        }
    … …  
    332436        }
    333437
    334         return wp_schedule_event( $timestamp, $recurrence, $hook, $args );
     438        return wp_schedule_event( $timestamp, $recurrence, $hook, $args, $wp_error );
    335439}
    336440
    … …  
    344448 * @since 5.1.0 Return value modified to boolean indicating success or failure,
    345449 *              {@see 'pre_unschedule_event'} filter added to short-circuit the function.
     450 * @since 5.7.0 The `$wp_error` parameter was added.
    346451 *
    347452 * @param int    $timestamp Unix timestamp (UTC) of the event.
    … …  
    350455 *                          Although not passed to a callback, these arguments are used to uniquely identify the
    351456 *                          event, so they should be the same as those used when originally scheduling the event.
    352  * @return bool True if event successfully unscheduled. False for failure.
    353  */
    354 function wp_unschedule_event( $timestamp, $hook, $args = array() ) {
     457 * @param bool   $wp_error  Optional. Whether to return a WP_Error on failure. Default false.
     458 * @return bool|WP_Error True if event successfully unscheduled. False or WP_Error on failure.
     459 */
     460function wp_unschedule_event( $timestamp, $hook, $args = array(), $wp_error = false ) {
    355461        // Make sure timestamp is a positive integer.
    356462        if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
     463                if ( $wp_error ) {
     464                        return new WP_Error(
     465                                'invalid_timestamp',
     466                                __( 'Event timestamp must be a valid Unix timestamp.' )
     467                        );
     468                }
     469
    357470                return false;
    358471        }
    … …  
    368481         *
    369482         * @since 5.1.0
    370          *
    371          * @param null|bool $pre       Value to return instead. Default null to continue unscheduling the event.
    372          * @param int       $timestamp Timestamp for when to run the event.
    373          * @param string    $hook      Action hook, the execution of which will be unscheduled.
    374          * @param array     $args      Arguments to pass to the hook's callback function.
    375          */
    376         $pre = apply_filters( 'pre_unschedule_event', null, $timestamp, $hook, $args );
     483         * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
     484         *
     485         * @param null|bool|WP_Error $pre       Value to return instead. Default null to continue unscheduling the event.
     486         * @param int                $timestamp Timestamp for when to run the event.
     487         * @param string             $hook      Action hook, the execution of which will be unscheduled.
     488         * @param array              $args      Arguments to pass to the hook's callback function.
     489         * @param bool               $wp_error  Whether to return a WP_Error on failure.
     490         */
     491        $pre = apply_filters( 'pre_unschedule_event', null, $timestamp, $hook, $args, $wp_error );
     492
    377493        if ( null !== $pre ) {
     494                if ( $wp_error && false === $pre ) {
     495                        return new WP_Error(
     496                                'pre_unschedule_event_false',
     497                                __( 'A plugin prevented the event from being unscheduled.' )
     498                        );
     499                }
     500
     501                if ( ! $wp_error && is_wp_error( $pre ) ) {
     502                        return false;
     503                }
     504
    378505                return $pre;
    379506        }
    … …  
    388515                unset( $crons[ $timestamp ] );
    389516        }
    390         return _set_cron_array( $crons );
     517
     518        return _set_cron_array( $crons, $wp_error );
    391519}
    392520
    … …  
    407535 *                     Although not passed to a callback, these arguments are used to uniquely identify the
    408536 *                     event, so they should be the same as those used when originally scheduling the event.
    409  * @return int|false On success an integer indicating number of events unscheduled (0 indicates no
    410  *                   events were registered with the hook and arguments combination), false if
    411  *                   unscheduling one or more events fail.
    412  */
    413 function wp_clear_scheduled_hook( $hook, $args = array() ) {
     537 * @param bool   $wp_error  Optional. Whether to return a WP_Error on failure. Default false.
     538 * @return int|false|WP_Error On success an integer indicating number of events unscheduled (0 indicates no
     539 *                            events were registered with the hook and arguments combination), false or WP_Error
     540 *                            if unscheduling one or more events fail.
     541 */
     542function wp_clear_scheduled_hook( $hook, $args = array(), $wp_error = false ) {
    414543        // Backward compatibility.
    415544        // Previously, this function took the arguments as discrete vars rather than an array like the rest of the API.
    … …  
    417546                _deprecated_argument( __FUNCTION__, '3.0.0', __( 'This argument has changed to an array to match the behavior of the other cron functions.' ) );
    418547                $args = array_slice( func_get_args(), 1 ); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
     548                $wp_error = false;
    419549        }
    420550
    … …  
    430560         *
    431561         * @since 5.1.0
    432          *
    433          * @param null|int|false $pre  Value to return instead. Default null to continue unscheduling the event.
    434          * @param string         $hook Action hook, the execution of which will be unscheduled.
    435          * @param array          $args Arguments to pass to the hook's callback function.
    436          */
    437         $pre = apply_filters( 'pre_clear_scheduled_hook', null, $hook, $args );
     562         * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
     563         *
     564         * @param null|int|false|WP_Error $pre      Value to return instead. Default null to continue unscheduling the event.
     565         * @param string                  $hook     Action hook, the execution of which will be unscheduled.
     566         * @param array                   $args     Arguments to pass to the hook's callback function.
     567         * @param bool                    $wp_error Whether to return a WP_Error on failure.
     568         */
     569        $pre = apply_filters( 'pre_clear_scheduled_hook', null, $hook, $args, $wp_error );
     570
    438571        if ( null !== $pre ) {
     572                if ( $wp_error && false === $pre ) {
     573                        return new WP_Error(
     574                                'pre_clear_scheduled_hook_false',
     575                                __( 'A plugin prevented the hook from being cleared.' )
     576                        );
     577                }
     578
     579                if ( ! $wp_error && is_wp_error( $pre ) ) {
     580                        return false;
     581                }
     582
    439583                return $pre;
    440584        }
    … …  
    452596        $results = array();
    453597        $key     = md5( serialize( $args ) );
     598
    454599        foreach ( $crons as $timestamp => $cron ) {
    455600                if ( isset( $cron[ $hook ][ $key ] ) ) {
    456                         $results[] = wp_unschedule_event( $timestamp, $hook, $args );
    457                 }
    458         }
    459         if ( in_array( false, $results, true ) ) {
    460                 return false;
    461         }
     601                        $results[] = wp_unschedule_event( $timestamp, $hook, $args, true );
     602                }
     603        }
     604
     605        $errors = array_filter( $results, 'is_wp_error' );
     606        $error  = new WP_Error();
     607
     608        if ( $errors ) {
     609                if ( $wp_error ) {
     610                        array_walk( $errors, array( $error, 'merge_from' ) );
     611
     612                        return $error;
     613                }
     614
     615                return false;
     616        }
     617
    462618        return count( $results );
    463619}
    … …  
    475631 * @since 4.9.0
    476632 * @since 5.1.0 Return value added to indicate success or failure.
    477  *
    478  * @param string $hook Action hook, the execution of which will be unscheduled.
    479  * @return int|false On success an integer indicating number of events unscheduled (0 indicates no
    480  *                   events were registered on the hook), false if unscheduling fails.
    481  */
    482 function wp_unschedule_hook( $hook ) {
     633 * @since 5.7.0 The `$wp_error` parameter was added.
     634 *
     635 * @param string $hook     Action hook, the execution of which will be unscheduled.
     636 * @param bool   $wp_error Optional. Whether to return a WP_Error on failure. Default false.
     637 * @return int|false|WP_Error On success an integer indicating number of events unscheduled (0 indicates no
     638 *                            events were registered on the hook), false or WP_Error if unscheduling fails.
     639 */
     640function wp_unschedule_hook( $hook, $wp_error = false ) {
    483641        /**
    484642         * Filter to preflight or hijack clearing all events attached to the hook.
    … …  
    492650         *
    493651         * @since 5.1.0
    494          *
    495          * @param null|int|false $pre  Value to return instead. Default null to continue unscheduling the hook.
    496          * @param string         $hook Action hook, the execution of which will be unscheduled.
    497          */
    498         $pre = apply_filters( 'pre_unschedule_hook', null, $hook );
     652         * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
     653         *
     654         * @param null|int|false|WP_Error $pre      Value to return instead. Default null to continue unscheduling the hook.
     655         * @param string                  $hook     Action hook, the execution of which will be unscheduled.
     656         * @param bool                    $wp_error Whether to return a WP_Error on failure.
     657         */
     658        $pre = apply_filters( 'pre_unschedule_hook', null, $hook, $wp_error );
     659
    499660        if ( null !== $pre ) {
     661                if ( $wp_error && false === $pre ) {
     662                        return new WP_Error(
     663                                'pre_unschedule_hook_false',
     664                                __( 'A plugin prevented the hook from being cleared.' )
     665                        );
     666                }
     667
     668                if ( ! $wp_error && is_wp_error( $pre ) ) {
     669                        return false;
     670                }
     671
    500672                return $pre;
    501673        }
    … …  
    525697                return 0;
    526698        }
    527         if ( _set_cron_array( $crons ) ) {
     699
     700        $set = _set_cron_array( $crons, $wp_error );
     701
     702        if ( true === $set ) {
    528703                return array_sum( $results );
    529704        }
    530         return false;
     705
     706        return $set;
    531707}
    532708
    … …  
    9931169
    9941170/**
    995  * Updates the CRON option with the new CRON array.
     1171 * Updates the cron option with the new cron array.
    9961172 *
    9971173 * @since 2.1.0
    9981174 * @since 5.1.0 Return value modified to outcome of update_option().
     1175 * @since 5.7.0 The `$wp_error` parameter was added.
    9991176 *
    10001177 * @access private
    10011178 *
    1002  * @param array $cron Cron info array from _get_cron_array().
    1003  * @return bool True if cron array updated, false on failure.
    1004  */
    1005 function _set_cron_array( $cron ) {
     1179 * @param array $cron     Cron info array from _get_cron_array().
     1180 * @param bool  $wp_error Optional. Whether to return a WP_Error on failure. Default false.
     1181 * @return bool|WP_Error True if cron array updated. False or WP_Error on failure.
     1182 */
     1183function _set_cron_array( $cron, $wp_error = false ) {
    10061184        $cron['version'] = 2;
    1007         return update_option( 'cron', $cron );
     1185        $result = update_option( 'cron', $cron );
     1186
     1187        if ( $wp_error && ! $result ) {
     1188                return new WP_Error(
     1189                        'could_not_set',
     1190                        __( 'The cron event list could not be saved.' )
     1191                );
     1192        }
     1193
     1194        return $result;
    10081195}
    10091196
  • trunk/tests/phpunit/tests/cron.php

    r48937 r50143  
    272272                // First one works.
    273273                $this->assertTrue( wp_schedule_single_event( $ts1, $hook, $args ) );
    274                 // Second one is ignored.
     274
     275                // Subsequent ones are ignored.
    275276                $this->assertFalse( wp_schedule_single_event( $ts2, $hook, $args ) );
     277                $subsequent = wp_schedule_single_event( $ts2, $hook, $args, true );
     278                $this->assertWPError( $subsequent );
     279                $this->assertSame( 'duplicate_event', $subsequent->get_error_code() );
    276280
    277281                // The next event should be at +5 minutes, not +3.
    … …  
    618622                // Third event fails.
    619623                $this->assertFalse( wp_schedule_single_event( $ts3, $hook, $args ) );
     624
     625                // Fourth event fails.
     626                $subsequent = wp_schedule_single_event( $ts3, $hook, $args, true );
     627                $this->assertWPError( $subsequent );
     628                $this->assertSame( 'duplicate_event', $subsequent->get_error_code() );
    620629        }
    621630
    … …  
    640649                // Third event fails.
    641650                $this->assertFalse( wp_schedule_single_event( $ts3, $hook, $args ) );
     651
     652                // Fourth event fails.
     653                $subsequent = wp_schedule_single_event( $ts3, $hook, $args, true );
     654                $this->assertWPError( $subsequent );
     655                $this->assertSame( 'duplicate_event', $subsequent->get_error_code() );
     656
    642657        }
    643658
    … …  
    660675                $this->assertFalse( wp_schedule_single_event( $ts2, $hook, $args ) );
    661676                $this->assertFalse( wp_schedule_single_event( $ts3, $hook, $args ) );
     677
     678                $subsequent = wp_schedule_single_event( $ts3, $hook, $args, true );
     679                $this->assertWPError( $subsequent );
     680                $this->assertSame( 'duplicate_event', $subsequent->get_error_code() );
    662681        }
    663682
    … …  
    681700                $this->assertTrue( wp_schedule_single_event( $ts3, $hook, $args ) );
    682701        }
     702
     703        /**
     704         * @ticket 49961
     705         */
     706        public function test_invalid_timestamp_for_event_returns_error() {
     707                $single_event      = wp_schedule_single_event( -50, 'hook', array(), true );
     708                $event             = wp_schedule_event( -50, 'daily', 'hook', array(), true );
     709                $rescheduled_event = wp_reschedule_event( -50, 'daily', 'hook', array(), true );
     710                $unscheduled_event = wp_unschedule_event( -50, 'hook', array(), true );
     711
     712                $this->assertWPError( $single_event );
     713                $this->assertSame( 'invalid_timestamp', $single_event->get_error_code() );
     714
     715                $this->assertWPError( $event );
     716                $this->assertSame( 'invalid_timestamp', $event->get_error_code() );
     717
     718                $this->assertWPError( $rescheduled_event );
     719                $this->assertSame( 'invalid_timestamp', $rescheduled_event->get_error_code() );
     720
     721                $this->assertWPError( $unscheduled_event );
     722                $this->assertSame( 'invalid_timestamp', $unscheduled_event->get_error_code() );
     723        }
     724
     725        /**
     726         * @ticket 49961
     727         */
     728        public function test_invalid_recurrence_for_event_returns_error() {
     729                $event             = wp_schedule_event( time(), 'invalid', 'hook', array(), true );
     730                $rescheduled_event = wp_reschedule_event( time(), 'invalid', 'hook', array(), true );
     731
     732                $this->assertWPError( $event );
     733                $this->assertSame( 'invalid_schedule', $event->get_error_code() );
     734
     735                $this->assertWPError( $rescheduled_event );
     736                $this->assertSame( 'invalid_schedule', $rescheduled_event->get_error_code() );
     737        }
     738
     739        /**
     740         * @ticket 49961
     741         */
     742        public function test_disallowed_event_returns_false_when_wp_error_is_set_to_false() {
     743                add_filter( 'schedule_event', '__return_false' );
     744
     745                $single_event      = wp_schedule_single_event( time(), 'hook', array() );
     746                $event             = wp_schedule_event( time(), 'daily', 'hook', array() );
     747                $rescheduled_event = wp_reschedule_event( time(), 'daily', 'hook', array() );
     748
     749                $this->assertFalse( $single_event );
     750                $this->assertFalse( $event );
     751                $this->assertFalse( $rescheduled_event );
     752        }
     753
     754        /**
     755         * @ticket 49961
     756         */
     757        public function test_disallowed_event_returns_error_when_wp_error_is_set_to_true() {
     758                add_filter( 'schedule_event', '__return_false' );
     759
     760                $single_event      = wp_schedule_single_event( time(), 'hook', array(), true );
     761                $event             = wp_schedule_event( time(), 'daily', 'hook', array(), true );
     762                $rescheduled_event = wp_reschedule_event( time(), 'daily', 'hook', array(), true );
     763
     764                $this->assertWPError( $single_event );
     765                $this->assertSame( 'schedule_event_false', $single_event->get_error_code() );
     766
     767                $this->assertWPError( $event );
     768                $this->assertSame( 'schedule_event_false', $event->get_error_code() );
     769
     770                $this->assertWPError( $rescheduled_event );
     771                $this->assertSame( 'schedule_event_false', $rescheduled_event->get_error_code() );
     772        }
     773
     774        /**
     775         * @ticket 49961
     776         */
     777        public function test_schedule_short_circuit_with_error_returns_false_when_wp_error_is_set_to_false() {
     778                $return_error = function() {
     779                        return new WP_Error(
     780                                'my_error',
     781                                'An error ocurred'
     782                        );
     783                };
     784
     785                // Add filters which return a WP_Error:
     786                add_filter( 'pre_schedule_event', $return_error );
     787                add_filter( 'pre_reschedule_event', $return_error );
     788
     789                // Schedule events without the `$wp_error` parameter:
     790                $single_event      = wp_schedule_single_event( time(), 'hook', array() );
     791                $event             = wp_schedule_event( time(), 'daily', 'hook', array() );
     792                $rescheduled_event = wp_reschedule_event( time(), 'daily', 'hook', array() );
     793
     794                // Ensure boolean false is returned:
     795                $this->assertFalse( $single_event );
     796                $this->assertFalse( $event );
     797                $this->assertFalse( $rescheduled_event );
     798        }
     799
     800        /**
     801         * @ticket 49961
     802         */
     803        public function test_schedule_short_circuit_with_error_returns_error_when_wp_error_is_set_to_true() {
     804                $return_error = function() {
     805                        return new WP_Error(
     806                                'my_error',
     807                                'An error ocurred'
     808                        );
     809                };
     810
     811                // Add filters which return a WP_Error:
     812                add_filter( 'pre_schedule_event', $return_error );
     813                add_filter( 'pre_reschedule_event', $return_error );
     814
     815                // Schedule events with the `$wp_error` parameter:
     816                $single_event      = wp_schedule_single_event( time(), 'hook', array(), true );
     817                $event             = wp_schedule_event( time(), 'daily', 'hook', array(), true );
     818                $rescheduled_event = wp_reschedule_event( time(), 'daily', 'hook', array(), true );
     819
     820                // Ensure the error object is returned:
     821                $this->assertWPError( $single_event );
     822                $this->assertSame( 'my_error', $single_event->get_error_code() );
     823
     824                $this->assertWPError( $event );
     825                $this->assertSame( 'my_error', $event->get_error_code() );
     826
     827                $this->assertWPError( $rescheduled_event );
     828                $this->assertSame( 'my_error', $rescheduled_event->get_error_code() );
     829        }
     830
     831        /**
     832         * @ticket 49961
     833         */
     834        public function test_schedule_short_circuit_with_false_returns_false_when_wp_error_is_set_to_false() {
     835                // Add filters which return false:
     836                add_filter( 'pre_schedule_event', '__return_false' );
     837                add_filter( 'pre_reschedule_event', '__return_false' );
     838
     839                // Schedule events without the `$wp_error` parameter:
     840                $single_event      = wp_schedule_single_event( time(), 'hook', array() );
     841                $event             = wp_schedule_event( time(), 'daily', 'hook', array() );
     842                $rescheduled_event = wp_reschedule_event( time(), 'daily', 'hook', array() );
     843
     844                // Ensure false is returned:
     845                $this->assertFalse( $single_event );
     846                $this->assertFalse( $event );
     847                $this->assertFalse( $rescheduled_event );
     848        }
     849
     850        /**
     851         * @ticket 49961
     852         */
     853        public function test_schedule_short_circuit_with_false_returns_error_when_wp_error_is_set_to_true() {
     854                // Add filters which return false:
     855                add_filter( 'pre_schedule_event', '__return_false' );
     856                add_filter( 'pre_reschedule_event', '__return_false' );
     857
     858                // Schedule events with the `$wp_error` parameter:
     859                $single_event      = wp_schedule_single_event( time(), 'hook', array(), true );
     860                $event             = wp_schedule_event( time(), 'daily', 'hook', array(), true );
     861                $rescheduled_event = wp_reschedule_event( time(), 'daily', 'hook', array(), true );
     862
     863                // Ensure an error object is returned:
     864                $this->assertWPError( $single_event );
     865                $this->assertSame( 'pre_schedule_event_false', $single_event->get_error_code() );
     866
     867                $this->assertWPError( $event );
     868                $this->assertSame( 'pre_schedule_event_false', $event->get_error_code() );
     869
     870                $this->assertWPError( $rescheduled_event );
     871                $this->assertSame( 'pre_reschedule_event_false', $rescheduled_event->get_error_code() );
     872        }
     873
     874        /**
     875         * @ticket 49961
     876         * @expectedDeprecated wp_clear_scheduled_hook
     877         */
     878        public function test_deprecated_argument_usage_of_wp_clear_scheduled_hook() {
     879                add_filter(
     880                        'pre_clear_scheduled_hook',
     881                        function( $pre, $hook, $args, $wp_error ) {
     882                                $this->assertSame( array( 1, 2, 3 ), $args );
     883                                $this->assertFalse( $wp_error );
     884
     885                                return $pre;
     886                        },
     887                        10,
     888                        4
     889                );
     890
     891                $cleared = wp_clear_scheduled_hook( 'hook', 1, 2, 3 );
     892
     893                $this->assertSame( 0, $cleared );
     894        }
     895
     896        /**
     897         * @ticket 49961
     898         */
     899        public function test_clear_scheduled_hook_returns_default_pre_filter_error_when_wp_error_is_set_to_true() {
     900                add_filter( 'pre_unschedule_event', '__return_false' );
     901
     902                wp_schedule_single_event( strtotime( '+1 hour' ), 'test_hook' );
     903                wp_schedule_single_event( strtotime( '+2 hours' ), 'test_hook' );
     904
     905                $cleared = wp_clear_scheduled_hook( 'test_hook', array(), true );
     906
     907                $this->assertWPError( $cleared );
     908                $this->assertSame(
     909                        array(
     910                                'pre_unschedule_event_false',
     911                        ),
     912                        $cleared->get_error_codes()
     913                );
     914                $this->assertCount( 2, $cleared->get_error_messages() );
     915        }
     916
     917        /**
     918         * @ticket 49961
     919         */
     920        public function test_clear_scheduled_hook_returns_custom_pre_filter_error_when_wp_error_is_set_to_true() {
     921                add_filter(
     922                        'pre_unschedule_event',
     923                        function( $pre ) {
     924                                return new WP_Error( 'error_code', 'error message' );
     925                        }
     926                );
     927
     928                wp_schedule_single_event( strtotime( '+1 hour' ), 'test_hook' );
     929                wp_schedule_single_event( strtotime( '+2 hours' ), 'test_hook' );
     930
     931                $cleared = wp_clear_scheduled_hook( 'test_hook', array(), true );
     932
     933                $this->assertWPError( $cleared );
     934                $this->assertSame(
     935                        array(
     936                                'error_code',
     937                        ),
     938                        $cleared->get_error_codes()
     939                );
     940                $this->assertSame(
     941                        array(
     942                                'error message',
     943                                'error message',
     944                        ),
     945                        $cleared->get_error_messages()
     946                );
     947        }
     948
     949        /**
     950         * @ticket 49961
     951         */
     952        public function test_unschedule_short_circuit_with_error_returns_false_when_wp_error_is_set_to_false() {
     953                $return_error = function() {
     954                        return new WP_Error(
     955                                'my_error',
     956                                'An error ocurred'
     957                        );
     958                };
     959
     960                // Add a filter which returns a WP_Error:
     961                add_filter( 'pre_unschedule_hook', $return_error );
     962
     963                // Unschedule a hook without the `$wp_error` parameter:
     964                $result = wp_unschedule_hook( 'hook' );
     965
     966                // Ensure boolean false is returned:
     967                $this->assertFalse( $result );
     968        }
     969
     970        /**
     971         * @ticket 49961
     972         */
     973        public function test_unschedule_short_circuit_with_error_returns_error_when_wp_error_is_set_to_true() {
     974                $return_error = function() {
     975                        return new WP_Error(
     976                                'my_error',
     977                                'An error ocurred'
     978                        );
     979                };
     980
     981                // Add a filter which returns a WP_Error:
     982                add_filter( 'pre_unschedule_hook', $return_error );
     983
     984                // Unschedule a hook with the `$wp_error` parameter:
     985                $result = wp_unschedule_hook( 'hook', true );
     986
     987                // Ensure the error object is returned:
     988                $this->assertWPError( $result );
     989                $this->assertSame( 'my_error', $result->get_error_code() );
     990        }
     991
     992        /**
     993         * @ticket 49961
     994         */
     995        public function test_unschedule_short_circuit_with_false_returns_false_when_wp_error_is_set_to_false() {
     996                // Add a filter which returns false:
     997                add_filter( 'pre_unschedule_hook', '__return_false' );
     998
     999                // Unschedule a hook without the `$wp_error` parameter:
     1000                $result = wp_unschedule_hook( 'hook' );
     1001
     1002                // Ensure false is returned:
     1003                $this->assertFalse( $result );
     1004        }
     1005
     1006        /**
     1007         * @ticket 49961
     1008         */
     1009        public function test_unschedule_short_circuit_with_false_returns_error_when_wp_error_is_set_to_true() {
     1010                // Add a filter which returns false:
     1011                add_filter( 'pre_unschedule_hook', '__return_false' );
     1012
     1013                // Unchedule a hook with the `$wp_error` parameter:
     1014                $result = wp_unschedule_hook( 'hook', true );
     1015
     1016                // Ensure an error object is returned:
     1017                $this->assertWPError( $result );
     1018                $this->assertSame( 'pre_unschedule_hook_false', $result->get_error_code() );
     1019        }
     1020
     1021        /**
     1022         * @ticket 49961
     1023         */
     1024        public function test_cron_array_error_is_returned_when_scheduling_single_event() {
     1025                // Force update_option() to fail by setting the new value to match the existing:
     1026                add_filter(
     1027                        'pre_update_option_cron',
     1028                        function() {
     1029                                return get_option( 'cron' );
     1030                        }
     1031                );
     1032
     1033                // Attempt to schedule a valid event:
     1034                $event = wp_schedule_single_event( time(), 'hook', array(), true );
     1035
     1036                // Ensure an error object is returned:
     1037                $this->assertWPError( $event );
     1038                $this->assertSame( 'could_not_set', $event->get_error_code() );
     1039        }
     1040
     1041        /**
     1042         * @ticket 49961
     1043         */
     1044        public function test_cron_array_error_is_returned_when_scheduling_event() {
     1045                // Force update_option() to fail by setting the new value to match the existing:
     1046                add_filter(
     1047                        'pre_update_option_cron',
     1048                        function() {
     1049                                return get_option( 'cron' );
     1050                        }
     1051                );
     1052
     1053                // Attempt to schedule a valid event:
     1054                $event = wp_schedule_event( time(), 'daily', 'hook', array(), true );
     1055
     1056                // Ensure an error object is returned:
     1057                $this->assertWPError( $event );
     1058                $this->assertSame( 'could_not_set', $event->get_error_code() );
     1059        }
     1060
     1061        /**
     1062         * @ticket 49961
     1063         */
     1064        public function test_cron_array_error_is_returned_when_unscheduling_hook() {
     1065                // Schedule a valid event:
     1066                $event = wp_schedule_event( strtotime( '+1 hour' ), 'daily', 'hook', array(), true );
     1067
     1068                // Force update_option() to fail by setting the new value to match the existing:
     1069                add_filter(
     1070                        'pre_update_option_cron',
     1071                        function() {
     1072                                return get_option( 'cron' );
     1073                        }
     1074                );
     1075
     1076                // Attempt to unschedule the hook:
     1077                $unscheduled = wp_unschedule_hook( 'hook', true );
     1078
     1079                // Ensure an error object is returned:
     1080                $this->assertTrue( $event );
     1081                $this->assertWPError( $unscheduled );
     1082                $this->assertSame( 'could_not_set', $unscheduled->get_error_code() );
     1083        }
     1084
     1085        /**
     1086         * @ticket 49961
     1087         */
     1088        public function test_cron_array_error_is_returned_when_unscheduling_event() {
     1089                // Schedule a valid event:
     1090                $event = wp_schedule_event( strtotime( '+1 hour' ), 'daily', 'hook', array(), true );
     1091
     1092                // Force update_option() to fail by setting the new value to match the existing:
     1093                add_filter(
     1094                        'pre_update_option_cron',
     1095                        function() {
     1096                                return get_option( 'cron' );
     1097                        }
     1098                );
     1099
     1100                // Attempt to unschedule the event:
     1101                $unscheduled = wp_unschedule_event( wp_next_scheduled( 'hook' ), 'hook', array(), true );
     1102
     1103                // Ensure an error object is returned:
     1104                $this->assertTrue( $event );
     1105                $this->assertWPError( $unscheduled );
     1106                $this->assertSame( 'could_not_set', $unscheduled->get_error_code() );
     1107        }
     1108
    6831109}
Note: See TracChangeset for help on using the changeset viewer.