[ 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 $event {
 134       *     An object containing an event's data.
 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://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 false|int 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 );
 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      // This logic duplicates wp_next_scheduled()
 430      // It's required due to a scenario where wp_unschedule_event() fails due to update_option() failing,
 431      // and, wp_next_scheduled() returns the same schedule in an infinite loop.
 432      $crons = _get_cron_array();
 433      if ( empty( $crons ) ) {
 434          return 0;
 435      }
 436  
 437      $results = array();
 438      $key     = md5( serialize( $args ) );
 439      foreach ( $crons as $timestamp => $cron ) {
 440          if ( isset( $cron[ $hook ][ $key ] ) ) {
 441              $results[] = wp_unschedule_event( $timestamp, $hook, $args );
 442          }
 443      }
 444      if ( in_array( false, $results, true ) ) {
 445          return false;
 446      }
 447      return count( $results );
 448  }
 449  
 450  /**
 451   * Unschedules all events attached to the hook.
 452   *
 453   * Can be useful for plugins when deactivating to clean up the cron queue.
 454   *
 455   * Warning: This function may return Boolean FALSE, but may also return a non-Boolean
 456   * value which evaluates to FALSE. For information about casting to booleans see the
 457   * {@link https://php.net/manual/en/language.types.boolean.php PHP documentation}. Use
 458   * the `===` operator for testing the return value of this function.
 459   *
 460   * @since 4.9.0
 461   * @since 5.1.0 Return value added to indicate success or failure.
 462   *
 463   * @param string $hook Action hook, the execution of which will be unscheduled.
 464   * @return false|int On success an integer indicating number of events unscheduled (0 indicates no
 465   *                   events were registered on the hook), false if unscheduling fails.
 466   */
 467  function wp_unschedule_hook( $hook ) {
 468      /**
 469       * Filter to preflight or hijack clearing all events attached to the hook.
 470       *
 471       * Returning a non-null value will short-circuit the normal unscheduling
 472       * process, causing the function to return the filtered value instead.
 473       *
 474       * For plugins replacing wp-cron, return the number of events successfully
 475       * unscheduled (zero if no events were registered with the hook) or false
 476       * if unscheduling one or more events fails.
 477       *
 478       * @since 5.1.0
 479       *
 480       * @param null|int|false $pre  Value to return instead. Default null to continue unscheduling the hook.
 481       * @param string         $hook Action hook, the execution of which will be unscheduled.
 482       */
 483      $pre = apply_filters( 'pre_unschedule_hook', null, $hook );
 484      if ( null !== $pre ) {
 485          return $pre;
 486      }
 487  
 488      $crons = _get_cron_array();
 489      if ( empty( $crons ) ) {
 490          return 0;
 491      }
 492  
 493      $results = array();
 494      foreach ( $crons as $timestamp => $args ) {
 495          if ( ! empty( $crons[ $timestamp ][ $hook ] ) ) {
 496              $results[] = count( $crons[ $timestamp ][ $hook ] );
 497          }
 498          unset( $crons[ $timestamp ][ $hook ] );
 499  
 500          if ( empty( $crons[ $timestamp ] ) ) {
 501              unset( $crons[ $timestamp ] );
 502          }
 503      }
 504  
 505      /*
 506       * If the results are empty (zero events to unschedule), no attempt
 507       * to update the cron array is required.
 508       */
 509      if ( empty( $results ) ) {
 510          return 0;
 511      }
 512      if ( _set_cron_array( $crons ) ) {
 513          return array_sum( $results );
 514      }
 515      return false;
 516  }
 517  
 518  /**
 519   * Retrieve a scheduled event.
 520   *
 521   * Retrieve the full event object for a given event, if no timestamp is specified the next
 522   * scheduled event is returned.
 523   *
 524   * @since 5.1.0
 525   *
 526   * @param string   $hook      Action hook of the event.
 527   * @param array    $args      Optional. Array containing each separate argument to pass to the hook's callback function.
 528   *                            Although not passed to a callback, these arguments are used to uniquely identify the
 529   *                            event, so they should be the same as those used when originally scheduling the event.
 530   * @param int|null $timestamp Optional. Unix timestamp (UTC) of the event. If not specified, the next scheduled event is returned.
 531   * @return false|object The event object. False if the event does not exist.
 532   */
 533  function wp_get_scheduled_event( $hook, $args = array(), $timestamp = null ) {
 534      /**
 535       * Filter to preflight or hijack retrieving a scheduled event.
 536       *
 537       * Returning a non-null value will short-circuit the normal process,
 538       * returning the filtered value instead.
 539       *
 540       * Return false if the event does not exist, otherwise an event object
 541       * should be returned.
 542       *
 543       * @since 5.1.0
 544       *
 545       * @param null|false|object $pre  Value to return instead. Default null to continue retrieving the event.
 546       * @param string            $hook Action hook of the event.
 547       * @param array             $args Array containing each separate argument to pass to the hook's callback function.
 548       *                                Although not passed to a callback, these arguments are used to uniquely identify
 549       *                                the event.
 550       * @param int|null  $timestamp Unix timestamp (UTC) of the event. Null to retrieve next scheduled event.
 551       */
 552      $pre = apply_filters( 'pre_get_scheduled_event', null, $hook, $args, $timestamp );
 553      if ( null !== $pre ) {
 554          return $pre;
 555      }
 556  
 557      if ( null !== $timestamp && ! is_numeric( $timestamp ) ) {
 558          return false;
 559      }
 560  
 561      $crons = _get_cron_array();
 562      if ( empty( $crons ) ) {
 563          return false;
 564      }
 565  
 566      $key = md5( serialize( $args ) );
 567  
 568      if ( ! $timestamp ) {
 569          // Get next event.
 570          $next = false;
 571          foreach ( $crons as $timestamp => $cron ) {
 572              if ( isset( $cron[ $hook ][ $key ] ) ) {
 573                  $next = $timestamp;
 574                  break;
 575              }
 576          }
 577          if ( ! $next ) {
 578              return false;
 579          }
 580  
 581          $timestamp = $next;
 582      } elseif ( ! isset( $crons[ $timestamp ][ $hook ][ $key ] ) ) {
 583          return false;
 584      }
 585  
 586      $event = (object) array(
 587          'hook'      => $hook,
 588          'timestamp' => $timestamp,
 589          'schedule'  => $crons[ $timestamp ][ $hook ][ $key ]['schedule'],
 590          'args'      => $args,
 591      );
 592  
 593      if ( isset( $crons[ $timestamp ][ $hook ][ $key ]['interval'] ) ) {
 594          $event->interval = $crons[ $timestamp ][ $hook ][ $key ]['interval'];
 595      }
 596  
 597      return $event;
 598  }
 599  
 600  /**
 601   * Retrieve the next timestamp for an event.
 602   *
 603   * @since 2.1.0
 604   *
 605   * @param string $hook Action hook of the event.
 606   * @param array  $args Optional. Array containing each separate argument to pass to the hook's callback function.
 607   *                     Although not passed to a callback, these arguments are used to uniquely identify the
 608   *                     event, so they should be the same as those used when originally scheduling the event.
 609   * @return false|int The Unix timestamp of the next time the event will occur. False if the event doesn't exist.
 610   */
 611  function wp_next_scheduled( $hook, $args = array() ) {
 612      $next_event = wp_get_scheduled_event( $hook, $args );
 613      if ( ! $next_event ) {
 614          return false;
 615      }
 616  
 617      return $next_event->timestamp;
 618  }
 619  
 620  /**
 621   * Sends a request to run cron through HTTP request that doesn't halt page loading.
 622   *
 623   * @since 2.1.0
 624   * @since 5.1.0 Return values added.
 625   *
 626   * @param int $gmt_time Optional. Unix timestamp (UTC). Default 0 (current time is used).
 627   * @return bool True if spawned, false if no events spawned.
 628   */
 629  function spawn_cron( $gmt_time = 0 ) {
 630      if ( ! $gmt_time ) {
 631          $gmt_time = microtime( true );
 632      }
 633  
 634      if ( defined( 'DOING_CRON' ) || isset( $_GET['doing_wp_cron'] ) ) {
 635          return false;
 636      }
 637  
 638      /*
 639       * Get the cron lock, which is a Unix timestamp of when the last cron was spawned
 640       * and has not finished running.
 641       *
 642       * Multiple processes on multiple web servers can run this code concurrently,
 643       * this lock attempts to make spawning as atomic as possible.
 644       */
 645      $lock = get_transient( 'doing_cron' );
 646  
 647      if ( $lock > $gmt_time + 10 * MINUTE_IN_SECONDS ) {
 648          $lock = 0;
 649      }
 650  
 651      // don't run if another process is currently running it or more than once every 60 sec.
 652      if ( $lock + WP_CRON_LOCK_TIMEOUT > $gmt_time ) {
 653          return false;
 654      }
 655  
 656      //sanity check
 657      $crons = wp_get_ready_cron_jobs();
 658      if ( empty( $crons ) ) {
 659          return false;
 660      }
 661  
 662      $keys = array_keys( $crons );
 663      if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) {
 664          return false;
 665      }
 666  
 667      if ( defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) {
 668          if ( 'GET' !== $_SERVER['REQUEST_METHOD'] || defined( 'DOING_AJAX' ) || defined( 'XMLRPC_REQUEST' ) ) {
 669              return false;
 670          }
 671  
 672          $doing_wp_cron = sprintf( '%.22F', $gmt_time );
 673          set_transient( 'doing_cron', $doing_wp_cron );
 674  
 675          ob_start();
 676          wp_redirect( add_query_arg( 'doing_wp_cron', $doing_wp_cron, wp_unslash( $_SERVER['REQUEST_URI'] ) ) );
 677          echo ' ';
 678  
 679          // flush any buffers and send the headers
 680          wp_ob_end_flush_all();
 681          flush();
 682  
 683          include_once( ABSPATH . 'wp-cron.php' );
 684          return true;
 685      }
 686  
 687      // Set the cron lock with the current unix timestamp, when the cron is being spawned.
 688      $doing_wp_cron = sprintf( '%.22F', $gmt_time );
 689      set_transient( 'doing_cron', $doing_wp_cron );
 690  
 691      /**
 692       * Filters the cron request arguments.
 693       *
 694       * @since 3.5.0
 695       * @since 4.5.0 The `$doing_wp_cron` parameter was added.
 696       *
 697       * @param array $cron_request_array {
 698       *     An array of cron request URL arguments.
 699       *
 700       *     @type string $url  The cron request URL.
 701       *     @type int    $key  The 22 digit GMT microtime.
 702       *     @type array  $args {
 703       *         An array of cron request arguments.
 704       *
 705       *         @type int  $timeout   The request timeout in seconds. Default .01 seconds.
 706       *         @type bool $blocking  Whether to set blocking for the request. Default false.
 707       *         @type bool $sslverify Whether SSL should be verified for the request. Default false.
 708       *     }
 709       * }
 710       * @param string $doing_wp_cron The unix timestamp of the cron lock.
 711       */
 712      $cron_request = apply_filters(
 713          'cron_request',
 714          array(
 715              'url'  => add_query_arg( 'doing_wp_cron', $doing_wp_cron, site_url( 'wp-cron.php' ) ),
 716              'key'  => $doing_wp_cron,
 717              'args' => array(
 718                  'timeout'   => 0.01,
 719                  'blocking'  => false,
 720                  /** This filter is documented in wp-includes/class-wp-http-streams.php */
 721                  'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
 722              ),
 723          ),
 724          $doing_wp_cron
 725      );
 726  
 727      $result = wp_remote_post( $cron_request['url'], $cron_request['args'] );
 728      return ! is_wp_error( $result );
 729  }
 730  
 731  /**
 732   * Run scheduled callbacks or spawn cron for all scheduled events.
 733   *
 734   * Warning: This function may return Boolean FALSE, but may also return a non-Boolean
 735   * value which evaluates to FALSE. For information about casting to booleans see the
 736   * {@link https://php.net/manual/en/language.types.boolean.php PHP documentation}. Use
 737   * the `===` operator for testing the return value of this function.
 738   *
 739   * @since 2.1.0
 740   * @since 5.1.0 Return value added to indicate success or failure.
 741   *
 742   * @return bool|int On success an integer indicating number of events spawned (0 indicates no
 743   *                  events needed to be spawned), false if spawning fails for one or more events.
 744   */
 745  function wp_cron() {
 746      // Prevent infinite loops caused by lack of wp-cron.php
 747      if ( strpos( $_SERVER['REQUEST_URI'], '/wp-cron.php' ) !== false || ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) ) {
 748          return 0;
 749      }
 750  
 751      $crons = wp_get_ready_cron_jobs();
 752      if ( empty( $crons ) ) {
 753          return 0;
 754      }
 755  
 756      $gmt_time = microtime( true );
 757      $keys     = array_keys( $crons );
 758      if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) {
 759          return 0;
 760      }
 761  
 762      $schedules = wp_get_schedules();
 763      $results   = array();
 764      foreach ( $crons as $timestamp => $cronhooks ) {
 765          if ( $timestamp > $gmt_time ) {
 766              break;
 767          }
 768          foreach ( (array) $cronhooks as $hook => $args ) {
 769              if ( isset( $schedules[ $hook ]['callback'] ) && ! call_user_func( $schedules[ $hook ]['callback'] ) ) {
 770                  continue;
 771              }
 772              $results[] = spawn_cron( $gmt_time );
 773              break 2;
 774          }
 775      }
 776  
 777      if ( in_array( false, $results, true ) ) {
 778          return false;
 779      }
 780      return count( $results );
 781  }
 782  
 783  /**
 784   * Retrieve supported event recurrence schedules.
 785   *
 786   * The default supported recurrences are 'hourly', 'twicedaily', and 'daily'. A plugin may
 787   * add more by hooking into the {@see 'cron_schedules'} filter. The filter accepts an array
 788   * of arrays. The outer array has a key that is the name of the schedule or for
 789   * example 'weekly'. The value is an array with two keys, one is 'interval' and
 790   * the other is 'display'.
 791   *
 792   * The 'interval' is a number in seconds of when the cron job should run. So for
 793   * 'hourly', the time is 3600 or 60*60. For weekly, the value would be
 794   * 60*60*24*7 or 604800. The value of 'interval' would then be 604800.
 795   *
 796   * The 'display' is the description. For the 'weekly' key, the 'display' would
 797   * be `__( 'Once Weekly' )`.
 798   *
 799   * For your plugin, you will be passed an array. you can easily add your
 800   * schedule by doing the following.
 801   *
 802   *     // Filter parameter variable name is 'array'.
 803   *     $array['weekly'] = array(
 804   *         'interval' => 604800,
 805   *         'display'  => __( 'Once Weekly' )
 806   *     );
 807   *
 808   * @since 2.1.0
 809   *
 810   * @return array
 811   */
 812  function wp_get_schedules() {
 813      $schedules = array(
 814          'hourly'     => array(
 815              'interval' => HOUR_IN_SECONDS,
 816              'display'  => __( 'Once Hourly' ),
 817          ),
 818          'twicedaily' => array(
 819              'interval' => 12 * HOUR_IN_SECONDS,
 820              'display'  => __( 'Twice Daily' ),
 821          ),
 822          'daily'      => array(
 823              'interval' => DAY_IN_SECONDS,
 824              'display'  => __( 'Once Daily' ),
 825          ),
 826      );
 827      /**
 828       * Filters the non-default cron schedules.
 829       *
 830       * @since 2.1.0
 831       *
 832       * @param array $new_schedules An array of non-default cron schedules. Default empty.
 833       */
 834      return array_merge( apply_filters( 'cron_schedules', array() ), $schedules );
 835  }
 836  
 837  /**
 838   * Retrieve the recurrence schedule for an event.
 839   *
 840   * @see wp_get_schedules() for available schedules.
 841   *
 842   * @since 2.1.0
 843   * @since 5.1.0 {@see 'get_schedule'} filter added.
 844   *
 845   * @param string $hook Action hook to identify the event.
 846   * @param array $args Optional. Arguments passed to the event's callback function.
 847   * @return string|false False, if no schedule. Schedule name on success.
 848   */
 849  function wp_get_schedule( $hook, $args = array() ) {
 850      $schedule = false;
 851      $event    = wp_get_scheduled_event( $hook, $args );
 852  
 853      if ( $event ) {
 854          $schedule = $event->schedule;
 855      }
 856  
 857      /**
 858       * Filter the schedule for a hook.
 859       *
 860       * @since 5.1.0
 861       *
 862       * @param string|bool $schedule Schedule for the hook. False if not found.
 863       * @param string      $hook     Action hook to execute when cron is run.
 864       * @param array       $args     Optional. Arguments to pass to the hook's callback function.
 865       */
 866      return apply_filters( 'get_schedule', $schedule, $hook, $args );
 867  }
 868  
 869  /**
 870   * Retrieve cron jobs ready to be run.
 871   *
 872   * Returns the results of _get_cron_array() limited to events ready to be run,
 873   * ie, with a timestamp in the past.
 874   *
 875   * @since 5.1.0
 876   *
 877   * @return array Cron jobs ready to be run.
 878   */
 879  function wp_get_ready_cron_jobs() {
 880      /**
 881       * Filter to preflight or hijack retrieving ready cron jobs.
 882       *
 883       * Returning an array will short-circuit the normal retrieval of ready
 884       * cron jobs, causing the function to return the filtered value instead.
 885       *
 886       * @since 5.1.0
 887       *
 888       * @param null|array $pre Array of ready cron tasks to return instead. Default null
 889       *                        to continue using results from _get_cron_array().
 890       */
 891      $pre = apply_filters( 'pre_get_ready_cron_jobs', null );
 892      if ( null !== $pre ) {
 893          return $pre;
 894      }
 895  
 896      $crons = _get_cron_array();
 897  
 898      if ( false === $crons ) {
 899          return array();
 900      }
 901  
 902      $gmt_time = microtime( true );
 903      $keys     = array_keys( $crons );
 904      if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) {
 905          return array();
 906      }
 907  
 908      $results = array();
 909      foreach ( $crons as $timestamp => $cronhooks ) {
 910          if ( $timestamp > $gmt_time ) {
 911              break;
 912          }
 913          $results[ $timestamp ] = $cronhooks;
 914      }
 915  
 916      return $results;
 917  }
 918  
 919  //
 920  // Private functions
 921  //
 922  
 923  /**
 924   * Retrieve cron info array option.
 925   *
 926   * @since 2.1.0
 927   * @access private
 928   *
 929   * @return false|array CRON info array.
 930   */
 931  function _get_cron_array() {
 932      $cron = get_option( 'cron' );
 933      if ( ! is_array( $cron ) ) {
 934          return false;
 935      }
 936  
 937      if ( ! isset( $cron['version'] ) ) {
 938          $cron = _upgrade_cron_array( $cron );
 939      }
 940  
 941      unset( $cron['version'] );
 942  
 943      return $cron;
 944  }
 945  
 946  /**
 947   * Updates the CRON option with the new CRON array.
 948   *
 949   * @since 2.1.0
 950   * @since 5.1.0 Return value modified to outcome of update_option().
 951   *
 952   * @access private
 953   *
 954   * @param array $cron Cron info array from _get_cron_array().
 955   * @return bool True if cron array updated, false on failure.
 956   */
 957  function _set_cron_array( $cron ) {
 958      $cron['version'] = 2;
 959      return update_option( 'cron', $cron );
 960  }
 961  
 962  /**
 963   * Upgrade a Cron info array.
 964   *
 965   * This function upgrades the Cron info array to version 2.
 966   *
 967   * @since 2.1.0
 968   * @access private
 969   *
 970   * @param array $cron Cron info array from _get_cron_array().
 971   * @return array An upgraded Cron info array.
 972   */
 973  function _upgrade_cron_array( $cron ) {
 974      if ( isset( $cron['version'] ) && 2 == $cron['version'] ) {
 975          return $cron;
 976      }
 977  
 978      $new_cron = array();
 979  
 980      foreach ( (array) $cron as $timestamp => $hooks ) {
 981          foreach ( (array) $hooks as $hook => $args ) {
 982              $key                                     = md5( serialize( $args['args'] ) );
 983              $new_cron[ $timestamp ][ $hook ][ $key ] = $args;
 984          }
 985      }
 986  
 987      $new_cron['version'] = 2;
 988      update_option( 'cron', $new_cron );
 989      return $new_cron;
 990  }


Generated: Wed Nov 20 01:00:03 2019 Cross-referenced by PHPXref 0.7.1