PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-includes/cron.php

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