PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-includes/cron.php

https://bitbucket.org/aqge/deptandashboard
PHP | 409 lines | 176 code | 52 blank | 181 comment | 47 complexity | c27c8356a9427cf443f2df8d2ab18135 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, LGPL-2.1
  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. $lock = get_transient('doing_cron');
  184. if ( $lock > $local_time + 10*60 )
  185. $lock = 0;
  186. // don't run if another process is currently running it or more than once every 60 sec.
  187. if ( $lock + WP_CRON_LOCK_TIMEOUT > $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. $doing_wp_cron = $local_time;
  200. set_transient( 'doing_cron', $doing_wp_cron );
  201. ob_start();
  202. wp_redirect( add_query_arg('doing_wp_cron', $doing_wp_cron, stripslashes($_SERVER['REQUEST_URI'])) );
  203. echo ' ';
  204. // flush any buffers and send the headers
  205. while ( @ob_end_flush() );
  206. flush();
  207. WP_DEBUG ? include_once( ABSPATH . 'wp-cron.php' ) : @include_once( ABSPATH . 'wp-cron.php' );
  208. return;
  209. }
  210. $doing_wp_cron = $local_time;
  211. set_transient( 'doing_cron', $doing_wp_cron );
  212. $cron_url = get_option( 'siteurl' ) . '/wp-cron.php?doing_wp_cron=' . $doing_wp_cron;
  213. wp_remote_post( $cron_url, array('timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters('https_local_ssl_verify', true)) );
  214. }
  215. /**
  216. * Run scheduled callbacks or spawn cron for all scheduled events.
  217. *
  218. * @since 2.1.0
  219. *
  220. * @return null When doesn't need to run Cron.
  221. */
  222. function wp_cron() {
  223. // Prevent infinite loops caused by lack of wp-cron.php
  224. if ( strpos($_SERVER['REQUEST_URI'], '/wp-cron.php') !== false || ( defined('DISABLE_WP_CRON') && DISABLE_WP_CRON ) )
  225. return;
  226. if ( false === $crons = _get_cron_array() )
  227. return;
  228. $local_time = time();
  229. $keys = array_keys( $crons );
  230. if ( isset($keys[0]) && $keys[0] > $local_time )
  231. return;
  232. $schedules = wp_get_schedules();
  233. foreach ( $crons as $timestamp => $cronhooks ) {
  234. if ( $timestamp > $local_time ) break;
  235. foreach ( (array) $cronhooks as $hook => $args ) {
  236. if ( isset($schedules[$hook]['callback']) && !call_user_func( $schedules[$hook]['callback'] ) )
  237. continue;
  238. spawn_cron( $local_time );
  239. break 2;
  240. }
  241. }
  242. }
  243. /**
  244. * Retrieve supported and filtered Cron recurrences.
  245. *
  246. * The supported recurrences are 'hourly' and 'daily'. A plugin may add more by
  247. * hooking into the 'cron_schedules' filter. The filter accepts an array of
  248. * arrays. The outer array has a key that is the name of the schedule or for
  249. * example 'weekly'. The value is an array with two keys, one is 'interval' and
  250. * the other is 'display'.
  251. *
  252. * The 'interval' is a number in seconds of when the cron job should run. So for
  253. * 'hourly', the time is 3600 or 60*60. For weekly, the value would be
  254. * 60*60*24*7 or 604800. The value of 'interval' would then be 604800.
  255. *
  256. * The 'display' is the description. For the 'weekly' key, the 'display' would
  257. * be <code>__('Once Weekly')</code>.
  258. *
  259. * For your plugin, you will be passed an array. you can easily add your
  260. * schedule by doing the following.
  261. * <code>
  262. * // filter parameter variable name is 'array'
  263. * $array['weekly'] = array(
  264. * 'interval' => 604800,
  265. * 'display' => __('Once Weekly')
  266. * );
  267. * </code>
  268. *
  269. * @since 2.1.0
  270. *
  271. * @return array
  272. */
  273. function wp_get_schedules() {
  274. $schedules = array(
  275. 'hourly' => array( 'interval' => 3600, 'display' => __('Once Hourly') ),
  276. 'twicedaily' => array( 'interval' => 43200, 'display' => __('Twice Daily') ),
  277. 'daily' => array( 'interval' => 86400, 'display' => __('Once Daily') ),
  278. );
  279. return array_merge( apply_filters( 'cron_schedules', array() ), $schedules );
  280. }
  281. /**
  282. * Retrieve Cron schedule for hook with arguments.
  283. *
  284. * @since 2.1.0
  285. *
  286. * @param string $hook Action hook to execute when cron is run.
  287. * @param array $args Optional. Arguments to pass to the hook's callback function.
  288. * @return string|bool False, if no schedule. Schedule on success.
  289. */
  290. function wp_get_schedule($hook, $args = array()) {
  291. $crons = _get_cron_array();
  292. $key = md5(serialize($args));
  293. if ( empty($crons) )
  294. return false;
  295. foreach ( $crons as $timestamp => $cron ) {
  296. if ( isset( $cron[$hook][$key] ) )
  297. return $cron[$hook][$key]['schedule'];
  298. }
  299. return false;
  300. }
  301. //
  302. // Private functions
  303. //
  304. /**
  305. * Retrieve cron info array option.
  306. *
  307. * @since 2.1.0
  308. * @access private
  309. *
  310. * @return array CRON info array.
  311. */
  312. function _get_cron_array() {
  313. $cron = get_option('cron');
  314. if ( ! is_array($cron) )
  315. return false;
  316. if ( !isset($cron['version']) )
  317. $cron = _upgrade_cron_array($cron);
  318. unset($cron['version']);
  319. return $cron;
  320. }
  321. /**
  322. * Updates the CRON option with the new CRON array.
  323. *
  324. * @since 2.1.0
  325. * @access private
  326. *
  327. * @param array $cron Cron info array from {@link _get_cron_array()}.
  328. */
  329. function _set_cron_array($cron) {
  330. $cron['version'] = 2;
  331. update_option( 'cron', $cron );
  332. }
  333. /**
  334. * Upgrade a Cron info array.
  335. *
  336. * This function upgrades the Cron info array to version 2.
  337. *
  338. * @since 2.1.0
  339. * @access private
  340. *
  341. * @param array $cron Cron info array from {@link _get_cron_array()}.
  342. * @return array An upgraded Cron info array.
  343. */
  344. function _upgrade_cron_array($cron) {
  345. if ( isset($cron['version']) && 2 == $cron['version'])
  346. return $cron;
  347. $new_cron = array();
  348. foreach ( (array) $cron as $timestamp => $hooks) {
  349. foreach ( (array) $hooks as $hook => $args ) {
  350. $key = md5(serialize($args['args']));
  351. $new_cron[$timestamp][$hook][$key] = $args;
  352. }
  353. }
  354. $new_cron['version'] = 2;
  355. update_option( 'cron', $new_cron );
  356. return $new_cron;
  357. }