home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress2 / wp-includes / cron.php < prev    next >
Encoding:
PHP Script  |  2017-06-29  |  16.1 KB  |  531 lines

  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 an event which will execute once by the WordPress actions core at
  12.  * a time which you specify. The action will fire off when someone visits your
  13.  * WordPress site, if the schedule 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.  * @since 2.1.0
  20.  * @link https://codex.wordpress.org/Function_Reference/wp_schedule_single_event
  21.  *
  22.  * @param int $timestamp Unix timestamp (UTC) for when to run the event.
  23.  * @param string $hook Action hook to execute when event is run.
  24.  * @param array $args Optional. Arguments to pass to the hook's callback function.
  25.  * @return false|void False if the event does not get scheduled.
  26.  */
  27. function wp_schedule_single_event( $timestamp, $hook, $args = array()) {
  28.     // Make sure timestamp is a positive integer
  29.     if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
  30.         return false;
  31.     }
  32.  
  33.     // Don't schedule a duplicate if there's already an identical event due within 10 minutes of it
  34.     $next = wp_next_scheduled($hook, $args);
  35.     if ( $next && abs( $next - $timestamp ) <= 10 * MINUTE_IN_SECONDS ) {
  36.         return false;
  37.     }
  38.  
  39.     $crons = _get_cron_array();
  40.     $event = (object) array( 'hook' => $hook, 'timestamp' => $timestamp, 'schedule' => false, 'args' => $args );
  41.     /**
  42.      * Filters a single event before it is scheduled.
  43.      *
  44.      * @since 3.1.0
  45.      *
  46.      * @param stdClass $event {
  47.      *     An object containing an event's data.
  48.      *
  49.      *     @type string       $hook      Action hook to execute when event is run.
  50.      *     @type int          $timestamp Unix timestamp (UTC) for when to run the event.
  51.      *     @type string|false $schedule  How often the event should recur. See `wp_get_schedules()`.
  52.      *     @type array        $args      Arguments to pass to the hook's callback function.
  53.      * }
  54.      */
  55.     $event = apply_filters( 'schedule_event', $event );
  56.  
  57.     // A plugin disallowed this event
  58.     if ( ! $event )
  59.         return false;
  60.  
  61.     $key = md5(serialize($event->args));
  62.  
  63.     $crons[$event->timestamp][$event->hook][$key] = array( 'schedule' => $event->schedule, 'args' => $event->args );
  64.     uksort( $crons, "strnatcasecmp" );
  65.     _set_cron_array( $crons );
  66. }
  67.  
  68. /**
  69.  * Schedule a recurring event.
  70.  *
  71.  * Schedules a hook which will be executed by the WordPress actions core on a
  72.  * specific interval, specified by you. The action will trigger when someone
  73.  * visits your WordPress site, if the scheduled time has passed.
  74.  *
  75.  * Valid values for the recurrence are hourly, daily, and twicedaily. These can
  76.  * be extended using the {@see 'cron_schedules'} filter in wp_get_schedules().
  77.  *
  78.  * Use wp_next_scheduled() to prevent duplicates
  79.  *
  80.  * @since 2.1.0
  81.  *
  82.  * @param int $timestamp Unix timestamp (UTC) for when to run the event.
  83.  * @param string $recurrence How often the event should recur.
  84.  * @param string $hook Action hook to execute when event is run.
  85.  * @param array $args Optional. Arguments to pass to the hook's callback function.
  86.  * @return false|void False if the event does not get scheduled.
  87.  */
  88. function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array()) {
  89.     // Make sure timestamp is a positive integer
  90.     if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
  91.         return false;
  92.     }
  93.  
  94.     $crons = _get_cron_array();
  95.     $schedules = wp_get_schedules();
  96.  
  97.     if ( !isset( $schedules[$recurrence] ) )
  98.         return false;
  99.  
  100.     $event = (object) array( 'hook' => $hook, 'timestamp' => $timestamp, 'schedule' => $recurrence, 'args' => $args, 'interval' => $schedules[$recurrence]['interval'] );
  101.     /** This filter is documented in wp-includes/cron.php */
  102.     $event = apply_filters( 'schedule_event', $event );
  103.  
  104.     // A plugin disallowed this event
  105.     if ( ! $event )
  106.         return false;
  107.  
  108.     $key = md5(serialize($event->args));
  109.  
  110.     $crons[$event->timestamp][$event->hook][$key] = array( 'schedule' => $event->schedule, 'args' => $event->args, 'interval' => $event->interval );
  111.     uksort( $crons, "strnatcasecmp" );
  112.     _set_cron_array( $crons );
  113. }
  114.  
  115. /**
  116.  * Reschedule a recurring event.
  117.  *
  118.  * @since 2.1.0
  119.  *
  120.  * @param int $timestamp Unix timestamp (UTC) for when to run the event.
  121.  * @param string $recurrence How often the event should recur.
  122.  * @param string $hook Action hook to execute when event is run.
  123.  * @param array $args Optional. Arguments to pass to the hook's callback function.
  124.  * @return false|void False if the event does not get rescheduled.
  125.  */
  126. function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) {
  127.     // Make sure timestamp is a positive integer
  128.     if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
  129.         return false;
  130.     }
  131.  
  132.     $crons = _get_cron_array();
  133.     $schedules = wp_get_schedules();
  134.     $key = md5( serialize( $args ) );
  135.     $interval = 0;
  136.  
  137.     // First we try to get it from the schedule
  138.     if ( isset( $schedules[ $recurrence ] ) ) {
  139.         $interval = $schedules[ $recurrence ]['interval'];
  140.     }
  141.     // Now we try to get it from the saved interval in case the schedule disappears
  142.     if ( 0 == $interval ) {
  143.         $interval = $crons[ $timestamp ][ $hook ][ $key ]['interval'];
  144.     }
  145.     // Now we assume something is wrong and fail to schedule
  146.     if ( 0 == $interval ) {
  147.         return false;
  148.     }
  149.  
  150.     $now = time();
  151.  
  152.     if ( $timestamp >= $now ) {
  153.         $timestamp = $now + $interval;
  154.     } else {
  155.         $timestamp = $now + ( $interval - ( ( $now - $timestamp ) % $interval ) );
  156.     }
  157.  
  158.     wp_schedule_event( $timestamp, $recurrence, $hook, $args );
  159. }
  160.  
  161. /**
  162.  * Unschedule a previously scheduled event.
  163.  *
  164.  * The $timestamp and $hook parameters are required so that the event can be
  165.  * identified.
  166.  *
  167.  * @since 2.1.0
  168.  *
  169.  * @param int $timestamp Unix timestamp (UTC) for when to run the event.
  170.  * @param string $hook Action hook, the execution of which will be unscheduled.
  171.  * @param array $args Arguments to pass to the hook's callback function.
  172.  * Although not passed to a callback function, these arguments are used
  173.  * to uniquely identify the scheduled event, so they should be the same
  174.  * as those used when originally scheduling the event.
  175.  * @return false|void False if the event does not get unscheduled.
  176.  */
  177. function wp_unschedule_event( $timestamp, $hook, $args = array() ) {
  178.     // Make sure timestamp is a positive integer
  179.     if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) {
  180.         return false;
  181.     }
  182.  
  183.     $crons = _get_cron_array();
  184.     $key = md5(serialize($args));
  185.     unset( $crons[$timestamp][$hook][$key] );
  186.     if ( empty($crons[$timestamp][$hook]) )
  187.         unset( $crons[$timestamp][$hook] );
  188.     if ( empty($crons[$timestamp]) )
  189.         unset( $crons[$timestamp] );
  190.     _set_cron_array( $crons );
  191. }
  192.  
  193. /**
  194.  * Unschedules all events attached to the hook with the specified arguments.
  195.  *
  196.  * @since 2.1.0
  197.  *
  198.  * @param string $hook Action hook, the execution of which will be unscheduled.
  199.  * @param array $args Optional. Arguments that were to be passed to the hook's callback function.
  200.  */
  201. function wp_clear_scheduled_hook( $hook, $args = array() ) {
  202.     // Backward compatibility
  203.     // Previously this function took the arguments as discrete vars rather than an array like the rest of the API
  204.     if ( !is_array($args) ) {
  205.         _deprecated_argument( __FUNCTION__, '3.0.0', __('This argument has changed to an array to match the behavior of the other cron functions.') );
  206.         $args = array_slice( func_get_args(), 1 );
  207.     }
  208.  
  209.     // This logic duplicates wp_next_scheduled()
  210.     // It's required due to a scenario where wp_unschedule_event() fails due to update_option() failing,
  211.     // and, wp_next_scheduled() returns the same schedule in an infinite loop.
  212.     $crons = _get_cron_array();
  213.     if ( empty( $crons ) )
  214.         return;
  215.  
  216.     $key = md5( serialize( $args ) );
  217.     foreach ( $crons as $timestamp => $cron ) {
  218.         if ( isset( $cron[ $hook ][ $key ] ) ) {
  219.             wp_unschedule_event( $timestamp, $hook, $args );
  220.         }
  221.     }
  222. }
  223.  
  224. /**
  225.  * Unschedules all events attached to the hook.
  226.  *
  227.  * Can be useful for plugins when deactivating to clean up the cron queue.
  228.  *
  229.  * @since 4.9.0
  230.  *
  231.  * @param string $hook Action hook, the execution of which will be unscheduled.
  232.  */
  233. function wp_unschedule_hook( $hook ) {
  234.     $crons = _get_cron_array();
  235.  
  236.     foreach( $crons as $timestamp => $args ) {
  237.         unset( $crons[ $timestamp ][ $hook ] );
  238.  
  239.         if ( empty( $crons[ $timestamp ] ) ) {
  240.             unset( $crons[ $timestamp ] );
  241.         }
  242.     }
  243.  
  244.     _set_cron_array( $crons );
  245. }
  246.  
  247. /**
  248.  * Retrieve the next timestamp for an event.
  249.  *
  250.  * @since 2.1.0
  251.  *
  252.  * @param string $hook Action hook to execute when event is run.
  253.  * @param array $args Optional. Arguments to pass to the hook's callback function.
  254.  * @return false|int The Unix timestamp of the next time the scheduled event will occur.
  255.  */
  256. function wp_next_scheduled( $hook, $args = array() ) {
  257.     $crons = _get_cron_array();
  258.     $key = md5(serialize($args));
  259.     if ( empty($crons) )
  260.         return false;
  261.     foreach ( $crons as $timestamp => $cron ) {
  262.         if ( isset( $cron[$hook][$key] ) )
  263.             return $timestamp;
  264.     }
  265.     return false;
  266. }
  267.  
  268. /**
  269.  * Sends a request to run cron through HTTP request that doesn't halt page loading.
  270.  *
  271.  * @since 2.1.0
  272.  *
  273.  * @param int $gmt_time Optional. Unix timestamp (UTC). Default 0 (current time is used).
  274.  */
  275. function spawn_cron( $gmt_time = 0 ) {
  276.     if ( ! $gmt_time )
  277.         $gmt_time = microtime( true );
  278.  
  279.     if ( defined('DOING_CRON') || isset($_GET['doing_wp_cron']) )
  280.         return;
  281.  
  282.     /*
  283.      * Get the cron lock, which is a Unix timestamp of when the last cron was spawned
  284.      * and has not finished running.
  285.      *
  286.      * Multiple processes on multiple web servers can run this code concurrently,
  287.      * this lock attempts to make spawning as atomic as possible.
  288.      */
  289.     $lock = get_transient('doing_cron');
  290.  
  291.     if ( $lock > $gmt_time + 10 * MINUTE_IN_SECONDS )
  292.         $lock = 0;
  293.  
  294.     // don't run if another process is currently running it or more than once every 60 sec.
  295.     if ( $lock + WP_CRON_LOCK_TIMEOUT > $gmt_time )
  296.         return;
  297.  
  298.     //sanity check
  299.     $crons = _get_cron_array();
  300.     if ( !is_array($crons) )
  301.         return;
  302.  
  303.     $keys = array_keys( $crons );
  304.     if ( isset($keys[0]) && $keys[0] > $gmt_time )
  305.         return;
  306.  
  307.     if ( defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) {
  308.         if ( 'GET' !== $_SERVER['REQUEST_METHOD'] || defined( 'DOING_AJAX' ) ||  defined( 'XMLRPC_REQUEST' ) ) {
  309.             return;
  310.         }
  311.  
  312.         $doing_wp_cron = sprintf( '%.22F', $gmt_time );
  313.         set_transient( 'doing_cron', $doing_wp_cron );
  314.  
  315.         ob_start();
  316.         wp_redirect( add_query_arg( 'doing_wp_cron', $doing_wp_cron, wp_unslash( $_SERVER['REQUEST_URI'] ) ) );
  317.         echo ' ';
  318.  
  319.         // flush any buffers and send the headers
  320.         while ( @ob_end_flush() );
  321.         flush();
  322.  
  323.         WP_DEBUG ? include_once( ABSPATH . 'wp-cron.php' ) : @include_once( ABSPATH . 'wp-cron.php' );
  324.         return;
  325.     }
  326.  
  327.     // Set the cron lock with the current unix timestamp, when the cron is being spawned.
  328.     $doing_wp_cron = sprintf( '%.22F', $gmt_time );
  329.     set_transient( 'doing_cron', $doing_wp_cron );
  330.  
  331.     /**
  332.      * Filters the cron request arguments.
  333.      *
  334.      * @since 3.5.0
  335.      * @since 4.5.0 The `$doing_wp_cron` parameter was added.
  336.      *
  337.      * @param array $cron_request_array {
  338.      *     An array of cron request URL arguments.
  339.      *
  340.      *     @type string $url  The cron request URL.
  341.      *     @type int    $key  The 22 digit GMT microtime.
  342.      *     @type array  $args {
  343.      *         An array of cron request arguments.
  344.      *
  345.      *         @type int  $timeout   The request timeout in seconds. Default .01 seconds.
  346.      *         @type bool $blocking  Whether to set blocking for the request. Default false.
  347.      *         @type bool $sslverify Whether SSL should be verified for the request. Default false.
  348.      *     }
  349.      * }
  350.      * @param string $doing_wp_cron The unix timestamp of the cron lock.
  351.      */
  352.     $cron_request = apply_filters( 'cron_request', array(
  353.         'url'  => add_query_arg( 'doing_wp_cron', $doing_wp_cron, site_url( 'wp-cron.php' ) ),
  354.         'key'  => $doing_wp_cron,
  355.         'args' => array(
  356.             'timeout'   => 0.01,
  357.             'blocking'  => false,
  358.             /** This filter is documented in wp-includes/class-wp-http-streams.php */
  359.             'sslverify' => apply_filters( 'https_local_ssl_verify', false )
  360.         )
  361.     ), $doing_wp_cron );
  362.  
  363.     wp_remote_post( $cron_request['url'], $cron_request['args'] );
  364. }
  365.  
  366. /**
  367.  * Run scheduled callbacks or spawn cron for all scheduled events.
  368.  *
  369.  * @since 2.1.0
  370.  */
  371. function wp_cron() {
  372.     // Prevent infinite loops caused by lack of wp-cron.php
  373.     if ( strpos($_SERVER['REQUEST_URI'], '/wp-cron.php') !== false || ( defined('DISABLE_WP_CRON') && DISABLE_WP_CRON ) )
  374.         return;
  375.  
  376.     if ( false === $crons = _get_cron_array() )
  377.         return;
  378.  
  379.     $gmt_time = microtime( true );
  380.     $keys = array_keys( $crons );
  381.     if ( isset($keys[0]) && $keys[0] > $gmt_time )
  382.         return;
  383.  
  384.     $schedules = wp_get_schedules();
  385.     foreach ( $crons as $timestamp => $cronhooks ) {
  386.         if ( $timestamp > $gmt_time ) break;
  387.         foreach ( (array) $cronhooks as $hook => $args ) {
  388.             if ( isset($schedules[$hook]['callback']) && !call_user_func( $schedules[$hook]['callback'] ) )
  389.                 continue;
  390.             spawn_cron( $gmt_time );
  391.             break 2;
  392.         }
  393.     }
  394. }
  395.  
  396. /**
  397.  * Retrieve supported event recurrence schedules.
  398.  *
  399.  * The default supported recurrences are 'hourly', 'twicedaily', and 'daily'. A plugin may
  400.  * add more by hooking into the {@see 'cron_schedules'} filter. The filter accepts an array
  401.  * of arrays. The outer array has a key that is the name of the schedule or for
  402.  * example 'weekly'. The value is an array with two keys, one is 'interval' and
  403.  * the other is 'display'.
  404.  *
  405.  * The 'interval' is a number in seconds of when the cron job should run. So for
  406.  * 'hourly', the time is 3600 or 60*60. For weekly, the value would be
  407.  * 60*60*24*7 or 604800. The value of 'interval' would then be 604800.
  408.  *
  409.  * The 'display' is the description. For the 'weekly' key, the 'display' would
  410.  * be `__( 'Once Weekly' )`.
  411.  *
  412.  * For your plugin, you will be passed an array. you can easily add your
  413.  * schedule by doing the following.
  414.  *
  415.  *     // Filter parameter variable name is 'array'.
  416.  *     $array['weekly'] = array(
  417.  *         'interval' => 604800,
  418.  *            'display'  => __( 'Once Weekly' )
  419.  *     );
  420.  *
  421.  *
  422.  * @since 2.1.0
  423.  *
  424.  * @return array
  425.  */
  426. function wp_get_schedules() {
  427.     $schedules = array(
  428.         'hourly'     => array( 'interval' => HOUR_IN_SECONDS,      'display' => __( 'Once Hourly' ) ),
  429.         'twicedaily' => array( 'interval' => 12 * HOUR_IN_SECONDS, 'display' => __( 'Twice Daily' ) ),
  430.         'daily'      => array( 'interval' => DAY_IN_SECONDS,       'display' => __( 'Once Daily' ) ),
  431.     );
  432.     /**
  433.      * Filters the non-default cron schedules.
  434.      *
  435.      * @since 2.1.0
  436.      *
  437.      * @param array $new_schedules An array of non-default cron schedules. Default empty.
  438.      */
  439.     return array_merge( apply_filters( 'cron_schedules', array() ), $schedules );
  440. }
  441.  
  442. /**
  443.  * Retrieve the recurrence schedule for an event.
  444.  *
  445.  * @see wp_get_schedules() for available schedules.
  446.  *
  447.  * @since 2.1.0
  448.  *
  449.  * @param string $hook Action hook to identify the event.
  450.  * @param array $args Optional. Arguments passed to the event's callback function.
  451.  * @return string|false False, if no schedule. Schedule name on success.
  452.  */
  453. function wp_get_schedule($hook, $args = array()) {
  454.     $crons = _get_cron_array();
  455.     $key = md5(serialize($args));
  456.     if ( empty($crons) )
  457.         return false;
  458.     foreach ( $crons as $timestamp => $cron ) {
  459.         if ( isset( $cron[$hook][$key] ) )
  460.             return $cron[$hook][$key]['schedule'];
  461.     }
  462.     return false;
  463. }
  464.  
  465. //
  466. // Private functions
  467. //
  468.  
  469. /**
  470.  * Retrieve cron info array option.
  471.  *
  472.  * @since 2.1.0
  473.  * @access private
  474.  *
  475.  * @return false|array CRON info array.
  476.  */
  477. function _get_cron_array()  {
  478.     $cron = get_option('cron');
  479.     if ( ! is_array($cron) )
  480.         return false;
  481.  
  482.     if ( !isset($cron['version']) )
  483.         $cron = _upgrade_cron_array($cron);
  484.  
  485.     unset($cron['version']);
  486.  
  487.     return $cron;
  488. }
  489.  
  490. /**
  491.  * Updates the CRON option with the new CRON array.
  492.  *
  493.  * @since 2.1.0
  494.  * @access private
  495.  *
  496.  * @param array $cron Cron info array from _get_cron_array().
  497.  */
  498. function _set_cron_array($cron) {
  499.     $cron['version'] = 2;
  500.     update_option( 'cron', $cron );
  501. }
  502.  
  503. /**
  504.  * Upgrade a Cron info array.
  505.  *
  506.  * This function upgrades the Cron info array to version 2.
  507.  *
  508.  * @since 2.1.0
  509.  * @access private
  510.  *
  511.  * @param array $cron Cron info array from _get_cron_array().
  512.  * @return array An upgraded Cron info array.
  513.  */
  514. function _upgrade_cron_array($cron) {
  515.     if ( isset($cron['version']) && 2 == $cron['version'])
  516.         return $cron;
  517.  
  518.     $new_cron = array();
  519.  
  520.     foreach ( (array) $cron as $timestamp => $hooks) {
  521.         foreach ( (array) $hooks as $hook => $args ) {
  522.             $key = md5(serialize($args['args']));
  523.             $new_cron[$timestamp][$hook][$key] = $args;
  524.         }
  525.     }
  526.  
  527.     $new_cron['version'] = 2;
  528.     update_option( 'cron', $new_cron );
  529.     return $new_cron;
  530. }
  531.