web/wp-includes/cron.php
branchwordpress
changeset 109 03b0d1493584
child 132 4d4862461b8d
equal deleted inserted replaced
-1:000000000000 109:03b0d1493584
       
     1 <?php
       
     2 /**
       
     3  * WordPress CRON API
       
     4  *
       
     5  * @package WordPress
       
     6  */
       
     7 
       
     8 /**
       
     9  * Schedules a hook to run only once.
       
    10  *
       
    11  * Schedules a hook which will be executed 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  * @since 2.1.0
       
    16  * @link http://codex.wordpress.org/Function_Reference/wp_schedule_single_event
       
    17  *
       
    18  * @param int $timestamp Timestamp for when to run the event.
       
    19  * @param string $hook Action hook to execute when cron is run.
       
    20  * @param array $args Optional. Arguments to pass to the hook's callback function.
       
    21  */
       
    22 function wp_schedule_single_event( $timestamp, $hook, $args = array()) {
       
    23 	// don't schedule a duplicate if there's already an identical event due in the next 10 minutes
       
    24 	$next = wp_next_scheduled($hook, $args);
       
    25 	if ( $next && $next <= $timestamp + 600 )
       
    26 		return;
       
    27 
       
    28 	$crons = _get_cron_array();
       
    29 	$key = md5(serialize($args));
       
    30 	$crons[$timestamp][$hook][$key] = array( 'schedule' => false, 'args' => $args );
       
    31 	uksort( $crons, "strnatcasecmp" );
       
    32 	_set_cron_array( $crons );
       
    33 }
       
    34 
       
    35 /**
       
    36  * Schedule a periodic event.
       
    37  *
       
    38  * Schedules a hook which will be executed by the WordPress actions core on a
       
    39  * specific interval, specified by you. The action will trigger when someone
       
    40  * visits your WordPress site, if the scheduled time has passed.
       
    41  *
       
    42  * Valid values for the recurrence are hourly, daily and twicedaily.  These can
       
    43  * be extended using the cron_schedules filter in wp_get_schedules().
       
    44  *
       
    45  * @since 2.1.0
       
    46  *
       
    47  * @param int $timestamp Timestamp for when to run the event.
       
    48  * @param string $recurrence How often the event should recur.
       
    49  * @param string $hook Action hook to execute when cron is run.
       
    50  * @param array $args Optional. Arguments to pass to the hook's callback function.
       
    51  * @return bool|null False on failure, null when complete with scheduling event.
       
    52  */
       
    53 function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array()) {
       
    54 	$crons = _get_cron_array();
       
    55 	$schedules = wp_get_schedules();
       
    56 	$key = md5(serialize($args));
       
    57 	if ( !isset( $schedules[$recurrence] ) )
       
    58 		return false;
       
    59 	$crons[$timestamp][$hook][$key] = array( 'schedule' => $recurrence, 'args' => $args, 'interval' => $schedules[$recurrence]['interval'] );
       
    60 	uksort( $crons, "strnatcasecmp" );
       
    61 	_set_cron_array( $crons );
       
    62 }
       
    63 
       
    64 /**
       
    65  * Reschedule a recurring event.
       
    66  *
       
    67  * @since 2.1.0
       
    68  *
       
    69  * @param int $timestamp Timestamp for when to run the event.
       
    70  * @param string $recurrence How often the event should recur.
       
    71  * @param string $hook Action hook to execute when cron is run.
       
    72  * @param array $args Optional. Arguments to pass to the hook's callback function.
       
    73  * @return bool|null False on failure. Null when event is rescheduled.
       
    74  */
       
    75 function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array()) {
       
    76 	$crons = _get_cron_array();
       
    77 	$schedules = wp_get_schedules();
       
    78 	$key = md5(serialize($args));
       
    79 	$interval = 0;
       
    80 
       
    81 	// First we try to get it from the schedule
       
    82 	if ( 0 == $interval )
       
    83 		$interval = $schedules[$recurrence]['interval'];
       
    84 	// Now we try to get it from the saved interval in case the schedule disappears
       
    85 	if ( 0 == $interval )
       
    86 		$interval = $crons[$timestamp][$hook][$key]['interval'];
       
    87 	// Now we assume something is wrong and fail to schedule
       
    88 	if ( 0 == $interval )
       
    89 		return false;
       
    90 
       
    91 	$now = time();
       
    92 
       
    93     if ( $timestamp >= $now )
       
    94         $timestamp = $now + $interval;
       
    95     else
       
    96         $timestamp = $now + ($interval - (($now - $timestamp) % $interval));
       
    97 
       
    98 	wp_schedule_event( $timestamp, $recurrence, $hook, $args );
       
    99 }
       
   100 
       
   101 /**
       
   102  * Unschedule a previously scheduled cron job.
       
   103  *
       
   104  * The $timestamp and $hook parameters are required, so that the event can be
       
   105  * identified.
       
   106  *
       
   107  * @since 2.1.0
       
   108  *
       
   109  * @param int $timestamp Timestamp for when to run the event.
       
   110  * @param string $hook Action hook, the execution of which will be unscheduled.
       
   111  * @param array $args Arguments to pass to the hook's callback function.
       
   112  * Although not passed to a callback function, these arguments are used
       
   113  * to uniquely identify the scheduled event, so they should be the same
       
   114  * as those used when originally scheduling the event.
       
   115  */
       
   116 function wp_unschedule_event( $timestamp, $hook, $args = array() ) {
       
   117 	$crons = _get_cron_array();
       
   118 	$key = md5(serialize($args));
       
   119 	unset( $crons[$timestamp][$hook][$key] );
       
   120 	if ( empty($crons[$timestamp][$hook]) )
       
   121 		unset( $crons[$timestamp][$hook] );
       
   122 	if ( empty($crons[$timestamp]) )
       
   123 		unset( $crons[$timestamp] );
       
   124 	_set_cron_array( $crons );
       
   125 }
       
   126 
       
   127 /**
       
   128  * Unschedule all cron jobs attached to a specific hook.
       
   129  *
       
   130  * @since 2.1.0
       
   131  *
       
   132  * @param string $hook Action hook, the execution of which will be unscheduled.
       
   133  * @param mixed $args,... Optional. Event arguments.
       
   134  */
       
   135 function wp_clear_scheduled_hook( $hook ) {
       
   136 	$args = array_slice( func_get_args(), 1 );
       
   137 
       
   138 	while ( $timestamp = wp_next_scheduled( $hook, $args ) )
       
   139 		wp_unschedule_event( $timestamp, $hook, $args );
       
   140 }
       
   141 
       
   142 /**
       
   143  * Retrieve the next timestamp for a cron event.
       
   144  *
       
   145  * @since 2.1.0
       
   146  *
       
   147  * @param string $hook Action hook to execute when cron is run.
       
   148  * @param array $args Optional. Arguments to pass to the hook's callback function.
       
   149  * @return bool|int The UNIX timestamp of the next time the scheduled event will occur.
       
   150  */
       
   151 function wp_next_scheduled( $hook, $args = array() ) {
       
   152 	$crons = _get_cron_array();
       
   153 	$key = md5(serialize($args));
       
   154 	if ( empty($crons) )
       
   155 		return false;
       
   156 	foreach ( $crons as $timestamp => $cron ) {
       
   157 		if ( isset( $cron[$hook][$key] ) )
       
   158 			return $timestamp;
       
   159 	}
       
   160 	return false;
       
   161 }
       
   162 
       
   163 /**
       
   164  * Send request to run cron through HTTP request that doesn't halt page loading.
       
   165  *
       
   166  * @since 2.1.0
       
   167  *
       
   168  * @return null Cron could not be spawned, because it is not needed to run.
       
   169  */
       
   170 function spawn_cron( $local_time = 0 ) {
       
   171 
       
   172 	if ( !$local_time )
       
   173 		$local_time = time();
       
   174 
       
   175 	if ( defined('DOING_CRON') || isset($_GET['doing_wp_cron']) )
       
   176 		return;
       
   177 
       
   178 	/*
       
   179 	 * do not even start the cron if local server timer has drifted
       
   180 	 * such as due to power failure, or misconfiguration
       
   181 	 */
       
   182 	$timer_accurate = check_server_timer( $local_time );
       
   183 	if ( !$timer_accurate )
       
   184 		return;
       
   185 
       
   186 	/*
       
   187 	* multiple processes on multiple web servers can run this code concurrently
       
   188 	* try to make this as atomic as possible by setting doing_cron switch
       
   189 	*/
       
   190 	$flag = get_transient('doing_cron');
       
   191 
       
   192 	if ( $flag > $local_time + 10*60 )
       
   193 		$flag = 0;
       
   194 
       
   195 	// don't run if another process is currently running it or more than once every 60 sec.
       
   196 	if ( $flag + 60 > $local_time )
       
   197 		return;
       
   198 
       
   199 	//sanity check
       
   200 	$crons = _get_cron_array();
       
   201 	if ( !is_array($crons) )
       
   202 		return;
       
   203 
       
   204 	$keys = array_keys( $crons );
       
   205 	if ( isset($keys[0]) && $keys[0] > $local_time )
       
   206 		return;
       
   207 
       
   208 	if ( defined('ALTERNATE_WP_CRON') && ALTERNATE_WP_CRON ) {
       
   209 		if ( !empty($_POST) || defined('DOING_AJAX') )
       
   210 			return;
       
   211 
       
   212 		set_transient( 'doing_cron', $local_time );
       
   213 
       
   214 		ob_start();
       
   215 		wp_redirect( add_query_arg('doing_wp_cron', '', stripslashes($_SERVER['REQUEST_URI'])) );
       
   216 		echo ' ';
       
   217 
       
   218 		// flush any buffers and send the headers
       
   219 		while ( @ob_end_flush() );
       
   220 		flush();
       
   221 
       
   222 		@include_once(ABSPATH . 'wp-cron.php');
       
   223 		return;
       
   224 	}
       
   225 
       
   226 	set_transient( 'doing_cron', $local_time );
       
   227 
       
   228 	$cron_url = get_option( 'siteurl' ) . '/wp-cron.php?doing_wp_cron';
       
   229 	wp_remote_post( $cron_url, array('timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters('https_local_ssl_verify', true)) );
       
   230 }
       
   231 
       
   232 /**
       
   233  * Run scheduled callbacks or spawn cron for all scheduled events.
       
   234  *
       
   235  * @since 2.1.0
       
   236  *
       
   237  * @return null When doesn't need to run Cron.
       
   238  */
       
   239 function wp_cron() {
       
   240 
       
   241 	// Prevent infinite loops caused by lack of wp-cron.php
       
   242 	if ( strpos($_SERVER['REQUEST_URI'], '/wp-cron.php') !== false || ( defined('DISABLE_WP_CRON') && DISABLE_WP_CRON ) )
       
   243 		return;
       
   244 
       
   245 	if ( false === $crons = _get_cron_array() )
       
   246 		return;
       
   247 
       
   248 	$local_time = time();
       
   249 	$keys = array_keys( $crons );
       
   250 	if ( isset($keys[0]) && $keys[0] > $local_time )
       
   251 		return;
       
   252 
       
   253 	$schedules = wp_get_schedules();
       
   254 	foreach ( $crons as $timestamp => $cronhooks ) {
       
   255 		if ( $timestamp > $local_time ) break;
       
   256 		foreach ( (array) $cronhooks as $hook => $args ) {
       
   257 			if ( isset($schedules[$hook]['callback']) && !call_user_func( $schedules[$hook]['callback'] ) )
       
   258 				continue;
       
   259 			spawn_cron( $local_time );
       
   260 			break 2;
       
   261 		}
       
   262 	}
       
   263 }
       
   264 
       
   265 /**
       
   266  * Retrieve supported and filtered Cron recurrences.
       
   267  *
       
   268  * The supported recurrences are 'hourly' and 'daily'. A plugin may add more by
       
   269  * hooking into the 'cron_schedules' filter. The filter accepts an array of
       
   270  * arrays. The outer array has a key that is the name of the schedule or for
       
   271  * example 'weekly'. The value is an array with two keys, one is 'interval' and
       
   272  * the other is 'display'.
       
   273  *
       
   274  * The 'interval' is a number in seconds of when the cron job should run. So for
       
   275  * 'hourly', the time is 3600 or 60*60. For weekly, the value would be
       
   276  * 60*60*24*7 or 604800. The value of 'interval' would then be 604800.
       
   277  *
       
   278  * The 'display' is the description. For the 'weekly' key, the 'display' would
       
   279  * be <code>__('Once Weekly')</code>.
       
   280  *
       
   281  * For your plugin, you will be passed an array. you can easily add your
       
   282  * schedule by doing the following.
       
   283  * <code>
       
   284  * // filter parameter variable name is 'array'
       
   285  *	$array['weekly'] = array(
       
   286  *		'interval' => 604800,
       
   287  *		'display' => __('Once Weekly')
       
   288  *	);
       
   289  * </code>
       
   290  *
       
   291  * @since 2.1.0
       
   292  *
       
   293  * @return array
       
   294  */
       
   295 function wp_get_schedules() {
       
   296 	$schedules = array(
       
   297 		'hourly' => array( 'interval' => 3600, 'display' => __('Once Hourly') ),
       
   298 		'twicedaily' => array( 'interval' => 43200, 'display' => __('Twice Daily') ),
       
   299 		'daily' => array( 'interval' => 86400, 'display' => __('Once Daily') ),
       
   300 	);
       
   301 	return array_merge( apply_filters( 'cron_schedules', array() ), $schedules );
       
   302 }
       
   303 
       
   304 /**
       
   305  * Retrieve Cron schedule for hook with arguments.
       
   306  *
       
   307  * @since 2.1.0
       
   308  *
       
   309  * @param string $hook Action hook to execute when cron is run.
       
   310  * @param array $args Optional. Arguments to pass to the hook's callback function.
       
   311  * @return string|bool False, if no schedule. Schedule on success.
       
   312  */
       
   313 function wp_get_schedule($hook, $args = array()) {
       
   314 	$crons = _get_cron_array();
       
   315 	$key = md5(serialize($args));
       
   316 	if ( empty($crons) )
       
   317 		return false;
       
   318 	foreach ( $crons as $timestamp => $cron ) {
       
   319 		if ( isset( $cron[$hook][$key] ) )
       
   320 			return $cron[$hook][$key]['schedule'];
       
   321 	}
       
   322 	return false;
       
   323 }
       
   324 
       
   325 //
       
   326 // Private functions
       
   327 //
       
   328 
       
   329 /**
       
   330  * Retrieve cron info array option.
       
   331  *
       
   332  * @since 2.1.0
       
   333  * @access private
       
   334  *
       
   335  * @return array CRON info array.
       
   336  */
       
   337 function _get_cron_array()  {
       
   338 	$cron = get_option('cron');
       
   339 	if ( ! is_array($cron) )
       
   340 		return false;
       
   341 
       
   342 	if ( !isset($cron['version']) )
       
   343 		$cron = _upgrade_cron_array($cron);
       
   344 
       
   345 	unset($cron['version']);
       
   346 
       
   347 	return $cron;
       
   348 }
       
   349 
       
   350 /**
       
   351  * Updates the CRON option with the new CRON array.
       
   352  *
       
   353  * @since 2.1.0
       
   354  * @access private
       
   355  *
       
   356  * @param array $cron Cron info array from {@link _get_cron_array()}.
       
   357  */
       
   358 function _set_cron_array($cron) {
       
   359 	$cron['version'] = 2;
       
   360 	update_option( 'cron', $cron );
       
   361 }
       
   362 
       
   363 /**
       
   364  * Upgrade a Cron info array.
       
   365  *
       
   366  * This function upgrades the Cron info array to version 2.
       
   367  *
       
   368  * @since 2.1.0
       
   369  * @access private
       
   370  *
       
   371  * @param array $cron Cron info array from {@link _get_cron_array()}.
       
   372  * @return array An upgraded Cron info array.
       
   373  */
       
   374 function _upgrade_cron_array($cron) {
       
   375 	if ( isset($cron['version']) && 2 == $cron['version'])
       
   376 		return $cron;
       
   377 
       
   378 	$new_cron = array();
       
   379 
       
   380 	foreach ( (array) $cron as $timestamp => $hooks) {
       
   381 		foreach ( (array) $hooks as $hook => $args ) {
       
   382 			$key = md5(serialize($args['args']));
       
   383 			$new_cron[$timestamp][$hook][$key] = $args;
       
   384 		}
       
   385 	}
       
   386 
       
   387 	$new_cron['version'] = 2;
       
   388 	update_option( 'cron', $new_cron );
       
   389 	return $new_cron;
       
   390 }
       
   391 
       
   392 // stub for checking server timer accuracy, using outside standard time sources
       
   393 function check_server_timer( $local_time ) {
       
   394 	return true;
       
   395 }
       
   396 
       
   397 ?>