* Schedules an event to run only once.
* Schedules a hook which will be triggered by WordPress at the specified time.
* The action will trigger when someone visits your WordPress site if the scheduled
* Note that scheduling an event to occur within 10 minutes of an existing event
* with the same action hook will be ignored unless you pass unique `$args` values
* for each scheduled event.
* Use wp_next_scheduled() to prevent duplicate events.
* Use wp_schedule_event() to schedule a recurring event.
* @since 5.1.0 Return value modified to boolean indicating success or failure,
* {@see 'pre_schedule_event'} filter added to short-circuit the function.
* @since 5.7.0 The `$wp_error` parameter was added.
* @link https://developer.wordpress.org/reference/functions/wp_schedule_single_event/
* @param int $timestamp Unix timestamp (UTC) for when to next run the event.
* @param string $hook Action hook to execute when the event is run.
* @param array $args Optional. Array containing arguments to pass to the
* hook's callback function. Each value in the array
* is passed to the callback as an individual parameter.
* The array keys are ignored. Default empty array.
* @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false.
* @return bool|WP_Error True if event successfully scheduled. False or WP_Error on failure.
function wp_schedule_single_event( $timestamp, $hook, $args = array(), $wp_error = false ) {
// Make sure timestamp is a positive integer.
if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
__( 'Event timestamp must be a valid Unix timestamp.' )
'timestamp' => $timestamp,
* Filter to preflight or hijack scheduling an event.
* Returning a non-null value will short-circuit adding the event to the
* cron array, causing the function to return the filtered value instead.
* Both single events and recurring events are passed through this filter;
* single events have `$event->schedule` as false, whereas recurring events
* have this set to a recurrence from wp_get_schedules(). Recurring
* events also have the integer recurrence interval set as `$event->interval`.
* For plugins replacing wp-cron, it is recommended you check for an
* identical event within ten minutes and apply the {@see 'schedule_event'}
* filter to check if another plugin has disallowed the event before scheduling.
* Return true if the event was scheduled, false or a WP_Error if not.
* @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
* @param null|bool|WP_Error $pre Value to return instead. Default null to continue adding the event.
* @param stdClass $event {
* An object containing an event's data.
* @type string $hook Action hook to execute when the event is run.
* @type int $timestamp Unix timestamp (UTC) for when to next run the event.
* @type string|false $schedule How often the event should subsequently recur.
* @type array $args Array containing each separate argument to pass to the hook's callback function.
* @type int $interval The interval time in seconds for the schedule. Only present for recurring events.
* @param bool $wp_error Whether to return a WP_Error on failure.
$pre = apply_filters( 'pre_schedule_event', null, $event, $wp_error );
if ( $wp_error && false === $pre ) {
'pre_schedule_event_false',
__( 'A plugin prevented the event from being scheduled.' )
if ( ! $wp_error && is_wp_error( $pre ) ) {
* Check for a duplicated event.
* Don't schedule an event if there's already an identical event
* When scheduling events within ten minutes of the current time,
* all past identical events are considered duplicates.
* When scheduling an event with a past timestamp (ie, before the
* current time) all events scheduled within the next ten minutes
* are considered duplicates.
$crons = (array) _get_cron_array();
$key = md5( serialize( $event->args ) );
if ( $event->timestamp < time() + 10 * MINUTE_IN_SECONDS ) {
$min_timestamp = $event->timestamp - 10 * MINUTE_IN_SECONDS;
if ( $event->timestamp < time() ) {
$max_timestamp = time() + 10 * MINUTE_IN_SECONDS;
$max_timestamp = $event->timestamp + 10 * MINUTE_IN_SECONDS;
foreach ( $crons as $event_timestamp => $cron ) {
if ( $event_timestamp < $min_timestamp ) {
if ( $event_timestamp > $max_timestamp ) {
if ( isset( $cron[ $event->hook ][ $key ] ) ) {
__( 'A duplicate event already exists.' )
* Modify an event before it is scheduled.
* @param stdClass|false $event {
* An object containing an event's data, or boolean false to prevent the event from being scheduled.
* @type string $hook Action hook to execute when the event is run.
* @type int $timestamp Unix timestamp (UTC) for when to next run the event.
* @type string|false $schedule How often the event should subsequently recur.
* @type array $args Array containing each separate argument to pass to the hook's callback function.
* @type int $interval The interval time in seconds for the schedule. Only present for recurring events.
$event = apply_filters( 'schedule_event', $event );
// A plugin disallowed this event.
__( 'A plugin disallowed this event.' )
$crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
'schedule' => $event->schedule,
uksort( $crons, 'strnatcasecmp' );
return _set_cron_array( $crons, $wp_error );
* Schedules a recurring event.
* Schedules a hook which will be triggered by WordPress at the specified interval.
* The action will trigger when someone visits your WordPress site if the scheduled
* Valid values for the recurrence are 'hourly', 'daily', and 'twicedaily'. These can
* be extended using the {@see 'cron_schedules'} filter in wp_get_schedules().
* Note that scheduling an event to occur within 10 minutes of an existing event
* with the same action hook will be ignored unless you pass unique `$args` values
* for each scheduled event.
* Use wp_next_scheduled() to prevent duplicate events.
* Use wp_schedule_single_event() to schedule a non-recurring event.
* @since 5.1.0 Return value modified to boolean indicating success or failure,
* {@see 'pre_schedule_event'} filter added to short-circuit the function.
* @since 5.7.0 The `$wp_error` parameter was added.
* @link https://developer.wordpress.org/reference/functions/wp_schedule_event/
* @param int $timestamp Unix timestamp (UTC) for when to next run the event.
* @param string $recurrence How often the event should subsequently recur.
* See wp_get_schedules() for accepted values.
* @param string $hook Action hook to execute when the event is run.
* @param array $args Optional. Array containing arguments to pass to the
* hook's callback function. Each value in the array
* is passed to the callback as an individual parameter.
* The array keys are ignored. Default empty array.
* @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false.
* @return bool|WP_Error True if event successfully scheduled. False or WP_Error on failure.
function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array(), $wp_error = false ) {
// Make sure timestamp is a positive integer.
if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
__( 'Event timestamp must be a valid Unix timestamp.' )
$schedules = wp_get_schedules();
if ( ! isset( $schedules[ $recurrence ] ) ) {
__( 'Event schedule does not exist.' )
'timestamp' => $timestamp,
'schedule' => $recurrence,
'interval' => $schedules[ $recurrence ]['interval'],
/** This filter is documented in wp-includes/cron.php */
$pre = apply_filters( 'pre_schedule_event', null, $event, $wp_error );
if ( $wp_error && false === $pre ) {
'pre_schedule_event_false',
__( 'A plugin prevented the event from being scheduled.' )
if ( ! $wp_error && is_wp_error( $pre ) ) {
/** This filter is documented in wp-includes/cron.php */
$event = apply_filters( 'schedule_event', $event );
// A plugin disallowed this event.
__( 'A plugin disallowed this event.' )
$key = md5( serialize( $event->args ) );
$crons = _get_cron_array();
$crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
'schedule' => $event->schedule,
'interval' => $event->interval,
uksort( $crons, 'strnatcasecmp' );
return _set_cron_array( $crons, $wp_error );
* Reschedules a recurring event.
* Mainly for internal use, this takes the time stamp of a previously run
* recurring event and reschedules it for its next run.
* To change upcoming scheduled events, use wp_schedule_event() to
* change the recurrence frequency.
* @since 5.1.0 Return value modified to boolean indicating success or failure,
* {@see 'pre_reschedule_event'} filter added to short-circuit the function.
* @since 5.7.0 The `$wp_error` parameter was added.
* @param int $timestamp Unix timestamp (UTC) for when the event was scheduled.
* @param string $recurrence How often the event should subsequently recur.
* See wp_get_schedules() for accepted values.
* @param string $hook Action hook to execute when the event is run.
* @param array $args Optional. Array containing arguments to pass to the
* hook's callback function. Each value in the array
* is passed to the callback as an individual parameter.
* The array keys are ignored. Default empty array.
* @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false.
* @return bool|WP_Error True if event successfully rescheduled. False or WP_Error on failure.
function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array(), $wp_error = false ) {
// Make sure timestamp is a positive integer.
if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
__( 'Event timestamp must be a valid Unix timestamp.' )
$schedules = wp_get_schedules();
// First we try to get the interval from the schedule.
if ( isset( $schedules[ $recurrence ] ) ) {
$interval = $schedules[ $recurrence ]['interval'];
// Now we try to get it from the saved interval in case the schedule disappears.
$scheduled_event = wp_get_scheduled_event( $hook, $args, $timestamp );
if ( $scheduled_event && isset( $scheduled_event->interval ) ) {
$interval = $scheduled_event->interval;
'timestamp' => $timestamp,
'schedule' => $recurrence,
* Filter to preflight or hijack rescheduling of events.
* Returning a non-null value will short-circuit the normal rescheduling
* process, causing the function to return the filtered value instead.
* For plugins replacing wp-cron, return true if the event was successfully
* rescheduled, false if not.
* @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
* @param null|bool|WP_Error $pre Value to return instead. Default null to continue adding the event.
* @param stdClass $event {
* An object containing an event's data.
* @type string $hook Action hook to execute when the event is run.
* @type int $timestamp Unix timestamp (UTC) for when to next run the event.
* @type string|false $schedule How often the event should subsequently recur.
* @type array $args Array containing each separate argument to pass to the hook's callback function.
* @type int $interval The interval time in seconds for the schedule. Only present for recurring events.
* @param bool $wp_error Whether to return a WP_Error on failure.
$pre = apply_filters( 'pre_reschedule_event', null, $event, $wp_error );
if ( $wp_error && false === $pre ) {
'pre_reschedule_event_false',
__( 'A plugin prevented the event from being rescheduled.' )
if ( ! $wp_error && is_wp_error( $pre ) ) {
// Now we assume something is wrong and fail to schedule.
__( 'Event schedule does not exist.' )
if ( $timestamp >= $now ) {
$timestamp = $now + $interval;
$timestamp = $now + ( $interval - ( ( $now - $timestamp ) % $interval ) );
return wp_schedule_event( $timestamp, $recurrence, $hook, $args, $wp_error );
* Unschedule a previously scheduled event.
* The $timestamp and $hook parameters are required so that the event can be
* @since 5.1.0 Return value modified to boolean indicating success or failure,
* {@see 'pre_unschedule_event'} filter added to short-circuit the function.
* @since 5.7.0 The `$wp_error` parameter was added.
* @param int $timestamp Unix timestamp (UTC) of the event.
* @param string $hook Action hook of the event.
* @param array $args Optional. Array containing each separate argument to pass to the hook's callback function.
* Although not passed to a callback, these arguments are used to uniquely identify the
* event, so they should be the same as those used when originally scheduling the event.
* @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false.
* @return bool|WP_Error True if event successfully unscheduled. False or WP_Error on failure.
function wp_unschedule_event( $timestamp, $hook, $args = array(), $wp_error = false ) {
// Make sure timestamp is a positive integer.
if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
__( 'Event timestamp must be a valid Unix timestamp.' )
* Filter to preflight or hijack unscheduling of events.
* Returning a non-null value will short-circuit the normal unscheduling
* process, causing the function to return the filtered value instead.
* For plugins replacing wp-cron, return true if the event was successfully
* unscheduled, false if not.
* @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
* @param null|bool|WP_Error $pre Value to return instead. Default null to continue unscheduling the event.
* @param int $timestamp Timestamp for when to run the event.
* @param string $hook Action hook, the execution of which will be unscheduled.
* @param array $args Arguments to pass to the hook's callback function.
* @param bool $wp_error Whether to return a WP_Error on failure.
$pre = apply_filters( 'pre_unschedule_event', null, $timestamp, $hook, $args, $wp_error );
if ( $wp_error && false === $pre ) {
'pre_unschedule_event_false',
__( 'A plugin prevented the event from being unscheduled.' )