wp/wp-includes/cron.php
changeset 18 be944660c56a
parent 16 a86126ab1dd4
child 19 3d72ae0968f4
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
    21  * Use wp_schedule_event() to schedule a recurring event.
    21  * Use wp_schedule_event() to schedule a recurring event.
    22  *
    22  *
    23  * @since 2.1.0
    23  * @since 2.1.0
    24  * @since 5.1.0 Return value modified to boolean indicating success or failure,
    24  * @since 5.1.0 Return value modified to boolean indicating success or failure,
    25  *              {@see 'pre_schedule_event'} filter added to short-circuit the function.
    25  *              {@see 'pre_schedule_event'} filter added to short-circuit the function.
       
    26  * @since 5.7.0 The `$wp_error` parameter was added.
    26  *
    27  *
    27  * @link https://developer.wordpress.org/reference/functions/wp_schedule_single_event/
    28  * @link https://developer.wordpress.org/reference/functions/wp_schedule_single_event/
    28  *
    29  *
    29  * @param int    $timestamp  Unix timestamp (UTC) for when to next run the event.
    30  * @param int    $timestamp  Unix timestamp (UTC) for when to next run the event.
    30  * @param string $hook       Action hook to execute when the event is run.
    31  * @param string $hook       Action hook to execute when the event is run.
    31  * @param array  $args       Optional. Array containing each separate argument to pass to the hook's callback function.
    32  * @param array  $args       Optional. Array containing arguments to pass to the
    32  * @return bool True if event successfully scheduled. False for failure.
    33  *                           hook's callback function. Each value in the array
    33  */
    34  *                           is passed to the callback as an individual parameter.
    34 function wp_schedule_single_event( $timestamp, $hook, $args = array() ) {
    35  *                           The array keys are ignored. Default empty 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  */
       
    39 function wp_schedule_single_event( $timestamp, $hook, $args = array(), $wp_error = false ) {
    35 	// Make sure timestamp is a positive integer.
    40 	// Make sure timestamp is a positive integer.
    36 	if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
    41 	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 
    37 		return false;
    49 		return false;
    38 	}
    50 	}
    39 
    51 
    40 	$event = (object) array(
    52 	$event = (object) array(
    41 		'hook'      => $hook,
    53 		'hook'      => $hook,
    57 	 *
    69 	 *
    58 	 * For plugins replacing wp-cron, it is recommended you check for an
    70 	 * For plugins replacing wp-cron, it is recommended you check for an
    59 	 * identical event within ten minutes and apply the {@see 'schedule_event'}
    71 	 * identical event within ten minutes and apply the {@see 'schedule_event'}
    60 	 * filter to check if another plugin has disallowed the event before scheduling.
    72 	 * filter to check if another plugin has disallowed the event before scheduling.
    61 	 *
    73 	 *
    62 	 * 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.
    63 	 *
    75 	 *
    64 	 * @since 5.1.0
    76 	 * @since 5.1.0
    65 	 *
    77 	 * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
    66 	 * @param null|bool $pre   Value to return instead. Default null to continue adding the event.
    78 	 *
    67 	 * @param stdClass  $event {
    79 	 * @param null|bool|WP_Error $pre      Value to return instead. Default null to continue adding the event.
       
    80 	 * @param stdClass           $event    {
    68 	 *     An object containing an event's data.
    81 	 *     An object containing an event's data.
    69 	 *
    82 	 *
    70 	 *     @type string       $hook      Action hook to execute when the event is run.
    83 	 *     @type string       $hook      Action hook to execute when the event is run.
    71 	 *     @type int          $timestamp Unix timestamp (UTC) for when to next run the event.
    84 	 *     @type int          $timestamp Unix timestamp (UTC) for when to next run the event.
    72 	 *     @type string|false $schedule  How often the event should subsequently recur.
    85 	 *     @type string|false $schedule  How often the event should subsequently recur.
    73 	 *     @type array        $args      Array containing each separate argument to pass to the hook's callback function.
    86 	 *     @type array        $args      Array containing each separate argument to pass to the hook's callback function.
    74 	 *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
    87 	 *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
    75 	 * }
    88 	 * }
    76 	 */
    89 	 * @param bool               $wp_error Whether to return a WP_Error on failure.
    77 	$pre = apply_filters( 'pre_schedule_event', null, $event );
    90 	 */
       
    91 	$pre = apply_filters( 'pre_schedule_event', null, $event, $wp_error );
       
    92 
    78 	if ( null !== $pre ) {
    93 	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 
    79 		return $pre;
   105 		return $pre;
    80 	}
   106 	}
    81 
   107 
    82 	/*
   108 	/*
    83 	 * Check for a duplicated event.
   109 	 * Check for a duplicated event.
   120 			break;
   146 			break;
   121 		}
   147 		}
   122 	}
   148 	}
   123 
   149 
   124 	if ( $duplicate ) {
   150 	if ( $duplicate ) {
       
   151 		if ( $wp_error ) {
       
   152 			return new WP_Error(
       
   153 				'duplicate_event',
       
   154 				__( 'A duplicate event already exists.' )
       
   155 			);
       
   156 		}
       
   157 
   125 		return false;
   158 		return false;
   126 	}
   159 	}
   127 
   160 
   128 	/**
   161 	/**
   129 	 * Modify an event before it is scheduled.
   162 	 * Modify an event before it is scheduled.
   142 	 */
   175 	 */
   143 	$event = apply_filters( 'schedule_event', $event );
   176 	$event = apply_filters( 'schedule_event', $event );
   144 
   177 
   145 	// A plugin disallowed this event.
   178 	// A plugin disallowed this event.
   146 	if ( ! $event ) {
   179 	if ( ! $event ) {
       
   180 		if ( $wp_error ) {
       
   181 			return new WP_Error(
       
   182 				'schedule_event_false',
       
   183 				__( 'A plugin disallowed this event.' )
       
   184 			);
       
   185 		}
       
   186 
   147 		return false;
   187 		return false;
   148 	}
   188 	}
   149 
   189 
   150 	$crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
   190 	$crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
   151 		'schedule' => $event->schedule,
   191 		'schedule' => $event->schedule,
   152 		'args'     => $event->args,
   192 		'args'     => $event->args,
   153 	);
   193 	);
   154 	uksort( $crons, 'strnatcasecmp' );
   194 	uksort( $crons, 'strnatcasecmp' );
   155 	return _set_cron_array( $crons );
   195 
       
   196 	return _set_cron_array( $crons, $wp_error );
   156 }
   197 }
   157 
   198 
   158 /**
   199 /**
   159  * Schedules a recurring event.
   200  * Schedules a recurring event.
   160  *
   201  *
   174  * Use wp_schedule_single_event() to schedule a non-recurring event.
   215  * Use wp_schedule_single_event() to schedule a non-recurring event.
   175  *
   216  *
   176  * @since 2.1.0
   217  * @since 2.1.0
   177  * @since 5.1.0 Return value modified to boolean indicating success or failure,
   218  * @since 5.1.0 Return value modified to boolean indicating success or failure,
   178  *              {@see 'pre_schedule_event'} filter added to short-circuit the function.
   219  *              {@see 'pre_schedule_event'} filter added to short-circuit the function.
       
   220  * @since 5.7.0 The `$wp_error` parameter was added.
   179  *
   221  *
   180  * @link https://developer.wordpress.org/reference/functions/wp_schedule_event/
   222  * @link https://developer.wordpress.org/reference/functions/wp_schedule_event/
   181  *
   223  *
   182  * @param int    $timestamp  Unix timestamp (UTC) for when to next run the event.
   224  * @param int    $timestamp  Unix timestamp (UTC) for when to next run the event.
   183  * @param string $recurrence How often the event should subsequently recur. See wp_get_schedules() for accepted values.
   225  * @param string $recurrence How often the event should subsequently recur.
       
   226  *                           See wp_get_schedules() for accepted values.
   184  * @param string $hook       Action hook to execute when the event is run.
   227  * @param string $hook       Action hook to execute when the event is run.
   185  * @param array  $args       Optional. Array containing each separate argument to pass to the hook's callback function.
   228  * @param array  $args       Optional. Array containing arguments to pass to the
   186  * @return bool True if event successfully scheduled. False for failure.
   229  *                           hook's callback function. Each value in the array
   187  */
   230  *                           is passed to the callback as an individual parameter.
   188 function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array() ) {
   231  *                           The array keys are ignored. Default empty 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  */
       
   235 function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array(), $wp_error = false ) {
   189 	// Make sure timestamp is a positive integer.
   236 	// Make sure timestamp is a positive integer.
   190 	if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
   237 	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 
   191 		return false;
   245 		return false;
   192 	}
   246 	}
   193 
   247 
   194 	$schedules = wp_get_schedules();
   248 	$schedules = wp_get_schedules();
   195 
   249 
   196 	if ( ! isset( $schedules[ $recurrence ] ) ) {
   250 	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 
   197 		return false;
   258 		return false;
   198 	}
   259 	}
   199 
   260 
   200 	$event = (object) array(
   261 	$event = (object) array(
   201 		'hook'      => $hook,
   262 		'hook'      => $hook,
   204 		'args'      => $args,
   265 		'args'      => $args,
   205 		'interval'  => $schedules[ $recurrence ]['interval'],
   266 		'interval'  => $schedules[ $recurrence ]['interval'],
   206 	);
   267 	);
   207 
   268 
   208 	/** This filter is documented in wp-includes/cron.php */
   269 	/** This filter is documented in wp-includes/cron.php */
   209 	$pre = apply_filters( 'pre_schedule_event', null, $event );
   270 	$pre = apply_filters( 'pre_schedule_event', null, $event, $wp_error );
       
   271 
   210 	if ( null !== $pre ) {
   272 	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 
   211 		return $pre;
   284 		return $pre;
   212 	}
   285 	}
   213 
   286 
   214 	/** This filter is documented in wp-includes/cron.php */
   287 	/** This filter is documented in wp-includes/cron.php */
   215 	$event = apply_filters( 'schedule_event', $event );
   288 	$event = apply_filters( 'schedule_event', $event );
   216 
   289 
   217 	// A plugin disallowed this event.
   290 	// A plugin disallowed this event.
   218 	if ( ! $event ) {
   291 	if ( ! $event ) {
       
   292 		if ( $wp_error ) {
       
   293 			return new WP_Error(
       
   294 				'schedule_event_false',
       
   295 				__( 'A plugin disallowed this event.' )
       
   296 			);
       
   297 		}
       
   298 
   219 		return false;
   299 		return false;
   220 	}
   300 	}
   221 
   301 
   222 	$key = md5( serialize( $event->args ) );
   302 	$key = md5( serialize( $event->args ) );
   223 
   303 
   226 		'schedule' => $event->schedule,
   306 		'schedule' => $event->schedule,
   227 		'args'     => $event->args,
   307 		'args'     => $event->args,
   228 		'interval' => $event->interval,
   308 		'interval' => $event->interval,
   229 	);
   309 	);
   230 	uksort( $crons, 'strnatcasecmp' );
   310 	uksort( $crons, 'strnatcasecmp' );
   231 	return _set_cron_array( $crons );
   311 
       
   312 	return _set_cron_array( $crons, $wp_error );
   232 }
   313 }
   233 
   314 
   234 /**
   315 /**
   235  * Reschedules a recurring event.
   316  * Reschedules a recurring event.
   236  *
   317  *
   241  * change the recurrence frequency.
   322  * change the recurrence frequency.
   242  *
   323  *
   243  * @since 2.1.0
   324  * @since 2.1.0
   244  * @since 5.1.0 Return value modified to boolean indicating success or failure,
   325  * @since 5.1.0 Return value modified to boolean indicating success or failure,
   245  *              {@see 'pre_reschedule_event'} filter added to short-circuit the function.
   326  *              {@see 'pre_reschedule_event'} filter added to short-circuit the function.
       
   327  * @since 5.7.0 The `$wp_error` parameter was added.
   246  *
   328  *
   247  * @param int    $timestamp  Unix timestamp (UTC) for when the event was scheduled.
   329  * @param int    $timestamp  Unix timestamp (UTC) for when the event was scheduled.
   248  * @param string $recurrence How often the event should subsequently recur. See wp_get_schedules() for accepted values.
   330  * @param string $recurrence How often the event should subsequently recur.
       
   331  *                           See wp_get_schedules() for accepted values.
   249  * @param string $hook       Action hook to execute when the event is run.
   332  * @param string $hook       Action hook to execute when the event is run.
   250  * @param array  $args       Optional. Array containing each separate argument to pass to the hook's callback function.
   333  * @param array  $args       Optional. Array containing arguments to pass to the
   251  * @return bool True if event successfully rescheduled. False for failure.
   334  *                           hook's callback function. Each value in the array
   252  */
   335  *                           is passed to the callback as an individual parameter.
   253 function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) {
   336  *                           The array keys are ignored. Default empty 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  */
       
   340 function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array(), $wp_error = false ) {
   254 	// Make sure timestamp is a positive integer.
   341 	// Make sure timestamp is a positive integer.
   255 	if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
   342 	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 
   256 		return false;
   350 		return false;
   257 	}
   351 	}
   258 
   352 
   259 	$schedules = wp_get_schedules();
   353 	$schedules = wp_get_schedules();
   260 	$interval  = 0;
   354 	$interval  = 0;
   288 	 *
   382 	 *
   289 	 * For plugins replacing wp-cron, return true if the event was successfully
   383 	 * For plugins replacing wp-cron, return true if the event was successfully
   290 	 * rescheduled, false if not.
   384 	 * rescheduled, false if not.
   291 	 *
   385 	 *
   292 	 * @since 5.1.0
   386 	 * @since 5.1.0
   293 	 *
   387 	 * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
   294 	 * @param null|bool $pre   Value to return instead. Default null to continue adding the event.
   388 	 *
   295 	 * @param stdClass  $event {
   389 	 * @param null|bool|WP_Error $pre      Value to return instead. Default null to continue adding the event.
       
   390 	 * @param stdClass           $event    {
   296 	 *     An object containing an event's data.
   391 	 *     An object containing an event's data.
   297 	 *
   392 	 *
   298 	 *     @type string       $hook      Action hook to execute when the event is run.
   393 	 *     @type string       $hook      Action hook to execute when the event is run.
   299 	 *     @type int          $timestamp Unix timestamp (UTC) for when to next run the event.
   394 	 *     @type int          $timestamp Unix timestamp (UTC) for when to next run the event.
   300 	 *     @type string|false $schedule  How often the event should subsequently recur.
   395 	 *     @type string|false $schedule  How often the event should subsequently recur.
   301 	 *     @type array        $args      Array containing each separate argument to pass to the hook's callback function.
   396 	 *     @type array        $args      Array containing each separate argument to pass to the hook's callback function.
   302 	 *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
   397 	 *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
   303 	 * }
   398 	 * }
   304 	 */
   399 	 * @param bool               $wp_error Whether to return a WP_Error on failure.
   305 	$pre = apply_filters( 'pre_reschedule_event', null, $event );
   400 	 */
       
   401 	$pre = apply_filters( 'pre_reschedule_event', null, $event, $wp_error );
       
   402 
   306 	if ( null !== $pre ) {
   403 	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 
   307 		return $pre;
   415 		return $pre;
   308 	}
   416 	}
   309 
   417 
   310 	// Now we assume something is wrong and fail to schedule.
   418 	// Now we assume something is wrong and fail to schedule.
   311 	if ( 0 == $interval ) {
   419 	if ( 0 == $interval ) {
       
   420 		if ( $wp_error ) {
       
   421 			return new WP_Error(
       
   422 				'invalid_schedule',
       
   423 				__( 'Event schedule does not exist.' )
       
   424 			);
       
   425 		}
       
   426 
   312 		return false;
   427 		return false;
   313 	}
   428 	}
   314 
   429 
   315 	$now = time();
   430 	$now = time();
   316 
   431 
   318 		$timestamp = $now + $interval;
   433 		$timestamp = $now + $interval;
   319 	} else {
   434 	} else {
   320 		$timestamp = $now + ( $interval - ( ( $now - $timestamp ) % $interval ) );
   435 		$timestamp = $now + ( $interval - ( ( $now - $timestamp ) % $interval ) );
   321 	}
   436 	}
   322 
   437 
   323 	return wp_schedule_event( $timestamp, $recurrence, $hook, $args );
   438 	return wp_schedule_event( $timestamp, $recurrence, $hook, $args, $wp_error );
   324 }
   439 }
   325 
   440 
   326 /**
   441 /**
   327  * Unschedule a previously scheduled event.
   442  * Unschedule a previously scheduled event.
   328  *
   443  *
   330  * identified.
   445  * identified.
   331  *
   446  *
   332  * @since 2.1.0
   447  * @since 2.1.0
   333  * @since 5.1.0 Return value modified to boolean indicating success or failure,
   448  * @since 5.1.0 Return value modified to boolean indicating success or failure,
   334  *              {@see 'pre_unschedule_event'} filter added to short-circuit the function.
   449  *              {@see 'pre_unschedule_event'} filter added to short-circuit the function.
       
   450  * @since 5.7.0 The `$wp_error` parameter was added.
   335  *
   451  *
   336  * @param int    $timestamp Unix timestamp (UTC) of the event.
   452  * @param int    $timestamp Unix timestamp (UTC) of the event.
   337  * @param string $hook      Action hook of the event.
   453  * @param string $hook      Action hook of the event.
   338  * @param array  $args      Optional. Array containing each separate argument to pass to the hook's callback function.
   454  * @param array  $args      Optional. Array containing each separate argument to pass to the hook's callback function.
   339  *                          Although not passed to a callback, these arguments are used to uniquely identify the
   455  *                          Although not passed to a callback, these arguments are used to uniquely identify the
   340  *                          event, so they should be the same as those used when originally scheduling the event.
   456  *                          event, so they should be the same as those used when originally scheduling the event.
   341  * @return bool True if event successfully unscheduled. False for failure.
   457  *                          Default empty array.
   342  */
   458  * @param bool   $wp_error  Optional. Whether to return a WP_Error on failure. Default false.
   343 function wp_unschedule_event( $timestamp, $hook, $args = array() ) {
   459  * @return bool|WP_Error True if event successfully unscheduled. False or WP_Error on failure.
       
   460  */
       
   461 function wp_unschedule_event( $timestamp, $hook, $args = array(), $wp_error = false ) {
   344 	// Make sure timestamp is a positive integer.
   462 	// Make sure timestamp is a positive integer.
   345 	if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
   463 	if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
       
   464 		if ( $wp_error ) {
       
   465 			return new WP_Error(
       
   466 				'invalid_timestamp',
       
   467 				__( 'Event timestamp must be a valid Unix timestamp.' )
       
   468 			);
       
   469 		}
       
   470 
   346 		return false;
   471 		return false;
   347 	}
   472 	}
   348 
   473 
   349 	/**
   474 	/**
   350 	 * Filter to preflight or hijack unscheduling of events.
   475 	 * Filter to preflight or hijack unscheduling of events.
   354 	 *
   479 	 *
   355 	 * For plugins replacing wp-cron, return true if the event was successfully
   480 	 * For plugins replacing wp-cron, return true if the event was successfully
   356 	 * unscheduled, false if not.
   481 	 * unscheduled, false if not.
   357 	 *
   482 	 *
   358 	 * @since 5.1.0
   483 	 * @since 5.1.0
   359 	 *
   484 	 * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
   360 	 * @param null|bool $pre       Value to return instead. Default null to continue unscheduling the event.
   485 	 *
   361 	 * @param int       $timestamp Timestamp for when to run the event.
   486 	 * @param null|bool|WP_Error $pre       Value to return instead. Default null to continue unscheduling the event.
   362 	 * @param string    $hook      Action hook, the execution of which will be unscheduled.
   487 	 * @param int                $timestamp Timestamp for when to run the event.
   363 	 * @param array     $args      Arguments to pass to the hook's callback function.
   488 	 * @param string             $hook      Action hook, the execution of which will be unscheduled.
   364 	 */
   489 	 * @param array              $args      Arguments to pass to the hook's callback function.
   365 	$pre = apply_filters( 'pre_unschedule_event', null, $timestamp, $hook, $args );
   490 	 * @param bool               $wp_error  Whether to return a WP_Error on failure.
       
   491 	 */
       
   492 	$pre = apply_filters( 'pre_unschedule_event', null, $timestamp, $hook, $args, $wp_error );
       
   493 
   366 	if ( null !== $pre ) {
   494 	if ( null !== $pre ) {
       
   495 		if ( $wp_error && false === $pre ) {
       
   496 			return new WP_Error(
       
   497 				'pre_unschedule_event_false',
       
   498 				__( 'A plugin prevented the event from being unscheduled.' )
       
   499 			);
       
   500 		}
       
   501 
       
   502 		if ( ! $wp_error && is_wp_error( $pre ) ) {
       
   503 			return false;
       
   504 		}
       
   505 
   367 		return $pre;
   506 		return $pre;
   368 	}
   507 	}
   369 
   508 
   370 	$crons = _get_cron_array();
   509 	$crons = _get_cron_array();
   371 	$key   = md5( serialize( $args ) );
   510 	$key   = md5( serialize( $args ) );
   374 		unset( $crons[ $timestamp ][ $hook ] );
   513 		unset( $crons[ $timestamp ][ $hook ] );
   375 	}
   514 	}
   376 	if ( empty( $crons[ $timestamp ] ) ) {
   515 	if ( empty( $crons[ $timestamp ] ) ) {
   377 		unset( $crons[ $timestamp ] );
   516 		unset( $crons[ $timestamp ] );
   378 	}
   517 	}
   379 	return _set_cron_array( $crons );
   518 
       
   519 	return _set_cron_array( $crons, $wp_error );
   380 }
   520 }
   381 
   521 
   382 /**
   522 /**
   383  * Unschedules all events attached to the hook with the specified arguments.
   523  * Unschedules all events attached to the hook with the specified arguments.
   384  *
   524  *
   388  * the `===` operator for testing the return value of this function.
   528  * the `===` operator for testing the return value of this function.
   389  *
   529  *
   390  * @since 2.1.0
   530  * @since 2.1.0
   391  * @since 5.1.0 Return value modified to indicate success or failure,
   531  * @since 5.1.0 Return value modified to indicate success or failure,
   392  *              {@see 'pre_clear_scheduled_hook'} filter added to short-circuit the function.
   532  *              {@see 'pre_clear_scheduled_hook'} filter added to short-circuit the function.
   393  *
   533  * @since 5.7.0 The `$wp_error` parameter was added.
   394  * @param string $hook Action hook, the execution of which will be unscheduled.
   534  *
   395  * @param array  $args Optional. Arguments that were to be passed to the hook's callback function.
   535  * @param string $hook     Action hook, the execution of which will be unscheduled.
   396  * @return int|false On success an integer indicating number of events unscheduled (0 indicates no
   536  * @param array  $args     Optional. Array containing each separate argument to pass to the hook's callback function.
   397  *                   events were registered with the hook and arguments combination), false if
   537  *                         Although not passed to a callback, these arguments are used to uniquely identify the
   398  *                   unscheduling one or more events fail.
   538  *                         event, so they should be the same as those used when originally scheduling the event.
   399  */
   539  *                         Default empty array.
   400 function wp_clear_scheduled_hook( $hook, $args = array() ) {
   540  * @param bool   $wp_error Optional. Whether to return a WP_Error on failure. Default false.
       
   541  * @return int|false|WP_Error On success an integer indicating number of events unscheduled (0 indicates no
       
   542  *                            events were registered with the hook and arguments combination), false or WP_Error
       
   543  *                            if unscheduling one or more events fail.
       
   544  */
       
   545 function wp_clear_scheduled_hook( $hook, $args = array(), $wp_error = false ) {
   401 	// Backward compatibility.
   546 	// Backward compatibility.
   402 	// Previously, this function took the arguments as discrete vars rather than an array like the rest of the API.
   547 	// Previously, this function took the arguments as discrete vars rather than an array like the rest of the API.
   403 	if ( ! is_array( $args ) ) {
   548 	if ( ! is_array( $args ) ) {
   404 		_deprecated_argument( __FUNCTION__, '3.0.0', __( 'This argument has changed to an array to match the behavior of the other cron functions.' ) );
   549 		_deprecated_argument( __FUNCTION__, '3.0.0', __( 'This argument has changed to an array to match the behavior of the other cron functions.' ) );
   405 		$args = array_slice( func_get_args(), 1 ); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
   550 		$args     = array_slice( func_get_args(), 1 ); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
       
   551 		$wp_error = false;
   406 	}
   552 	}
   407 
   553 
   408 	/**
   554 	/**
   409 	 * Filter to preflight or hijack clearing a scheduled hook.
   555 	 * Filter to preflight or hijack clearing a scheduled hook.
   410 	 *
   556 	 *
   414 	 * For plugins replacing wp-cron, return the number of events successfully
   560 	 * For plugins replacing wp-cron, return the number of events successfully
   415 	 * unscheduled (zero if no events were registered with the hook) or false
   561 	 * unscheduled (zero if no events were registered with the hook) or false
   416 	 * if unscheduling one or more events fails.
   562 	 * if unscheduling one or more events fails.
   417 	 *
   563 	 *
   418 	 * @since 5.1.0
   564 	 * @since 5.1.0
   419 	 *
   565 	 * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
   420 	 * @param null|int|false $pre  Value to return instead. Default null to continue unscheduling the event.
   566 	 *
   421 	 * @param string         $hook Action hook, the execution of which will be unscheduled.
   567 	 * @param null|int|false|WP_Error $pre      Value to return instead. Default null to continue unscheduling the event.
   422 	 * @param array          $args Arguments to pass to the hook's callback function.
   568 	 * @param string                  $hook     Action hook, the execution of which will be unscheduled.
   423 	 */
   569 	 * @param array                   $args     Arguments to pass to the hook's callback function.
   424 	$pre = apply_filters( 'pre_clear_scheduled_hook', null, $hook, $args );
   570 	 * @param bool                    $wp_error Whether to return a WP_Error on failure.
       
   571 	 */
       
   572 	$pre = apply_filters( 'pre_clear_scheduled_hook', null, $hook, $args, $wp_error );
       
   573 
   425 	if ( null !== $pre ) {
   574 	if ( null !== $pre ) {
       
   575 		if ( $wp_error && false === $pre ) {
       
   576 			return new WP_Error(
       
   577 				'pre_clear_scheduled_hook_false',
       
   578 				__( 'A plugin prevented the hook from being cleared.' )
       
   579 			);
       
   580 		}
       
   581 
       
   582 		if ( ! $wp_error && is_wp_error( $pre ) ) {
       
   583 			return false;
       
   584 		}
       
   585 
   426 		return $pre;
   586 		return $pre;
   427 	}
   587 	}
   428 
   588 
   429 	/*
   589 	/*
   430 	 * This logic duplicates wp_next_scheduled().
   590 	 * This logic duplicates wp_next_scheduled().
   436 		return 0;
   596 		return 0;
   437 	}
   597 	}
   438 
   598 
   439 	$results = array();
   599 	$results = array();
   440 	$key     = md5( serialize( $args ) );
   600 	$key     = md5( serialize( $args ) );
       
   601 
   441 	foreach ( $crons as $timestamp => $cron ) {
   602 	foreach ( $crons as $timestamp => $cron ) {
   442 		if ( isset( $cron[ $hook ][ $key ] ) ) {
   603 		if ( isset( $cron[ $hook ][ $key ] ) ) {
   443 			$results[] = wp_unschedule_event( $timestamp, $hook, $args );
   604 			$results[] = wp_unschedule_event( $timestamp, $hook, $args, true );
   444 		}
   605 		}
   445 	}
   606 	}
   446 	if ( in_array( false, $results, true ) ) {
   607 
   447 		return false;
   608 	$errors = array_filter( $results, 'is_wp_error' );
   448 	}
   609 	$error  = new WP_Error();
       
   610 
       
   611 	if ( $errors ) {
       
   612 		if ( $wp_error ) {
       
   613 			array_walk( $errors, array( $error, 'merge_from' ) );
       
   614 
       
   615 			return $error;
       
   616 		}
       
   617 
       
   618 		return false;
       
   619 	}
       
   620 
   449 	return count( $results );
   621 	return count( $results );
   450 }
   622 }
   451 
   623 
   452 /**
   624 /**
   453  * Unschedules all events attached to the hook.
   625  * Unschedules all events attached to the hook.
   459  * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use
   631  * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use
   460  * the `===` operator for testing the return value of this function.
   632  * the `===` operator for testing the return value of this function.
   461  *
   633  *
   462  * @since 4.9.0
   634  * @since 4.9.0
   463  * @since 5.1.0 Return value added to indicate success or failure.
   635  * @since 5.1.0 Return value added to indicate success or failure.
   464  *
   636  * @since 5.7.0 The `$wp_error` parameter was added.
   465  * @param string $hook Action hook, the execution of which will be unscheduled.
   637  *
   466  * @return int|false On success an integer indicating number of events unscheduled (0 indicates no
   638  * @param string $hook     Action hook, the execution of which will be unscheduled.
   467  *                   events were registered on the hook), false if unscheduling fails.
   639  * @param bool   $wp_error Optional. Whether to return a WP_Error on failure. Default false.
   468  */
   640  * @return int|false|WP_Error On success an integer indicating number of events unscheduled (0 indicates no
   469 function wp_unschedule_hook( $hook ) {
   641  *                            events were registered on the hook), false or WP_Error if unscheduling fails.
       
   642  */
       
   643 function wp_unschedule_hook( $hook, $wp_error = false ) {
   470 	/**
   644 	/**
   471 	 * Filter to preflight or hijack clearing all events attached to the hook.
   645 	 * Filter to preflight or hijack clearing all events attached to the hook.
   472 	 *
   646 	 *
   473 	 * Returning a non-null value will short-circuit the normal unscheduling
   647 	 * Returning a non-null value will short-circuit the normal unscheduling
   474 	 * process, causing the function to return the filtered value instead.
   648 	 * process, causing the function to return the filtered value instead.
   476 	 * For plugins replacing wp-cron, return the number of events successfully
   650 	 * For plugins replacing wp-cron, return the number of events successfully
   477 	 * unscheduled (zero if no events were registered with the hook) or false
   651 	 * unscheduled (zero if no events were registered with the hook) or false
   478 	 * if unscheduling one or more events fails.
   652 	 * if unscheduling one or more events fails.
   479 	 *
   653 	 *
   480 	 * @since 5.1.0
   654 	 * @since 5.1.0
   481 	 *
   655 	 * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
   482 	 * @param null|int|false $pre  Value to return instead. Default null to continue unscheduling the hook.
   656 	 *
   483 	 * @param string         $hook Action hook, the execution of which will be unscheduled.
   657 	 * @param null|int|false|WP_Error $pre      Value to return instead. Default null to continue unscheduling the hook.
   484 	 */
   658 	 * @param string                  $hook     Action hook, the execution of which will be unscheduled.
   485 	$pre = apply_filters( 'pre_unschedule_hook', null, $hook );
   659 	 * @param bool                    $wp_error Whether to return a WP_Error on failure.
       
   660 	 */
       
   661 	$pre = apply_filters( 'pre_unschedule_hook', null, $hook, $wp_error );
       
   662 
   486 	if ( null !== $pre ) {
   663 	if ( null !== $pre ) {
       
   664 		if ( $wp_error && false === $pre ) {
       
   665 			return new WP_Error(
       
   666 				'pre_unschedule_hook_false',
       
   667 				__( 'A plugin prevented the hook from being cleared.' )
       
   668 			);
       
   669 		}
       
   670 
       
   671 		if ( ! $wp_error && is_wp_error( $pre ) ) {
       
   672 			return false;
       
   673 		}
       
   674 
   487 		return $pre;
   675 		return $pre;
   488 	}
   676 	}
   489 
   677 
   490 	$crons = _get_cron_array();
   678 	$crons = _get_cron_array();
   491 	if ( empty( $crons ) ) {
   679 	if ( empty( $crons ) ) {
   509 	 * to update the cron array is required.
   697 	 * to update the cron array is required.
   510 	 */
   698 	 */
   511 	if ( empty( $results ) ) {
   699 	if ( empty( $results ) ) {
   512 		return 0;
   700 		return 0;
   513 	}
   701 	}
   514 	if ( _set_cron_array( $crons ) ) {
   702 
       
   703 	$set = _set_cron_array( $crons, $wp_error );
       
   704 
       
   705 	if ( true === $set ) {
   515 		return array_sum( $results );
   706 		return array_sum( $results );
   516 	}
   707 	}
   517 	return false;
   708 
       
   709 	return $set;
   518 }
   710 }
   519 
   711 
   520 /**
   712 /**
   521  * Retrieve a scheduled event.
   713  * Retrieve a scheduled event.
   522  *
   714  *
   527  *
   719  *
   528  * @param string   $hook      Action hook of the event.
   720  * @param string   $hook      Action hook of the event.
   529  * @param array    $args      Optional. Array containing each separate argument to pass to the hook's callback function.
   721  * @param array    $args      Optional. Array containing each separate argument to pass to the hook's callback function.
   530  *                            Although not passed to a callback, these arguments are used to uniquely identify the
   722  *                            Although not passed to a callback, these arguments are used to uniquely identify the
   531  *                            event, so they should be the same as those used when originally scheduling the event.
   723  *                            event, so they should be the same as those used when originally scheduling the event.
   532  * @param int|null $timestamp Optional. Unix timestamp (UTC) of the event. If not specified, the next scheduled event is returned.
   724  *                            Default empty array.
       
   725  * @param int|null $timestamp Optional. Unix timestamp (UTC) of the event. If not specified, the next scheduled event
       
   726  *                            is returned. Default null.
   533  * @return object|false The event object. False if the event does not exist.
   727  * @return object|false The event object. False if the event does not exist.
   534  */
   728  */
   535 function wp_get_scheduled_event( $hook, $args = array(), $timestamp = null ) {
   729 function wp_get_scheduled_event( $hook, $args = array(), $timestamp = null ) {
   536 	/**
   730 	/**
   537 	 * Filter to preflight or hijack retrieving a scheduled event.
   731 	 * Filter to preflight or hijack retrieving a scheduled event.
   606  *
   800  *
   607  * @param string $hook Action hook of the event.
   801  * @param string $hook Action hook of the event.
   608  * @param array  $args Optional. Array containing each separate argument to pass to the hook's callback function.
   802  * @param array  $args Optional. Array containing each separate argument to pass to the hook's callback function.
   609  *                     Although not passed to a callback, these arguments are used to uniquely identify the
   803  *                     Although not passed to a callback, these arguments are used to uniquely identify the
   610  *                     event, so they should be the same as those used when originally scheduling the event.
   804  *                     event, so they should be the same as those used when originally scheduling the event.
       
   805  *                     Default empty array.
   611  * @return int|false The Unix timestamp of the next time the event will occur. False if the event doesn't exist.
   806  * @return int|false The Unix timestamp of the next time the event will occur. False if the event doesn't exist.
   612  */
   807  */
   613 function wp_next_scheduled( $hook, $args = array() ) {
   808 function wp_next_scheduled( $hook, $args = array() ) {
   614 	$next_event = wp_get_scheduled_event( $hook, $args );
   809 	$next_event = wp_get_scheduled_event( $hook, $args );
   615 	if ( ! $next_event ) {
   810 	if ( ! $next_event ) {
   729 	$result = wp_remote_post( $cron_request['url'], $cron_request['args'] );
   924 	$result = wp_remote_post( $cron_request['url'], $cron_request['args'] );
   730 	return ! is_wp_error( $result );
   925 	return ! is_wp_error( $result );
   731 }
   926 }
   732 
   927 
   733 /**
   928 /**
   734  * Run scheduled callbacks or spawn cron for all scheduled events.
   929  * Register _wp_cron() to run on the {@see 'wp_loaded'} action.
       
   930  *
       
   931  * If the {@see 'wp_loaded'} action has already fired, this function calls
       
   932  * _wp_cron() directly.
   735  *
   933  *
   736  * Warning: This function may return Boolean FALSE, but may also return a non-Boolean
   934  * Warning: This function may return Boolean FALSE, but may also return a non-Boolean
   737  * value which evaluates to FALSE. For information about casting to booleans see the
   935  * value which evaluates to FALSE. For information about casting to booleans see the
   738  * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use
   936  * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use
   739  * the `===` operator for testing the return value of this function.
   937  * the `===` operator for testing the return value of this function.
   740  *
   938  *
   741  * @since 2.1.0
   939  * @since 2.1.0
   742  * @since 5.1.0 Return value added to indicate success or failure.
   940  * @since 5.1.0 Return value added to indicate success or failure.
   743  *
   941  * @since 5.7.0 Functionality moved to _wp_cron() to which this becomes a wrapper.
   744  * @return bool|int On success an integer indicating number of events spawned (0 indicates no
   942  *
   745  *                  events needed to be spawned), false if spawning fails for one or more events.
   943  * @return bool|int|void On success an integer indicating number of events spawned (0 indicates no
       
   944  *                       events needed to be spawned), false if spawning fails for one or more events or
       
   945  *                       void if the function registered _wp_cron() to run on the action.
   746  */
   946  */
   747 function wp_cron() {
   947 function wp_cron() {
       
   948 	if ( did_action( 'wp_loaded' ) ) {
       
   949 		return _wp_cron();
       
   950 	}
       
   951 
       
   952 	add_action( 'wp_loaded', '_wp_cron', 20 );
       
   953 }
       
   954 
       
   955 /**
       
   956  * Run scheduled callbacks or spawn cron for all scheduled events.
       
   957  *
       
   958  * Warning: This function may return Boolean FALSE, but may also return a non-Boolean
       
   959  * value which evaluates to FALSE. For information about casting to booleans see the
       
   960  * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use
       
   961  * the `===` operator for testing the return value of this function.
       
   962  *
       
   963  * @since 5.7.0
       
   964  * @access private
       
   965  *
       
   966  * @return int|false On success an integer indicating number of events spawned (0 indicates no
       
   967  *                   events needed to be spawned), false if spawning fails for one or more events.
       
   968  */
       
   969 function _wp_cron() {
   748 	// Prevent infinite loops caused by lack of wp-cron.php.
   970 	// Prevent infinite loops caused by lack of wp-cron.php.
   749 	if ( strpos( $_SERVER['REQUEST_URI'], '/wp-cron.php' ) !== false || ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) ) {
   971 	if ( strpos( $_SERVER['REQUEST_URI'], '/wp-cron.php' ) !== false || ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) ) {
   750 		return 0;
   972 		return 0;
   751 	}
   973 	}
   752 
   974 
   850  * @since 2.1.0
  1072  * @since 2.1.0
   851  * @since 5.1.0 {@see 'get_schedule'} filter added.
  1073  * @since 5.1.0 {@see 'get_schedule'} filter added.
   852  *
  1074  *
   853  * @param string $hook Action hook to identify the event.
  1075  * @param string $hook Action hook to identify the event.
   854  * @param array  $args Optional. Arguments passed to the event's callback function.
  1076  * @param array  $args Optional. Arguments passed to the event's callback function.
   855  * @return string|false False, if no schedule. Schedule name on success.
  1077  *                     Default empty array.
       
  1078  * @return string|false Schedule name on success, false if no schedule.
   856  */
  1079  */
   857 function wp_get_schedule( $hook, $args = array() ) {
  1080 function wp_get_schedule( $hook, $args = array() ) {
   858 	$schedule = false;
  1081 	$schedule = false;
   859 	$event    = wp_get_scheduled_event( $hook, $args );
  1082 	$event    = wp_get_scheduled_event( $hook, $args );
   860 
  1083 
   861 	if ( $event ) {
  1084 	if ( $event ) {
   862 		$schedule = $event->schedule;
  1085 		$schedule = $event->schedule;
   863 	}
  1086 	}
   864 
  1087 
   865 	/**
  1088 	/**
   866 	 * Filter the schedule for a hook.
  1089 	 * Filters the schedule for a hook.
   867 	 *
  1090 	 *
   868 	 * @since 5.1.0
  1091 	 * @since 5.1.0
   869 	 *
  1092 	 *
   870 	 * @param string|bool $schedule Schedule for the hook. False if not found.
  1093 	 * @param string|false $schedule Schedule for the hook. False if not found.
   871 	 * @param string      $hook     Action hook to execute when cron is run.
  1094 	 * @param string       $hook     Action hook to execute when cron is run.
   872 	 * @param array       $args     Optional. Arguments to pass to the hook's callback function.
  1095 	 * @param array        $args     Arguments to pass to the hook's callback function.
   873 	 */
  1096 	 */
   874 	return apply_filters( 'get_schedule', $schedule, $hook, $args );
  1097 	return apply_filters( 'get_schedule', $schedule, $hook, $args );
   875 }
  1098 }
   876 
  1099 
   877 /**
  1100 /**
   932  * Retrieve cron info array option.
  1155  * Retrieve cron info array option.
   933  *
  1156  *
   934  * @since 2.1.0
  1157  * @since 2.1.0
   935  * @access private
  1158  * @access private
   936  *
  1159  *
   937  * @return array|false CRON info array.
  1160  * @return array|false Cron info array on success, false on failure.
   938  */
  1161  */
   939 function _get_cron_array() {
  1162 function _get_cron_array() {
   940 	$cron = get_option( 'cron' );
  1163 	$cron = get_option( 'cron' );
   941 	if ( ! is_array( $cron ) ) {
  1164 	if ( ! is_array( $cron ) ) {
   942 		return false;
  1165 		return false;
   950 
  1173 
   951 	return $cron;
  1174 	return $cron;
   952 }
  1175 }
   953 
  1176 
   954 /**
  1177 /**
   955  * Updates the CRON option with the new CRON array.
  1178  * Updates the cron option with the new cron array.
   956  *
  1179  *
   957  * @since 2.1.0
  1180  * @since 2.1.0
   958  * @since 5.1.0 Return value modified to outcome of update_option().
  1181  * @since 5.1.0 Return value modified to outcome of update_option().
       
  1182  * @since 5.7.0 The `$wp_error` parameter was added.
   959  *
  1183  *
   960  * @access private
  1184  * @access private
   961  *
  1185  *
   962  * @param array $cron Cron info array from _get_cron_array().
  1186  * @param array $cron     Cron info array from _get_cron_array().
   963  * @return bool True if cron array updated, false on failure.
  1187  * @param bool  $wp_error Optional. Whether to return a WP_Error on failure. Default false.
   964  */
  1188  * @return bool|WP_Error True if cron array updated. False or WP_Error on failure.
   965 function _set_cron_array( $cron ) {
  1189  */
       
  1190 function _set_cron_array( $cron, $wp_error = false ) {
   966 	$cron['version'] = 2;
  1191 	$cron['version'] = 2;
   967 	return update_option( 'cron', $cron );
  1192 	$result          = update_option( 'cron', $cron );
       
  1193 
       
  1194 	if ( $wp_error && ! $result ) {
       
  1195 		return new WP_Error(
       
  1196 			'could_not_set',
       
  1197 			__( 'The cron event list could not be saved.' )
       
  1198 		);
       
  1199 	}
       
  1200 
       
  1201 	return $result;
   968 }
  1202 }
   969 
  1203 
   970 /**
  1204 /**
   971  * Upgrade a Cron info array.
  1205  * Upgrade a Cron info array.
   972  *
  1206  *