PageRenderTime 26ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-includes/cron.php

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