[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> cron.php (source)

   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   *
  27   * @link https://developer.wordpress.org/reference/functions/wp_schedule_single_event/
  28   *
  29   * @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 array  $args       Optional. Array containing each separate argument to pass to the hook's callback function.
  32   * @return bool True if event successfully scheduled. False for failure.
  33   */
  34  function wp_schedule_single_event( $timestamp, $hook, $args = array() ) {
  35      // Make sure timestamp is a positive integer.
  36      if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
  37          return false;
  38      }
  39  
  40      $event = (object) array(
  41          'hook'      => $hook,
  42          'timestamp' => $timestamp,
  43          'schedule'  => false,
  44          'args'      => $args,
  45      );
  46  
  47      /**
  48       * Filter to preflight or hijack scheduling an event.
  49       *
  50       * Returning a non-null value will short-circuit adding the event to the
  51       * cron array, causing the function to return the filtered value instead.
  52       *
  53       * Both single events and recurring events are passed through this filter;
  54       * single events have `$event->schedule` as false, whereas recurring events
  55       * have this set to a recurrence from wp_get_schedules(). Recurring
  56       * events also have the integer recurrence interval set as `$event->interval`.
  57       *
  58       * For plugins replacing wp-cron, it is recommended you check for an
  59       * identical event within ten minutes and apply the {@see 'schedule_event'}
  60       * filter to check if another plugin has disallowed the event before scheduling.
  61       *
  62       * Return true if the event was scheduled, false if not.
  63       *
  64       * @since 5.1.0
  65       *
  66       * @param null|bool $pre   Value to return instead. Default null to continue adding the event.
  67       * @param stdClass  $event {
  68       *     An object containing an event's data.
  69       *
  70       *     @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.
  72       *     @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.
  74       *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
  75       * }
  76       */
  77      $pre = apply_filters( 'pre_schedule_event', null, $event );
  78      if ( null !== $pre ) {
  79          return $pre;
  80      }
  81  
  82      /*
  83       * Check for a duplicated event.
  84       *
  85       * Don't schedule an event if there's already an identical event
  86       * within 10 minutes.
  87       *
  88       * When scheduling events within ten minutes of the current time,
  89       * all past identical events are considered duplicates.
  90       *
  91       * When scheduling an event with a past timestamp (ie, before the
  92       * current time) all events scheduled within the next ten minutes
  93       * are considered duplicates.
  94       */
  95      $crons     = (array) _get_cron_array();
  96      $key       = md5( serialize( $event->args ) );
  97      $duplicate = false;
  98  
  99      if ( $event->timestamp < time() + 10 * MINUTE_IN_SECONDS ) {
 100          $min_timestamp = 0;
 101      } else {
 102          $min_timestamp = $event->timestamp - 10 * MINUTE_IN_SECONDS;
 103      }
 104  
 105      if ( $event->timestamp < time() ) {
 106          $max_timestamp = time() + 10 * MINUTE_IN_SECONDS;
 107      } else {
 108          $max_timestamp = $event->timestamp + 10 * MINUTE_IN_SECONDS;
 109      }
 110  
 111      foreach ( $crons as $event_timestamp => $cron ) {
 112          if ( $event_timestamp < $min_timestamp ) {
 113              continue;
 114          }
 115          if ( $event_timestamp > $max_timestamp ) {
 116              break;
 117          }
 118          if ( isset( $cron[ $event->hook ][ $key ] ) ) {
 119              $duplicate = true;
 120              break;
 121          }
 122      }
 123  
 124      if ( $duplicate ) {
 125          return false;
 126      }
 127  
 128      /**
 129       * Modify an event before it is scheduled.
 130       *
 131       * @since 3.1.0
 132       *
 133       * @param stdClass|false $event {
 134       *     An object containing an event's data, or boolean false to prevent the event from being scheduled.
 135       *
 136       *     @type string       $hook      Action hook to execute when the event is run.
 137       *     @type int          $timestamp Unix timestamp (UTC) for when to next run the event.
 138       *     @type string|false $schedule  How often the event should subsequently recur.
 139       *     @type array        $args      Array containing each separate argument to pass to the hook's callback function.
 140       *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
 141       * }
 142       */
 143      $event = apply_filters( 'schedule_event', $event );
 144  
 145      // A plugin disallowed this event.
 146      if ( ! $event ) {
 147          return false;
 148      }
 149  
 150      $crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
 151          'schedule' => $event->schedule,
 152          'args'     => $event->args,
 153      );
 154      uksort( $crons, 'strnatcasecmp' );
 155      return _set_cron_array( $crons );
 156  }
 157  
 158  /**
 159   * Schedules a recurring event.
 160   *
 161   * Schedules a hook which will be triggered by WordPress at the specified interval.
 162   * The action will trigger when someone visits your WordPress site if the scheduled
 163   * time has passed.
 164   *
 165   * Valid values for the recurrence are 'hourly', 'daily', and 'twicedaily'. These can
 166   * be extended using the {@see 'cron_schedules'} filter in wp_get_schedules().
 167   *
 168   * Note that scheduling an event to occur within 10 minutes of an existing event
 169   * with the same action hook will be ignored unless you pass unique `$args` values
 170   * for each scheduled event.
 171   *
 172   * Use wp_next_scheduled() to prevent duplicate events.
 173   *
 174   * Use wp_schedule_single_event() to schedule a non-recurring event.
 175   *
 176   * @since 2.1.0
 177   * @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.
 179   *
 180   * @link https://developer.wordpress.org/reference/functions/wp_schedule_event/
 181   *
 182   * @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.
 184   * @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.
 186   * @return bool True if event successfully scheduled. False for failure.
 187   */
 188  function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array() ) {
 189      // Make sure timestamp is a positive integer.
 190      if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
 191          return false;
 192      }
 193  
 194      $schedules = wp_get_schedules();
 195  
 196      if ( ! isset( $schedules[ $recurrence ] ) ) {
 197          return false;
 198      }
 199  
 200      $event = (object) array(
 201          'hook'      => $hook,
 202          'timestamp' => $timestamp,
 203          'schedule'  => $recurrence,
 204          'args'      => $args,
 205          'interval'  => $schedules[ $recurrence ]['interval'],
 206      );
 207  
 208      /** This filter is documented in wp-includes/cron.php */
 209      $pre = apply_filters( 'pre_schedule_event', null, $event );
 210      if ( null !== $pre ) {
 211          return $pre;
 212      }
 213  
 214      /** This filter is documented in wp-includes/cron.php */
 215      $event = apply_filters( 'schedule_event', $event );
 216  
 217      // A plugin disallowed this event.
 218      if ( ! $event ) {
 219          return false;
 220      }
 221  
 222      $key = md5( serialize( $event->args ) );
 223  
 224      $crons = _get_cron_array();
 225      $crons[ $event->timestamp ][ $event->hook ][ $key ] = array(
 226          'schedule' => $event->schedule,
 227          'args'     => $event->args,
 228          'interval' => $event->interval,
 229      );
 230      uksort( $crons, 'strnatcasecmp' );
 231      return _set_cron_array( $crons );
 232  }
 233  
 234  /**
 235   * Reschedules a recurring event.
 236   *
 237   * Mainly for internal use, this takes the time stamp of a previously run
 238   * recurring event and reschedules it for its next run.
 239   *
 240   * To change upcoming scheduled events, use wp_schedule_event() to
 241   * change the recurrence frequency.
 242   *
 243   * @since 2.1.0
 244   * @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.
 246   *
 247   * @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.
 249   * @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.
 251   * @return bool True if event successfully rescheduled. False for failure.
 252   */
 253  function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) {
 254      // Make sure timestamp is a positive integer.
 255      if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
 256          return false;
 257      }
 258  
 259      $schedules = wp_get_schedules();
 260      $interval  = 0;
 261  
 262      // First we try to get the interval from the schedule.
 263      if ( isset( $schedules[ $recurrence ] ) ) {
 264          $interval = $schedules[ $recurrence ]['interval'];
 265      }
 266  
 267      // Now we try to get it from the saved interval in case the schedule disappears.
 268      if ( 0 === $interval ) {
 269          $scheduled_event = wp_get_scheduled_event( $hook, $args, $timestamp );
 270          if ( $scheduled_event && isset( $scheduled_event->interval ) ) {
 271              $interval = $scheduled_event->interval;
 272          }
 273      }
 274  
 275      $event = (object) array(
 276          'hook'      => $hook,
 277          'timestamp' => $timestamp,
 278          'schedule'  => $recurrence,
 279          'args'      => $args,
 280          'interval'  => $interval,
 281      );
 282  
 283      /**
 284       * Filter to preflight or hijack rescheduling of events.
 285       *
 286       * Returning a non-null value will short-circuit the normal rescheduling
 287       * process, causing the function to return the filtered value instead.
 288       *
 289       * For plugins replacing wp-cron, return true if the event was successfully
 290       * rescheduled, false if not.
 291       *
 292       * @since 5.1.0
 293       *
 294       * @param null|bool $pre   Value to return instead. Default null to continue adding the event.
 295       * @param stdClass  $event {
 296       *     An object containing an event's data.
 297       *
 298       *     @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.
 300       *     @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.
 302       *     @type int          $interval  The interval time in seconds for the schedule. Only present for recurring events.
 303       * }
 304       */
 305      $pre = apply_filters( 'pre_reschedule_event', null, $event );
 306      if ( null !== $pre ) {
 307          return $pre;
 308      }
 309  
 310      // Now we assume something is wrong and fail to schedule.
 311      if ( 0 == $interval ) {
 312          return false;
 313      }
 314  
 315      $now = time();
 316  
 317      if ( $timestamp >= $now ) {
 318          $timestamp = $now + $interval;
 319      } else {
 320          $timestamp = $now + ( $interval - ( ( $now - $timestamp ) % $interval ) );
 321      }
 322  
 323      return wp_schedule_event( $timestamp, $recurrence, $hook, $args );
 324  }
 325  
 326  /**
 327   * Unschedule a previously scheduled event.
 328   *
 329   * The $timestamp and $hook parameters are required so that the event can be
 330   * identified.
 331   *
 332   * @since 2.1.0
 333   * @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.
 335   *
 336   * @param int    $timestamp Unix timestamp (UTC) of the event.
 337   * @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.
 339   *                          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.
 341   * @return bool True if event successfully unscheduled. False for failure.
 342   */
 343  function wp_unschedule_event( $timestamp, $hook, $args = array() ) {
 344      // Make sure timestamp is a positive integer.
 345      if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
 346          return false;
 347      }
 348  
 349      /**
 350       * Filter to preflight or hijack unscheduling of events.
 351       *
 352       * Returning a non-null value will short-circuit the normal unscheduling
 353       * process, causing the function to return the filtered value instead.
 354       *
 355       * For plugins replacing wp-cron, return true if the event was successfully
 356       * unscheduled, false if not.
 357       *
 358       * @since 5.1.0
 359       *
 360       * @param null|bool $pre       Value to return instead. Default null to continue unscheduling the event.
 361       * @param int       $timestamp Timestamp for when to run the event.
 362       * @param string    $hook      Action hook, the execution of which will be unscheduled.
 363       * @param array     $args      Arguments to pass to the hook's callback function.
 364       */
 365      $pre = apply_filters( 'pre_unschedule_event', null, $timestamp, $hook, $args );
 366      if ( null !== $pre ) {
 367          return $pre;
 368      }
 369  
 370      $crons = _get_cron_array();
 371      $key   = md5( serialize( $args ) );
 372      unset( $crons[ $timestamp ][ $hook ][ $key ] );
 373      if ( empty( $crons[ $timestamp ][ $hook ] ) ) {
 374          unset( $crons[ $timestamp ][ $hook ] );
 375      }
 376      if ( empty( $crons[ $timestamp ] ) ) {
 377          unset( $crons[ $timestamp ] );
 378      }
 379      return _set_cron_array( $crons );
 380  }
 381  
 382  /**
 383   * Unschedules all events attached to the hook with the specified arguments.
 384   *
 385   * Warning: This function may return Boolean FALSE, but may also return a non-Boolean
 386   * value which evaluates to FALSE. For information about casting to booleans see the
 387   * {@link https://www.php.net/manual/en/language.types.boolean.php PHP documentation}. Use
 388   * the `===` operator for testing the return value of this function.
 389   *
 390   * @since 2.1.0
 391   * @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.
 393   *
 394   * @param string $hook Action hook, the execution of which will be unscheduled.
 395   * @param array  $args Optional. Arguments that were to be passed to the hook's callback function.
 396   * @return int|false On success an integer indicating number of events unscheduled (0 indicates no
 397   *                   events were registered with the hook and arguments combination), false if
 398   *                   unscheduling one or more events fail.
 399   */
 400  function wp_clear_scheduled_hook( $hook, $args = array() ) {
 401      // Backward compatibility.
 402      // Previously, this function took the arguments as discrete vars rather than an array like the rest of the API.
 403      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.' ) );
 405          $args = array_slice( func_get_args(), 1 ); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
 406      }
 407  
 408      /**
 409       * Filter to preflight or hijack clearing a scheduled hook.
 410       *
 411       * Returning a non-null value will short-circuit the normal unscheduling
 412       * process, causing the function to return the filtered value instead.
 413       *
 414       * For plugins replacing wp-cron, return the number of events successfully
 415       * unscheduled (zero if no events were registered with the hook) or false
 416       * if unscheduling one or more events fails.
 417       *
 418       * @since 5.1.0
 419       *
 420       * @param null|int|false $pre  Value to return instead. Default null to continue unscheduling the event.
 421       * @param string         $hook Action hook, the execution of which will be unscheduled.
 422       * @param array          $args Arguments to pass to the hook's callback function.
 423       */
 424      $pre = apply_filters( 'pre_clear_scheduled_hook', null, $hook, $args );
 425      if ( null !== $pre ) {
 426          return $pre;
 427      }
 428  
 429      /*
 430       * This logic duplicates wp_next_scheduled().
 431       * It's required due to a scenario where wp_unschedule_event() fails due to update_option() failing,
 432       * and, wp_next_scheduled() returns the same schedule in an infinite loop.
 433       */
 434      $crons = _get_cron_array();
 435      if ( empty( $crons ) ) {
 436          return 0;
 437      }
 438  
 439      $results = array();
 440      $key     = md5( serialize( $args ) );
 441      foreach ( $crons as $timestamp => $cron ) {
 442          if ( isset( $cron[ $hook ][ $key ] ) ) {
 443              $results[] = wp_unschedule_event( $timestamp, $hook, $args );
 444          }
 445      }
 446      if ( in_array( false, $results, true ) ) {
 447          return false;
 448      }
 449      return count( $results );
 450  }
 451  
 452  /**
 453   * Unschedules all events attached to the hook.
 454   *
 455   * Can be useful for plugins when deactivating to clean up the cron queue.
 456   *
 457   * Warning: This function may return Boolean FALSE, but may also return a non-Boolean
 458   * value which evaluates to FALSE. For information about casting to booleans see the
 459   * {@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.
 461   *
 462   * @since 4.9.0
 463   * @since 5.1.0 Return value added to indicate success or failure.
 464   *
 465   * @param string $hook Action hook, the execution of which will be unscheduled.
 466   * @return int|false On success an integer indicating number of events unscheduled (0 indicates no
 467   *                   events were registered on the hook), false if unscheduling fails.
 468   */
 469  function wp_unschedule_hook( $hook ) {
 470      /**
 471       * Filter to preflight or hijack clearing all events attached to the hook.
 472       *
 473       * Returning a non-null value will short-circuit the normal unscheduling
 474       * process, causing the function to return the filtered value instead.
 475       *
 476       * For plugins replacing wp-cron, return the number of events successfully
 477       * unscheduled (zero if no events were registered with the hook) or false
 478       * if unscheduling one or more events fails.
 479       *
 480       * @since 5.1.0
 481       *
 482       * @param null|int|false $pre  Value to return instead. Default null to continue unscheduling the hook.
 483       * @param string         $hook Action hook, the execution of which will be unscheduled.
 484       */
 485      $pre = apply_filters( 'pre_unschedule_hook', null, $hook );
 486      if ( null !== $pre ) {
 487          return $pre;
 488      }
 489  
 490      $crons = _get_cron_array();
 491      if ( empty( $crons ) ) {
 492          return 0;
 493      }
 494  
 495      $results = array();
 496      foreach ( $crons as $timestamp => $args ) {
 497          if ( ! empty( $crons[ $timestamp ][ $hook ] ) ) {
 498              $results[] = count( $crons[ $timestamp ][ $hook ] );
 499          }
 500          unset( $crons[ $timestamp ][ $hook ] );
 501  
 502          if ( empty( $crons[ $timestamp ] ) ) {
 503              unset( $crons[ $timestamp ] );
 504          }
 505      }
 506  
 507      /*
 508       * If the results are empty (zero events to unschedule), no attempt
 509       * to update the cron array is required.
 510       */
 511      if ( empty( $results ) ) {
 512          return 0;
 513      }
 514      if ( _set_cron_array( $crons ) ) {
 515          return array_sum( $results );
 516      }
 517      return false;
 518  }
 519  
 520  /**
 521   * Retrieve a scheduled event.
 522   *
 523   * Retrieve the full event object for a given event, if no timestamp is specified the next
 524   * scheduled event is returned.
 525   *
 526   * @since 5.1.0
 527   *
 528   * @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.
 530   *                            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.
 532   * @param int|null $timestamp Optional. Unix timestamp (UTC) of the event. If not specified, the next scheduled event is returned.
 533   * @return object|false The event object. False if the event does not exist.
 534   */
 535  function wp_get_scheduled_event( $hook, $args = array(), $timestamp = null ) {
 536      /**
 537       * Filter to preflight or hijack retrieving a scheduled event.
 538       *
 539       * Returning a non-null value will short-circuit the normal process,
 540       * returning the filtered value instead.
 541       *
 542       * Return false if the event does not exist, otherwise an event object
 543       * should be returned.
 544       *
 545       * @since 5.1.0
 546       *
 547       * @param null|false|object $pre  Value to return instead. Default null to continue retrieving the event.
 548       * @param string            $hook Action hook of the event.
 549       * @param array             $args Array containing each separate argument to pass to the hook's callback function.
 550       *                                Although not passed to a callback, these arguments are used to uniquely identify
 551       *                                the event.
 552       * @param int|null  $timestamp Unix timestamp (UTC) of the event. Null to retrieve next scheduled event.
 553       */
 554      $pre = apply_filters( 'pre_get_scheduled_event', null, $hook, $args, $timestamp );
 555      if ( null !== $pre ) {
 556          return $pre;
 557      }
 558  
 559      if ( null !== $timestamp && ! is_numeric( $timestamp ) ) {
 560          return false;
 561      }
 562  
 563      $crons = _get_cron_array();
 564      if ( empty( $crons ) ) {
 565          return false;
 566      }
 567  
 568      $key = md5( serialize( $args ) );
 569  
 570      if ( ! $timestamp ) {
 571          // Get next event.
 572          $next = false;
 573          foreach ( $crons as $timestamp => $cron ) {
 574              if ( isset( $cron[ $hook ][ $key ] ) ) {
 575                  $next = $timestamp;
 576                  break;
 577              }
 578          }
 579          if ( ! $next ) {
 580              return false;
 581          }
 582  
 583          $timestamp = $next;
 584      } elseif ( ! isset( $crons[ $timestamp ][ $hook ][ $key ] ) ) {
 585          return false;
 586      }
 587  
 588      $event = (object) array(
 589          'hook'      => $hook,
 590          'timestamp' => $timestamp,
 591          'schedule'  => $crons[ $timestamp ][ $hook ][ $key ]['schedule'],
 592          'args'      => $args,
 593      );
 594  
 595      if ( isset( $crons[ $timestamp ][ $hook ][ $key ]['interval'] ) ) {
 596          $event->interval = $crons[ $timestamp ][ $hook ][ $key ]['interval'];
 597      }
 598  
 599      return $event;
 600  }
 601  
 602  /**
 603   * Retrieve the next timestamp for an event.
 604   *
 605   * @since 2.1.0
 606   *
 607   * @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.
 609   *                     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.
 611   * @return int|false The Unix timestamp of the next time the event will occur. False if the event doesn't exist.
 612   */
 613  function wp_next_scheduled( $hook, $args = array() ) {
 614      $next_event = wp_get_scheduled_event( $hook, $args );
 615      if ( ! $next_event ) {
 616          return false;
 617      }
 618  
 619      return $next_event->timestamp;
 620  }
 621  
 622  /**
 623   * Sends a request to run cron through HTTP request that doesn't halt page loading.
 624   *
 625   * @since 2.1.0
 626   * @since 5.1.0 Return values added.
 627   *
 628   * @param int $gmt_time Optional. Unix timestamp (UTC). Default 0 (current time is used).
 629   * @return bool True if spawned, false if no events spawned.
 630   */
 631  function spawn_cron( $gmt_time = 0 ) {
 632      if ( ! $gmt_time ) {
 633          $gmt_time = microtime( true );
 634      }
 635  
 636      if ( defined( 'DOING_CRON' ) || isset( $_GET['doing_wp_cron'] ) ) {
 637          return false;
 638      }
 639  
 640      /*
 641       * Get the cron lock, which is a Unix timestamp of when the last cron was spawned
 642       * and has not finished running.
 643       *
 644       * Multiple processes on multiple web servers can run this code concurrently,
 645       * this lock attempts to make spawning as atomic as possible.
 646       */
 647      $lock = get_transient( 'doing_cron' );
 648  
 649      if ( $lock > $gmt_time + 10 * MINUTE_IN_SECONDS ) {
 650          $lock = 0;
 651      }
 652  
 653      // Don't run if another process is currently running it or more than once every 60 sec.
 654      if ( $lock + WP_CRON_LOCK_TIMEOUT > $gmt_time ) {
 655          return false;
 656      }
 657  
 658      // Sanity check.
 659      $crons = wp_get_ready_cron_jobs();
 660      if ( empty( $crons ) ) {
 661          return false;
 662      }
 663  
 664      $keys = array_keys( $crons );
 665      if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) {
 666          return false;
 667      }
 668  
 669      if ( defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) {
 670          if ( 'GET' !== $_SERVER['REQUEST_METHOD'] || defined( 'DOING_AJAX' ) || defined( 'XMLRPC_REQUEST' ) ) {
 671              return false;
 672          }
 673  
 674          $doing_wp_cron = sprintf( '%.22F', $gmt_time );
 675          set_transient( 'doing_cron', $doing_wp_cron );
 676  
 677          ob_start();
 678          wp_redirect( add_query_arg( 'doing_wp_cron', $doing_wp_cron, wp_unslash( $_SERVER['REQUEST_URI'] ) ) );
 679          echo ' ';
 680  
 681          // Flush any buffers and send the headers.
 682          wp_ob_end_flush_all();
 683          flush();
 684  
 685          include_once ABSPATH . 'wp-cron.php';
 686          return true;
 687      }
 688  
 689      // Set the cron lock with the current unix timestamp, when the cron is being spawned.
 690      $doing_wp_cron = sprintf( '%.22F', $gmt_time );
 691      set_transient( 'doing_cron', $doing_wp_cron );
 692  
 693      /**
 694       * Filters the cron request arguments.
 695       *
 696       * @since 3.5.0
 697       * @since 4.5.0 The `$doing_wp_cron` parameter was added.
 698       *
 699       * @param array $cron_request_array {
 700       *     An array of cron request URL arguments.
 701       *
 702       *     @type string $url  The cron request URL.
 703       *     @type int    $key  The 22 digit GMT microtime.
 704       *     @type array  $args {
 705       *         An array of cron request arguments.
 706       *
 707       *         @type int  $timeout   The request timeout in seconds. Default .01 seconds.
 708       *         @type bool $blocking  Whether to set blocking for the request. Default false.
 709       *         @type bool $sslverify Whether SSL should be verified for the request. Default false.
 710       *     }
 711       * }
 712       * @param string $doing_wp_cron The unix timestamp of the cron lock.
 713       */
 714      $cron_request = apply_filters(
 715          'cron_request',
 716          array(
 717              'url'  => add_query_arg( 'doing_wp_cron', $doing_wp_cron, site_url( 'wp-cron.php' ) ),
 718              'key'  => $doing_wp_cron,
 719              'args' => array(
 720                  'timeout'   => 0.01,
 721                  'blocking'  => false,
 722                  /** This filter is documented in wp-includes/class-wp-http-streams.php */
 723                  'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
 724              ),
 725          ),
 726          $doing_wp_cron
 727      );
 728  
 729      $result = wp_remote_post( $cron_request['url'], $cron_request['args'] );
 730      return ! is_wp_error( $result );
 731  }
 732  
 733  /**
 734   * Run scheduled callbacks or spawn cron for all scheduled events.
 735   *
 736   * 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
 738   * {@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.
 740   *
 741   * @since 2.1.0
 742   * @since 5.1.0 Return value added to indicate success or failure.
 743   *
 744   * @return bool|int On success an integer indicating number of events spawned (0 indicates no
 745   *                  events needed to be spawned), false if spawning fails for one or more events.
 746   */
 747  function wp_cron() {
 748      // 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 ) ) {
 750          return 0;
 751      }
 752  
 753      $crons = wp_get_ready_cron_jobs();
 754      if ( empty( $crons ) ) {
 755          return 0;
 756      }
 757  
 758      $gmt_time = microtime( true );
 759      $keys     = array_keys( $crons );
 760      if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) {
 761          return 0;
 762      }
 763  
 764      $schedules = wp_get_schedules();
 765      $results   = array();
 766      foreach ( $crons as $timestamp => $cronhooks ) {
 767          if ( $timestamp > $gmt_time ) {
 768              break;
 769          }
 770          foreach ( (array) $cronhooks as $hook => $args ) {
 771              if ( isset( $schedules[ $hook ]['callback'] ) && ! call_user_func( $schedules[ $hook ]['callback'] ) ) {
 772                  continue;
 773              }
 774              $results[] = spawn_cron( $gmt_time );
 775              break 2;
 776          }
 777      }
 778  
 779      if ( in_array( false, $results, true ) ) {
 780          return false;
 781      }
 782      return count( $results );
 783  }
 784  
 785  /**
 786   * Retrieve supported event recurrence schedules.
 787   *
 788   * The default supported recurrences are 'hourly', 'twicedaily', 'daily', and 'weekly'.
 789   * A plugin may add more by hooking into the {@see 'cron_schedules'} filter.
 790   * The filter accepts an array of arrays. The outer array has a key that is the name
 791   * of the schedule, for example 'monthly'. The value is an array with two keys,
 792   * one is 'interval' and the other is 'display'.
 793   *
 794   * The 'interval' is a number in seconds of when the cron job should run.
 795   * So for 'hourly' the time is `HOUR_IN_SECONDS` (60 * 60 or 3600). For 'monthly',
 796   * the value would be `MONTH_IN_SECONDS` (30 * 24 * 60 * 60 or 2592000).
 797   *
 798   * The 'display' is the description. For the 'monthly' key, the 'display'
 799   * would be `__( 'Once Monthly' )`.
 800   *
 801   * For your plugin, you will be passed an array. You can easily add your
 802   * schedule by doing the following.
 803   *
 804   *     // Filter parameter variable name is 'array'.
 805   *     $array['monthly'] = array(
 806   *         'interval' => MONTH_IN_SECONDS,
 807   *         'display'  => __( 'Once Monthly' )
 808   *     );
 809   *
 810   * @since 2.1.0
 811   * @since 5.4.0 The 'weekly' schedule was added.
 812   *
 813   * @return array
 814   */
 815  function wp_get_schedules() {
 816      $schedules = array(
 817          'hourly'     => array(
 818              'interval' => HOUR_IN_SECONDS,
 819              'display'  => __( 'Once Hourly' ),
 820          ),
 821          'twicedaily' => array(
 822              'interval' => 12 * HOUR_IN_SECONDS,
 823              'display'  => __( 'Twice Daily' ),
 824          ),
 825          'daily'      => array(
 826              'interval' => DAY_IN_SECONDS,
 827              'display'  => __( 'Once Daily' ),
 828          ),
 829          'weekly'     => array(
 830              'interval' => WEEK_IN_SECONDS,
 831              'display'  => __( 'Once Weekly' ),
 832          ),
 833      );
 834  
 835      /**
 836       * Filters the non-default cron schedules.
 837       *
 838       * @since 2.1.0
 839       *
 840       * @param array $new_schedules An array of non-default cron schedules. Default empty.
 841       */
 842      return array_merge( apply_filters( 'cron_schedules', array() ), $schedules );
 843  }
 844  
 845  /**
 846   * Retrieve the recurrence schedule for an event.
 847   *
 848   * @see wp_get_schedules() for available schedules.
 849   *
 850   * @since 2.1.0
 851   * @since 5.1.0 {@see 'get_schedule'} filter added.
 852   *
 853   * @param string $hook Action hook to identify the event.
 854   * @param array  $args Optional. Arguments passed to the event's callback function.
 855   * @return string|false False, if no schedule. Schedule name on success.
 856   */
 857  function wp_get_schedule( $hook, $args = array() ) {
 858      $schedule = false;
 859      $event    = wp_get_scheduled_event( $hook, $args );
 860  
 861      if ( $event ) {
 862          $schedule = $event->schedule;
 863      }
 864  
 865      /**
 866       * Filters the schedule for a hook.
 867       *
 868       * @since 5.1.0
 869       *
 870       * @param string|bool $schedule Schedule for the hook. False if not found.
 871       * @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.
 873       */
 874      return apply_filters( 'get_schedule', $schedule, $hook, $args );
 875  }
 876  
 877  /**
 878   * Retrieve cron jobs ready to be run.
 879   *
 880   * Returns the results of _get_cron_array() limited to events ready to be run,
 881   * ie, with a timestamp in the past.
 882   *
 883   * @since 5.1.0
 884   *
 885   * @return array Cron jobs ready to be run.
 886   */
 887  function wp_get_ready_cron_jobs() {
 888      /**
 889       * Filter to preflight or hijack retrieving ready cron jobs.
 890       *
 891       * Returning an array will short-circuit the normal retrieval of ready
 892       * cron jobs, causing the function to return the filtered value instead.
 893       *
 894       * @since 5.1.0
 895       *
 896       * @param null|array $pre Array of ready cron tasks to return instead. Default null
 897       *                        to continue using results from _get_cron_array().
 898       */
 899      $pre = apply_filters( 'pre_get_ready_cron_jobs', null );
 900      if ( null !== $pre ) {
 901          return $pre;
 902      }
 903  
 904      $crons = _get_cron_array();
 905  
 906      if ( false === $crons ) {
 907          return array();
 908      }
 909  
 910      $gmt_time = microtime( true );
 911      $keys     = array_keys( $crons );
 912      if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) {
 913          return array();
 914      }
 915  
 916      $results = array();
 917      foreach ( $crons as $timestamp => $cronhooks ) {
 918          if ( $timestamp > $gmt_time ) {
 919              break;
 920          }
 921          $results[ $timestamp ] = $cronhooks;
 922      }
 923  
 924      return $results;
 925  }
 926  
 927  //
 928  // Private functions.
 929  //
 930  
 931  /**
 932   * Retrieve cron info array option.
 933   *
 934   * @since 2.1.0
 935   * @access private
 936   *
 937   * @return array|false CRON info array.
 938   */
 939  function _get_cron_array() {
 940      $cron = get_option( 'cron' );
 941      if ( ! is_array( $cron ) ) {
 942          return false;
 943      }
 944  
 945      if ( ! isset( $cron['version'] ) ) {
 946          $cron = _upgrade_cron_array( $cron );
 947      }
 948  
 949      unset( $cron['version'] );
 950  
 951      return $cron;
 952  }
 953  
 954  /**
 955   * Updates the CRON option with the new CRON array.
 956   *
 957   * @since 2.1.0
 958   * @since 5.1.0 Return value modified to outcome of update_option().
 959   *
 960   * @access private
 961   *
 962   * @param array $cron Cron info array from _get_cron_array().
 963   * @return bool True if cron array updated, false on failure.
 964   */
 965  function _set_cron_array( $cron ) {
 966      $cron['version'] = 2;
 967      return update_option( 'cron', $cron );
 968  }
 969  
 970  /**
 971   * Upgrade a Cron info array.
 972   *
 973   * This function upgrades the Cron info array to version 2.
 974   *
 975   * @since 2.1.0
 976   * @access private
 977   *
 978   * @param array $cron Cron info array from _get_cron_array().
 979   * @return array An upgraded Cron info array.
 980   */
 981  function _upgrade_cron_array( $cron ) {
 982      if ( isset( $cron['version'] ) && 2 == $cron['version'] ) {
 983          return $cron;
 984      }
 985  
 986      $new_cron = array();
 987  
 988      foreach ( (array) $cron as $timestamp => $hooks ) {
 989          foreach ( (array) $hooks as $hook => $args ) {
 990              $key                                     = md5( serialize( $args['args'] ) );
 991              $new_cron[ $timestamp ][ $hook ][ $key ] = $args;
 992          }
 993      }
 994  
 995      $new_cron['version'] = 2;
 996      update_option( 'cron', $new_cron );
 997      return $new_cron;
 998  }


Generated: Mon Oct 26 01:00:02 2020 Cross-referenced by PHPXref 0.7.1