balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

cron.php (40646B)


      1 <?php
      2 /**
      3  * WordPress Cron API
      4  *
      5  * @package WordPress
      6  */
      7 
      8 /**
      9  * Schedules an event to run only once.
     10  *
     11  * Schedules a hook which will be triggered by WordPress at the specified time.
     12  * The action will trigger when someone visits your WordPress site if the scheduled
     13  * time has passed.
     14  *
     15  * Note that scheduling an event to occur within 10 minutes of an existing event
     16  * with the same action hook will be ignored unless you pass unique `$args` values
     17  * for each scheduled event.
     18  *
     19  * Use wp_next_scheduled() to prevent duplicate events.
     20  *
     21  * Use wp_schedule_event() to schedule a recurring event.
     22  *
     23  * @since 2.1.0
     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.
     26  * @since 5.7.0 The `$wp_error` parameter was added.
     27  *
     28  * @link https://developer.wordpress.org/reference/functions/wp_schedule_single_event/
     29  *
     30  * @param int    $timestamp  Unix timestamp (UTC) for when to next run the event.
     31  * @param string $hook       Action hook to execute when the event is run.
     32  * @param array  $args       Optional. Array containing arguments to pass to the
     33  *                           hook's callback function. Each value in the array
     34  *                           is passed to the callback as an individual parameter.
     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 ) {
     40 	// Make sure timestamp is a positive integer.
     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 
     49 		return false;
     50 	}
     51 
     52 	$event = (object) array(
     53 		'hook'      => $hook,
     54 		'timestamp' => $timestamp,
     55 		'schedule'  => false,
     56 		'args'      => $args,
     57 	);
     58 
     59 	/**
     60 	 * Filter to preflight or hijack scheduling an event.
     61 	 *
     62 	 * Returning a non-null value will short-circuit adding the event to the
     63 	 * cron array, causing the function to return the filtered value instead.
     64 	 *
     65 	 * Both single events and recurring events are passed through this filter;
     66 	 * single events have `$event->schedule` as false, whereas recurring events
     67 	 * have this set to a recurrence from wp_get_schedules(). Recurring
     68 	 * events also have the integer recurrence interval set as `$event->interval`.
     69 	 *
     70 	 * For plugins replacing wp-cron, it is recommended you check for an
     71 	 * identical event within ten minutes and apply the {@see 'schedule_event'}
     72 	 * filter to check if another plugin has disallowed the event before scheduling.
     73 	 *
     74 	 * Return true if the event was scheduled, false or a WP_Error if not.
     75 	 *
     76 	 * @since 5.1.0
     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    {
     81 	 *     An object containing an event's data.
     82 	 *
     83 	 *     @type string       $hook      Action hook to execute when the event is run.
     84 	 *     @type int          $timestamp Unix timestamp (UTC) for when to next run the event.
     85 	 *     @type string|false $schedule  How often the event should subsequently recur.
     86 	 *     @type array        $args      Array containing each separate argument to pass to the hook's callback function.
     87 	 *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
     88 	 * }
     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 
     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 
    105 		return $pre;
    106 	}
    107 
    108 	/*
    109 	 * Check for a duplicated event.
    110 	 *
    111 	 * Don't schedule an event if there's already an identical event
    112 	 * within 10 minutes.
    113 	 *
    114 	 * When scheduling events within ten minutes of the current time,
    115 	 * all past identical events are considered duplicates.
    116 	 *
    117 	 * When scheduling an event with a past timestamp (ie, before the
    118 	 * current time) all events scheduled within the next ten minutes
    119 	 * are considered duplicates.
    120 	 */
    121 	$crons     = (array) _get_cron_array();
    122 	$key       = md5( serialize( $event->args ) );
    123 	$duplicate = false;
    124 
    125 	if ( $event->timestamp < time() + 10 * MINUTE_IN_SECONDS ) {
    126 		$min_timestamp = 0;
    127 	} else {
    128 		$min_timestamp = $event->timestamp - 10 * MINUTE_IN_SECONDS;
    129 	}
    130 
    131 	if ( $event->timestamp < time() ) {
    132 		$max_timestamp = time() + 10 * MINUTE_IN_SECONDS;
    133 	} else {
    134 		$max_timestamp = $event->timestamp + 10 * MINUTE_IN_SECONDS;
    135 	}
    136 
    137 	foreach ( $crons as $event_timestamp => $cron ) {
    138 		if ( $event_timestamp < $min_timestamp ) {
    139 			continue;
    140 		}
    141 		if ( $event_timestamp > $max_timestamp ) {
    142 			break;
    143 		}
    144 		if ( isset( $cron[ $event->hook ][ $key ] ) ) {
    145 			$duplicate = true;
    146 			break;
    147 		}
    148 	}
    149 
    150 	if ( $duplicate ) {
    151 		if ( $wp_error ) {
    152 			return new WP_Error(
    153 				'duplicate_event',
    154 				__( 'A duplicate event already exists.' )
    155 			);
    156 		}
    157 
    158 		return false;
    159 	}
    160 
    161 	/**
    162 	 * Modify an event before it is scheduled.
    163 	 *
    164 	 * @since 3.1.0
    165 	 *
    166 	 * @param stdClass|false $event {
    167 	 *     An object containing an event's data, or boolean false to prevent the event from being scheduled.
    168 	 *
    169 	 *     @type string       $hook      Action hook to execute when the event is run.
    170 	 *     @type int          $timestamp Unix timestamp (UTC) for when to next run the event.
    171 	 *     @type string|false $schedule  How often the event should subsequently recur.
    172 	 *     @type array        $args      Array containing each separate argument to pass to the hook's callback function.
    173 	 *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
    174 	 * }
    175 	 */
    176 	$event = apply_filters( 'schedule_event', $event );
    177 
    178 	// A plugin disallowed this 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 
    187 		return false;
    188 	}
    189 
    190 	$crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
    191 		'schedule' => $event->schedule,
    192 		'args'     => $event->args,
    193 	);
    194 	uksort( $crons, 'strnatcasecmp' );
    195 
    196 	return _set_cron_array( $crons, $wp_error );
    197 }
    198 
    199 /**
    200  * Schedules a recurring event.
    201  *
    202  * Schedules a hook which will be triggered by WordPress at the specified interval.
    203  * The action will trigger when someone visits your WordPress site if the scheduled
    204  * time has passed.
    205  *
    206  * Valid values for the recurrence are 'hourly', 'daily', and 'twicedaily'. These can
    207  * be extended using the {@see 'cron_schedules'} filter in wp_get_schedules().
    208  *
    209  * Note that scheduling an event to occur within 10 minutes of an existing event
    210  * with the same action hook will be ignored unless you pass unique `$args` values
    211  * for each scheduled event.
    212  *
    213  * Use wp_next_scheduled() to prevent duplicate events.
    214  *
    215  * Use wp_schedule_single_event() to schedule a non-recurring event.
    216  *
    217  * @since 2.1.0
    218  * @since 5.1.0 Return value modified to boolean indicating success or failure,
    219  *              {@see 'pre_schedule_event'} filter added to short-circuit the function.
    220  * @since 5.7.0 The `$wp_error` parameter was added.
    221  *
    222  * @link https://developer.wordpress.org/reference/functions/wp_schedule_event/
    223  *
    224  * @param int    $timestamp  Unix timestamp (UTC) for when to next run the event.
    225  * @param string $recurrence How often the event should subsequently recur.
    226  *                           See wp_get_schedules() for accepted values.
    227  * @param string $hook       Action hook to execute when the event is run.
    228  * @param array  $args       Optional. Array containing arguments to pass to the
    229  *                           hook's callback function. Each value in the array
    230  *                           is passed to the callback as an individual parameter.
    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 ) {
    236 	// Make sure timestamp is a positive integer.
    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 
    245 		return false;
    246 	}
    247 
    248 	$schedules = wp_get_schedules();
    249 
    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 
    258 		return false;
    259 	}
    260 
    261 	$event = (object) array(
    262 		'hook'      => $hook,
    263 		'timestamp' => $timestamp,
    264 		'schedule'  => $recurrence,
    265 		'args'      => $args,
    266 		'interval'  => $schedules[ $recurrence ]['interval'],
    267 	);
    268 
    269 	/** This filter is documented in wp-includes/cron.php */
    270 	$pre = apply_filters( 'pre_schedule_event', null, $event, $wp_error );
    271 
    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 
    284 		return $pre;
    285 	}
    286 
    287 	/** This filter is documented in wp-includes/cron.php */
    288 	$event = apply_filters( 'schedule_event', $event );
    289 
    290 	// A plugin disallowed this 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 
    299 		return false;
    300 	}
    301 
    302 	$key = md5( serialize( $event->args ) );
    303 
    304 	$crons = _get_cron_array();
    305 	$crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
    306 		'schedule' => $event->schedule,
    307 		'args'     => $event->args,
    308 		'interval' => $event->interval,
    309 	);
    310 	uksort( $crons, 'strnatcasecmp' );
    311 
    312 	return _set_cron_array( $crons, $wp_error );
    313 }
    314 
    315 /**
    316  * Reschedules a recurring event.
    317  *
    318  * Mainly for internal use, this takes the time stamp of a previously run
    319  * recurring event and reschedules it for its next run.
    320  *
    321  * To change upcoming scheduled events, use wp_schedule_event() to
    322  * change the recurrence frequency.
    323  *
    324  * @since 2.1.0
    325  * @since 5.1.0 Return value modified to boolean indicating success or failure,
    326  *              {@see 'pre_reschedule_event'} filter added to short-circuit the function.
    327  * @since 5.7.0 The `$wp_error` parameter was added.
    328  *
    329  * @param int    $timestamp  Unix timestamp (UTC) for when the event was scheduled.
    330  * @param string $recurrence How often the event should subsequently recur.
    331  *                           See wp_get_schedules() for accepted values.
    332  * @param string $hook       Action hook to execute when the event is run.
    333  * @param array  $args       Optional. Array containing arguments to pass to the
    334  *                           hook's callback function. Each value in the array
    335  *                           is passed to the callback as an individual parameter.
    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 ) {
    341 	// Make sure timestamp is a positive integer.
    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 
    350 		return false;
    351 	}
    352 
    353 	$schedules = wp_get_schedules();
    354 	$interval  = 0;
    355 
    356 	// First we try to get the interval from the schedule.
    357 	if ( isset( $schedules[ $recurrence ] ) ) {
    358 		$interval = $schedules[ $recurrence ]['interval'];
    359 	}
    360 
    361 	// Now we try to get it from the saved interval in case the schedule disappears.
    362 	if ( 0 === $interval ) {
    363 		$scheduled_event = wp_get_scheduled_event( $hook, $args, $timestamp );
    364 		if ( $scheduled_event && isset( $scheduled_event->interval ) ) {
    365 			$interval = $scheduled_event->interval;
    366 		}
    367 	}
    368 
    369 	$event = (object) array(
    370 		'hook'      => $hook,
    371 		'timestamp' => $timestamp,
    372 		'schedule'  => $recurrence,
    373 		'args'      => $args,
    374 		'interval'  => $interval,
    375 	);
    376 
    377 	/**
    378 	 * Filter to preflight or hijack rescheduling of events.
    379 	 *
    380 	 * Returning a non-null value will short-circuit the normal rescheduling
    381 	 * process, causing the function to return the filtered value instead.
    382 	 *
    383 	 * For plugins replacing wp-cron, return true if the event was successfully
    384 	 * rescheduled, false if not.
    385 	 *
    386 	 * @since 5.1.0
    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    {
    391 	 *     An object containing an event's data.
    392 	 *
    393 	 *     @type string       $hook      Action hook to execute when the event is run.
    394 	 *     @type int          $timestamp Unix timestamp (UTC) for when to next run the event.
    395 	 *     @type string|false $schedule  How often the event should subsequently recur.
    396 	 *     @type array        $args      Array containing each separate argument to pass to the hook's callback function.
    397 	 *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
    398 	 * }
    399 	 * @param bool               $wp_error Whether to return a WP_Error on failure.
    400 	 */
    401 	$pre = apply_filters( 'pre_reschedule_event', null, $event, $wp_error );
    402 
    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 
    415 		return $pre;
    416 	}
    417 
    418 	// Now we assume something is wrong and fail to schedule.
    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 
    427 		return false;
    428 	}
    429 
    430 	$now = time();
    431 
    432 	if ( $timestamp >= $now ) {
    433 		$timestamp = $now + $interval;
    434 	} else {
    435 		$timestamp = $now + ( $interval - ( ( $now - $timestamp ) % $interval ) );
    436 	}
    437 
    438 	return wp_schedule_event( $timestamp, $recurrence, $hook, $args, $wp_error );
    439 }
    440 
    441 /**
    442  * Unschedule a previously scheduled event.
    443  *
    444  * The $timestamp and $hook parameters are required so that the event can be
    445  * identified.
    446  *
    447  * @since 2.1.0
    448  * @since 5.1.0 Return value modified to boolean indicating success or failure,
    449  *              {@see 'pre_unschedule_event'} filter added to short-circuit the function.
    450  * @since 5.7.0 The `$wp_error` parameter was added.
    451  *
    452  * @param int    $timestamp Unix timestamp (UTC) of the event.
    453  * @param string $hook      Action hook of the event.
    454  * @param array  $args      Optional. Array containing each separate argument to pass to the hook's callback function.
    455  *                          Although not passed to a callback, these arguments are used to uniquely identify the
    456  *                          event, so they should be the same as those used when originally scheduling the event.
    457  *                          Default empty array.
    458  * @param bool   $wp_error  Optional. Whether to return a WP_Error on failure. Default false.
    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 ) {
    462 	// Make sure timestamp is a positive integer.
    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 
    471 		return false;
    472 	}
    473 
    474 	/**
    475 	 * Filter to preflight or hijack unscheduling of events.
    476 	 *
    477 	 * Returning a non-null value will short-circuit the normal unscheduling
    478 	 * process, causing the function to return the filtered value instead.
    479 	 *
    480 	 * For plugins replacing wp-cron, return true if the event was successfully
    481 	 * unscheduled, false if not.
    482 	 *
    483 	 * @since 5.1.0
    484 	 * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
    485 	 *
    486 	 * @param null|bool|WP_Error $pre       Value to return instead. Default null to continue unscheduling the event.
    487 	 * @param int                $timestamp Timestamp for when to run the event.
    488 	 * @param string             $hook      Action hook, the execution of which will be unscheduled.
    489 	 * @param array              $args      Arguments to pass to the hook's callback function.
    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 
    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 
    506 		return $pre;
    507 	}
    508 
    509 	$crons = _get_cron_array();
    510 	$key   = md5( serialize( $args ) );
    511 	unset( $crons[ $timestamp ][ $hook ][ $key ] );
    512 	if ( empty( $crons[ $timestamp ][ $hook ] ) ) {
    513 		unset( $crons[ $timestamp ][ $hook ] );
    514 	}
    515 	if ( empty( $crons[ $timestamp ] ) ) {
    516 		unset( $crons[ $timestamp ] );
    517 	}
    518 
    519 	return _set_cron_array( $crons, $wp_error );
    520 }
    521 
    522 /**
    523  * Unschedules all events attached to the hook with the specified arguments.
    524  *
    525  * Warning: This function may return Boolean FALSE, but may also return a non-Boolean
    526  * value which evaluates to FALSE. For information about casting to booleans see the
    527  * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use
    528  * the `===` operator for testing the return value of this function.
    529  *
    530  * @since 2.1.0
    531  * @since 5.1.0 Return value modified to indicate success or failure,
    532  *              {@see 'pre_clear_scheduled_hook'} filter added to short-circuit the function.
    533  * @since 5.7.0 The `$wp_error` parameter was added.
    534  *
    535  * @param string $hook     Action hook, the execution of which will be unscheduled.
    536  * @param array  $args     Optional. Array containing each separate argument to pass to the hook's callback function.
    537  *                         Although not passed to a callback, these arguments are used to uniquely identify the
    538  *                         event, so they should be the same as those used when originally scheduling the event.
    539  *                         Default empty 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 ) {
    546 	// Backward compatibility.
    547 	// Previously, this function took the arguments as discrete vars rather than an array like the rest of the API.
    548 	if ( ! is_array( $args ) ) {
    549 		_deprecated_argument( __FUNCTION__, '3.0.0', __( 'This argument has changed to an array to match the behavior of the other cron functions.' ) );
    550 		$args     = array_slice( func_get_args(), 1 ); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
    551 		$wp_error = false;
    552 	}
    553 
    554 	/**
    555 	 * Filter to preflight or hijack clearing a scheduled hook.
    556 	 *
    557 	 * Returning a non-null value will short-circuit the normal unscheduling
    558 	 * process, causing the function to return the filtered value instead.
    559 	 *
    560 	 * For plugins replacing wp-cron, return the number of events successfully
    561 	 * unscheduled (zero if no events were registered with the hook) or false
    562 	 * if unscheduling one or more events fails.
    563 	 *
    564 	 * @since 5.1.0
    565 	 * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
    566 	 *
    567 	 * @param null|int|false|WP_Error $pre      Value to return instead. Default null to continue unscheduling the event.
    568 	 * @param string                  $hook     Action hook, the execution of which will be unscheduled.
    569 	 * @param array                   $args     Arguments to pass to the hook's callback function.
    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 
    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 
    586 		return $pre;
    587 	}
    588 
    589 	/*
    590 	 * This logic duplicates wp_next_scheduled().
    591 	 * It's required due to a scenario where wp_unschedule_event() fails due to update_option() failing,
    592 	 * and, wp_next_scheduled() returns the same schedule in an infinite loop.
    593 	 */
    594 	$crons = _get_cron_array();
    595 	if ( empty( $crons ) ) {
    596 		return 0;
    597 	}
    598 
    599 	$results = array();
    600 	$key     = md5( serialize( $args ) );
    601 
    602 	foreach ( $crons as $timestamp => $cron ) {
    603 		if ( isset( $cron[ $hook ][ $key ] ) ) {
    604 			$results[] = wp_unschedule_event( $timestamp, $hook, $args, true );
    605 		}
    606 	}
    607 
    608 	$errors = array_filter( $results, 'is_wp_error' );
    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 
    621 	return count( $results );
    622 }
    623 
    624 /**
    625  * Unschedules all events attached to the hook.
    626  *
    627  * Can be useful for plugins when deactivating to clean up the cron queue.
    628  *
    629  * Warning: This function may return Boolean FALSE, but may also return a non-Boolean
    630  * value which evaluates to FALSE. For information about casting to booleans see the
    631  * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use
    632  * the `===` operator for testing the return value of this function.
    633  *
    634  * @since 4.9.0
    635  * @since 5.1.0 Return value added to indicate success or failure.
    636  * @since 5.7.0 The `$wp_error` parameter was added.
    637  *
    638  * @param string $hook     Action hook, the execution of which will be unscheduled.
    639  * @param bool   $wp_error Optional. Whether to return a WP_Error on failure. Default false.
    640  * @return int|false|WP_Error On success an integer indicating number of events unscheduled (0 indicates no
    641  *                            events were registered on the hook), false or WP_Error if unscheduling fails.
    642  */
    643 function wp_unschedule_hook( $hook, $wp_error = false ) {
    644 	/**
    645 	 * Filter to preflight or hijack clearing all events attached to the hook.
    646 	 *
    647 	 * Returning a non-null value will short-circuit the normal unscheduling
    648 	 * process, causing the function to return the filtered value instead.
    649 	 *
    650 	 * For plugins replacing wp-cron, return the number of events successfully
    651 	 * unscheduled (zero if no events were registered with the hook) or false
    652 	 * if unscheduling one or more events fails.
    653 	 *
    654 	 * @since 5.1.0
    655 	 * @since 5.7.0 The `$wp_error` parameter was added, and a `WP_Error` object can now be returned.
    656 	 *
    657 	 * @param null|int|false|WP_Error $pre      Value to return instead. Default null to continue unscheduling the hook.
    658 	 * @param string                  $hook     Action hook, the execution of which will be unscheduled.
    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 
    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 
    675 		return $pre;
    676 	}
    677 
    678 	$crons = _get_cron_array();
    679 	if ( empty( $crons ) ) {
    680 		return 0;
    681 	}
    682 
    683 	$results = array();
    684 	foreach ( $crons as $timestamp => $args ) {
    685 		if ( ! empty( $crons[ $timestamp ][ $hook ] ) ) {
    686 			$results[] = count( $crons[ $timestamp ][ $hook ] );
    687 		}
    688 		unset( $crons[ $timestamp ][ $hook ] );
    689 
    690 		if ( empty( $crons[ $timestamp ] ) ) {
    691 			unset( $crons[ $timestamp ] );
    692 		}
    693 	}
    694 
    695 	/*
    696 	 * If the results are empty (zero events to unschedule), no attempt
    697 	 * to update the cron array is required.
    698 	 */
    699 	if ( empty( $results ) ) {
    700 		return 0;
    701 	}
    702 
    703 	$set = _set_cron_array( $crons, $wp_error );
    704 
    705 	if ( true === $set ) {
    706 		return array_sum( $results );
    707 	}
    708 
    709 	return $set;
    710 }
    711 
    712 /**
    713  * Retrieve a scheduled event.
    714  *
    715  * Retrieve the full event object for a given event, if no timestamp is specified the next
    716  * scheduled event is returned.
    717  *
    718  * @since 5.1.0
    719  *
    720  * @param string   $hook      Action hook of the event.
    721  * @param array    $args      Optional. Array containing each separate argument to pass to the hook's callback function.
    722  *                            Although not passed to a callback, these arguments are used to uniquely identify the
    723  *                            event, so they should be the same as those used when originally scheduling the event.
    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.
    727  * @return object|false The event object. False if the event does not exist.
    728  */
    729 function wp_get_scheduled_event( $hook, $args = array(), $timestamp = null ) {
    730 	/**
    731 	 * Filter to preflight or hijack retrieving a scheduled event.
    732 	 *
    733 	 * Returning a non-null value will short-circuit the normal process,
    734 	 * returning the filtered value instead.
    735 	 *
    736 	 * Return false if the event does not exist, otherwise an event object
    737 	 * should be returned.
    738 	 *
    739 	 * @since 5.1.0
    740 	 *
    741 	 * @param null|false|object $pre  Value to return instead. Default null to continue retrieving the event.
    742 	 * @param string            $hook Action hook of the event.
    743 	 * @param array             $args Array containing each separate argument to pass to the hook's callback function.
    744 	 *                                Although not passed to a callback, these arguments are used to uniquely identify
    745 	 *                                the event.
    746 	 * @param int|null  $timestamp Unix timestamp (UTC) of the event. Null to retrieve next scheduled event.
    747 	 */
    748 	$pre = apply_filters( 'pre_get_scheduled_event', null, $hook, $args, $timestamp );
    749 	if ( null !== $pre ) {
    750 		return $pre;
    751 	}
    752 
    753 	if ( null !== $timestamp && ! is_numeric( $timestamp ) ) {
    754 		return false;
    755 	}
    756 
    757 	$crons = _get_cron_array();
    758 	if ( empty( $crons ) ) {
    759 		return false;
    760 	}
    761 
    762 	$key = md5( serialize( $args ) );
    763 
    764 	if ( ! $timestamp ) {
    765 		// Get next event.
    766 		$next = false;
    767 		foreach ( $crons as $timestamp => $cron ) {
    768 			if ( isset( $cron[ $hook ][ $key ] ) ) {
    769 				$next = $timestamp;
    770 				break;
    771 			}
    772 		}
    773 		if ( ! $next ) {
    774 			return false;
    775 		}
    776 
    777 		$timestamp = $next;
    778 	} elseif ( ! isset( $crons[ $timestamp ][ $hook ][ $key ] ) ) {
    779 		return false;
    780 	}
    781 
    782 	$event = (object) array(
    783 		'hook'      => $hook,
    784 		'timestamp' => $timestamp,
    785 		'schedule'  => $crons[ $timestamp ][ $hook ][ $key ]['schedule'],
    786 		'args'      => $args,
    787 	);
    788 
    789 	if ( isset( $crons[ $timestamp ][ $hook ][ $key ]['interval'] ) ) {
    790 		$event->interval = $crons[ $timestamp ][ $hook ][ $key ]['interval'];
    791 	}
    792 
    793 	return $event;
    794 }
    795 
    796 /**
    797  * Retrieve the next timestamp for an event.
    798  *
    799  * @since 2.1.0
    800  *
    801  * @param string $hook Action hook of the event.
    802  * @param array  $args Optional. Array containing each separate argument to pass to the hook's callback function.
    803  *                     Although not passed to a callback, these arguments are used to uniquely identify the
    804  *                     event, so they should be the same as those used when originally scheduling the event.
    805  *                     Default empty array.
    806  * @return int|false The Unix timestamp of the next time the event will occur. False if the event doesn't exist.
    807  */
    808 function wp_next_scheduled( $hook, $args = array() ) {
    809 	$next_event = wp_get_scheduled_event( $hook, $args );
    810 	if ( ! $next_event ) {
    811 		return false;
    812 	}
    813 
    814 	return $next_event->timestamp;
    815 }
    816 
    817 /**
    818  * Sends a request to run cron through HTTP request that doesn't halt page loading.
    819  *
    820  * @since 2.1.0
    821  * @since 5.1.0 Return values added.
    822  *
    823  * @param int $gmt_time Optional. Unix timestamp (UTC). Default 0 (current time is used).
    824  * @return bool True if spawned, false if no events spawned.
    825  */
    826 function spawn_cron( $gmt_time = 0 ) {
    827 	if ( ! $gmt_time ) {
    828 		$gmt_time = microtime( true );
    829 	}
    830 
    831 	if ( defined( 'DOING_CRON' ) || isset( $_GET['doing_wp_cron'] ) ) {
    832 		return false;
    833 	}
    834 
    835 	/*
    836 	 * Get the cron lock, which is a Unix timestamp of when the last cron was spawned
    837 	 * and has not finished running.
    838 	 *
    839 	 * Multiple processes on multiple web servers can run this code concurrently,
    840 	 * this lock attempts to make spawning as atomic as possible.
    841 	 */
    842 	$lock = get_transient( 'doing_cron' );
    843 
    844 	if ( $lock > $gmt_time + 10 * MINUTE_IN_SECONDS ) {
    845 		$lock = 0;
    846 	}
    847 
    848 	// Don't run if another process is currently running it or more than once every 60 sec.
    849 	if ( $lock + WP_CRON_LOCK_TIMEOUT > $gmt_time ) {
    850 		return false;
    851 	}
    852 
    853 	// Sanity check.
    854 	$crons = wp_get_ready_cron_jobs();
    855 	if ( empty( $crons ) ) {
    856 		return false;
    857 	}
    858 
    859 	$keys = array_keys( $crons );
    860 	if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) {
    861 		return false;
    862 	}
    863 
    864 	if ( defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) {
    865 		if ( 'GET' !== $_SERVER['REQUEST_METHOD'] || defined( 'DOING_AJAX' ) || defined( 'XMLRPC_REQUEST' ) ) {
    866 			return false;
    867 		}
    868 
    869 		$doing_wp_cron = sprintf( '%.22F', $gmt_time );
    870 		set_transient( 'doing_cron', $doing_wp_cron );
    871 
    872 		ob_start();
    873 		wp_redirect( add_query_arg( 'doing_wp_cron', $doing_wp_cron, wp_unslash( $_SERVER['REQUEST_URI'] ) ) );
    874 		echo ' ';
    875 
    876 		// Flush any buffers and send the headers.
    877 		wp_ob_end_flush_all();
    878 		flush();
    879 
    880 		include_once ABSPATH . 'wp-cron.php';
    881 		return true;
    882 	}
    883 
    884 	// Set the cron lock with the current unix timestamp, when the cron is being spawned.
    885 	$doing_wp_cron = sprintf( '%.22F', $gmt_time );
    886 	set_transient( 'doing_cron', $doing_wp_cron );
    887 
    888 	/**
    889 	 * Filters the cron request arguments.
    890 	 *
    891 	 * @since 3.5.0
    892 	 * @since 4.5.0 The `$doing_wp_cron` parameter was added.
    893 	 *
    894 	 * @param array $cron_request_array {
    895 	 *     An array of cron request URL arguments.
    896 	 *
    897 	 *     @type string $url  The cron request URL.
    898 	 *     @type int    $key  The 22 digit GMT microtime.
    899 	 *     @type array  $args {
    900 	 *         An array of cron request arguments.
    901 	 *
    902 	 *         @type int  $timeout   The request timeout in seconds. Default .01 seconds.
    903 	 *         @type bool $blocking  Whether to set blocking for the request. Default false.
    904 	 *         @type bool $sslverify Whether SSL should be verified for the request. Default false.
    905 	 *     }
    906 	 * }
    907 	 * @param string $doing_wp_cron The unix timestamp of the cron lock.
    908 	 */
    909 	$cron_request = apply_filters(
    910 		'cron_request',
    911 		array(
    912 			'url'  => add_query_arg( 'doing_wp_cron', $doing_wp_cron, site_url( 'wp-cron.php' ) ),
    913 			'key'  => $doing_wp_cron,
    914 			'args' => array(
    915 				'timeout'   => 0.01,
    916 				'blocking'  => false,
    917 				/** This filter is documented in wp-includes/class-wp-http-streams.php */
    918 				'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
    919 			),
    920 		),
    921 		$doing_wp_cron
    922 	);
    923 
    924 	$result = wp_remote_post( $cron_request['url'], $cron_request['args'] );
    925 	return ! is_wp_error( $result );
    926 }
    927 
    928 /**
    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.
    933  *
    934  * Warning: This function may return Boolean FALSE, but may also return a non-Boolean
    935  * value which evaluates to FALSE. For information about casting to booleans see the
    936  * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use
    937  * the `===` operator for testing the return value of this function.
    938  *
    939  * @since 2.1.0
    940  * @since 5.1.0 Return value added to indicate success or failure.
    941  * @since 5.7.0 Functionality moved to _wp_cron() to which this becomes a wrapper.
    942  *
    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.
    946  */
    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() {
    970 	// Prevent infinite loops caused by lack of wp-cron.php.
    971 	if ( strpos( $_SERVER['REQUEST_URI'], '/wp-cron.php' ) !== false || ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) ) {
    972 		return 0;
    973 	}
    974 
    975 	$crons = wp_get_ready_cron_jobs();
    976 	if ( empty( $crons ) ) {
    977 		return 0;
    978 	}
    979 
    980 	$gmt_time = microtime( true );
    981 	$keys     = array_keys( $crons );
    982 	if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) {
    983 		return 0;
    984 	}
    985 
    986 	$schedules = wp_get_schedules();
    987 	$results   = array();
    988 	foreach ( $crons as $timestamp => $cronhooks ) {
    989 		if ( $timestamp > $gmt_time ) {
    990 			break;
    991 		}
    992 		foreach ( (array) $cronhooks as $hook => $args ) {
    993 			if ( isset( $schedules[ $hook ]['callback'] ) && ! call_user_func( $schedules[ $hook ]['callback'] ) ) {
    994 				continue;
    995 			}
    996 			$results[] = spawn_cron( $gmt_time );
    997 			break 2;
    998 		}
    999 	}
   1000 
   1001 	if ( in_array( false, $results, true ) ) {
   1002 		return false;
   1003 	}
   1004 	return count( $results );
   1005 }
   1006 
   1007 /**
   1008  * Retrieve supported event recurrence schedules.
   1009  *
   1010  * The default supported recurrences are 'hourly', 'twicedaily', 'daily', and 'weekly'.
   1011  * A plugin may add more by hooking into the {@see 'cron_schedules'} filter.
   1012  * The filter accepts an array of arrays. The outer array has a key that is the name
   1013  * of the schedule, for example 'monthly'. The value is an array with two keys,
   1014  * one is 'interval' and the other is 'display'.
   1015  *
   1016  * The 'interval' is a number in seconds of when the cron job should run.
   1017  * So for 'hourly' the time is `HOUR_IN_SECONDS` (60 * 60 or 3600). For 'monthly',
   1018  * the value would be `MONTH_IN_SECONDS` (30 * 24 * 60 * 60 or 2592000).
   1019  *
   1020  * The 'display' is the description. For the 'monthly' key, the 'display'
   1021  * would be `__( 'Once Monthly' )`.
   1022  *
   1023  * For your plugin, you will be passed an array. You can easily add your
   1024  * schedule by doing the following.
   1025  *
   1026  *     // Filter parameter variable name is 'array'.
   1027  *     $array['monthly'] = array(
   1028  *         'interval' => MONTH_IN_SECONDS,
   1029  *         'display'  => __( 'Once Monthly' )
   1030  *     );
   1031  *
   1032  * @since 2.1.0
   1033  * @since 5.4.0 The 'weekly' schedule was added.
   1034  *
   1035  * @return array
   1036  */
   1037 function wp_get_schedules() {
   1038 	$schedules = array(
   1039 		'hourly'     => array(
   1040 			'interval' => HOUR_IN_SECONDS,
   1041 			'display'  => __( 'Once Hourly' ),
   1042 		),
   1043 		'twicedaily' => array(
   1044 			'interval' => 12 * HOUR_IN_SECONDS,
   1045 			'display'  => __( 'Twice Daily' ),
   1046 		),
   1047 		'daily'      => array(
   1048 			'interval' => DAY_IN_SECONDS,
   1049 			'display'  => __( 'Once Daily' ),
   1050 		),
   1051 		'weekly'     => array(
   1052 			'interval' => WEEK_IN_SECONDS,
   1053 			'display'  => __( 'Once Weekly' ),
   1054 		),
   1055 	);
   1056 
   1057 	/**
   1058 	 * Filters the non-default cron schedules.
   1059 	 *
   1060 	 * @since 2.1.0
   1061 	 *
   1062 	 * @param array $new_schedules An array of non-default cron schedules. Default empty.
   1063 	 */
   1064 	return array_merge( apply_filters( 'cron_schedules', array() ), $schedules );
   1065 }
   1066 
   1067 /**
   1068  * Retrieve the recurrence schedule for an event.
   1069  *
   1070  * @see wp_get_schedules() for available schedules.
   1071  *
   1072  * @since 2.1.0
   1073  * @since 5.1.0 {@see 'get_schedule'} filter added.
   1074  *
   1075  * @param string $hook Action hook to identify the event.
   1076  * @param array  $args Optional. Arguments passed to the event's callback function.
   1077  *                     Default empty array.
   1078  * @return string|false Schedule name on success, false if no schedule.
   1079  */
   1080 function wp_get_schedule( $hook, $args = array() ) {
   1081 	$schedule = false;
   1082 	$event    = wp_get_scheduled_event( $hook, $args );
   1083 
   1084 	if ( $event ) {
   1085 		$schedule = $event->schedule;
   1086 	}
   1087 
   1088 	/**
   1089 	 * Filters the schedule for a hook.
   1090 	 *
   1091 	 * @since 5.1.0
   1092 	 *
   1093 	 * @param string|false $schedule Schedule for the hook. False if not found.
   1094 	 * @param string       $hook     Action hook to execute when cron is run.
   1095 	 * @param array        $args     Arguments to pass to the hook's callback function.
   1096 	 */
   1097 	return apply_filters( 'get_schedule', $schedule, $hook, $args );
   1098 }
   1099 
   1100 /**
   1101  * Retrieve cron jobs ready to be run.
   1102  *
   1103  * Returns the results of _get_cron_array() limited to events ready to be run,
   1104  * ie, with a timestamp in the past.
   1105  *
   1106  * @since 5.1.0
   1107  *
   1108  * @return array Cron jobs ready to be run.
   1109  */
   1110 function wp_get_ready_cron_jobs() {
   1111 	/**
   1112 	 * Filter to preflight or hijack retrieving ready cron jobs.
   1113 	 *
   1114 	 * Returning an array will short-circuit the normal retrieval of ready
   1115 	 * cron jobs, causing the function to return the filtered value instead.
   1116 	 *
   1117 	 * @since 5.1.0
   1118 	 *
   1119 	 * @param null|array $pre Array of ready cron tasks to return instead. Default null
   1120 	 *                        to continue using results from _get_cron_array().
   1121 	 */
   1122 	$pre = apply_filters( 'pre_get_ready_cron_jobs', null );
   1123 	if ( null !== $pre ) {
   1124 		return $pre;
   1125 	}
   1126 
   1127 	$crons = _get_cron_array();
   1128 
   1129 	if ( false === $crons ) {
   1130 		return array();
   1131 	}
   1132 
   1133 	$gmt_time = microtime( true );
   1134 	$keys     = array_keys( $crons );
   1135 	if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) {
   1136 		return array();
   1137 	}
   1138 
   1139 	$results = array();
   1140 	foreach ( $crons as $timestamp => $cronhooks ) {
   1141 		if ( $timestamp > $gmt_time ) {
   1142 			break;
   1143 		}
   1144 		$results[ $timestamp ] = $cronhooks;
   1145 	}
   1146 
   1147 	return $results;
   1148 }
   1149 
   1150 //
   1151 // Private functions.
   1152 //
   1153 
   1154 /**
   1155  * Retrieve cron info array option.
   1156  *
   1157  * @since 2.1.0
   1158  * @access private
   1159  *
   1160  * @return array|false Cron info array on success, false on failure.
   1161  */
   1162 function _get_cron_array() {
   1163 	$cron = get_option( 'cron' );
   1164 	if ( ! is_array( $cron ) ) {
   1165 		return false;
   1166 	}
   1167 
   1168 	if ( ! isset( $cron['version'] ) ) {
   1169 		$cron = _upgrade_cron_array( $cron );
   1170 	}
   1171 
   1172 	unset( $cron['version'] );
   1173 
   1174 	return $cron;
   1175 }
   1176 
   1177 /**
   1178  * Updates the cron option with the new cron array.
   1179  *
   1180  * @since 2.1.0
   1181  * @since 5.1.0 Return value modified to outcome of update_option().
   1182  * @since 5.7.0 The `$wp_error` parameter was added.
   1183  *
   1184  * @access private
   1185  *
   1186  * @param array $cron     Cron info array from _get_cron_array().
   1187  * @param bool  $wp_error Optional. Whether to return a WP_Error on failure. Default false.
   1188  * @return bool|WP_Error True if cron array updated. False or WP_Error on failure.
   1189  */
   1190 function _set_cron_array( $cron, $wp_error = false ) {
   1191 	$cron['version'] = 2;
   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;
   1202 }
   1203 
   1204 /**
   1205  * Upgrade a Cron info array.
   1206  *
   1207  * This function upgrades the Cron info array to version 2.
   1208  *
   1209  * @since 2.1.0
   1210  * @access private
   1211  *
   1212  * @param array $cron Cron info array from _get_cron_array().
   1213  * @return array An upgraded Cron info array.
   1214  */
   1215 function _upgrade_cron_array( $cron ) {
   1216 	if ( isset( $cron['version'] ) && 2 == $cron['version'] ) {
   1217 		return $cron;
   1218 	}
   1219 
   1220 	$new_cron = array();
   1221 
   1222 	foreach ( (array) $cron as $timestamp => $hooks ) {
   1223 		foreach ( (array) $hooks as $hook => $args ) {
   1224 			$key                                     = md5( serialize( $args['args'] ) );
   1225 			$new_cron[ $timestamp ][ $hook ][ $key ] = $args;
   1226 		}
   1227 	}
   1228 
   1229 	$new_cron['version'] = 2;
   1230 	update_option( 'cron', $new_cron );
   1231 	return $new_cron;
   1232 }