6 */ |
6 */ |
7 |
7 |
8 /** |
8 /** |
9 * Schedules an event to run only once. |
9 * Schedules an event to run only once. |
10 * |
10 * |
11 * Schedules an event which will execute once by the WordPress actions core at |
11 * Schedules a hook which will be triggered by WordPress at the specified time. |
12 * a time which you specify. The action will fire off when someone visits your |
12 * The action will trigger when someone visits your WordPress site if the scheduled |
13 * WordPress site, if the schedule time has passed. |
13 * time has passed. |
14 * |
14 * |
15 * Note that scheduling an event to occur within 10 minutes of an existing event |
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 |
16 * with the same action hook will be ignored unless you pass unique `$args` values |
17 * for each scheduled event. |
17 * for each scheduled event. |
18 * |
18 * |
19 * @since 2.1.0 |
19 * Use wp_next_scheduled() to prevent duplicate events. |
|
20 * |
|
21 * Use wp_schedule_event() to schedule a recurring event. |
|
22 * |
|
23 * @since 2.1.0 |
|
24 * @since 5.1.0 Return value modified to boolean indicating success or failure, |
|
25 * {@see 'pre_schedule_event'} filter added to short-circuit the function. |
|
26 * |
20 * @link https://codex.wordpress.org/Function_Reference/wp_schedule_single_event |
27 * @link https://codex.wordpress.org/Function_Reference/wp_schedule_single_event |
21 * |
28 * |
22 * @param int $timestamp Unix timestamp (UTC) for when to run the event. |
29 * @param int $timestamp Unix timestamp (UTC) for when to next run the event. |
23 * @param string $hook Action hook to execute when event is run. |
30 * @param string $hook Action hook to execute when the event is run. |
24 * @param array $args Optional. Arguments to pass to the hook's callback function. |
31 * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. |
25 * @return false|void False if the event does not get scheduled. |
32 * @return bool True if event successfully scheduled. False for failure. |
26 */ |
33 */ |
27 function wp_schedule_single_event( $timestamp, $hook, $args = array()) { |
34 function wp_schedule_single_event( $timestamp, $hook, $args = array() ) { |
28 // Make sure timestamp is a positive integer |
35 // Make sure timestamp is a positive integer |
29 if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) { |
36 if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) { |
30 return false; |
37 return false; |
31 } |
38 } |
32 |
39 |
33 // Don't schedule a duplicate if there's already an identical event due within 10 minutes of it |
40 $event = (object) array( |
34 $next = wp_next_scheduled($hook, $args); |
41 'hook' => $hook, |
35 if ( $next && abs( $next - $timestamp ) <= 10 * MINUTE_IN_SECONDS ) { |
42 'timestamp' => $timestamp, |
36 return false; |
43 'schedule' => false, |
37 } |
44 'args' => $args, |
38 |
45 ); |
39 $crons = _get_cron_array(); |
46 |
40 $event = (object) array( 'hook' => $hook, 'timestamp' => $timestamp, 'schedule' => false, 'args' => $args ); |
47 /** |
41 /** |
48 * Filter to preflight or hijack scheduling an event. |
42 * Filters a single event before it is scheduled. |
49 * |
|
50 * Returning a non-null value will short-circuit adding the event to the |
|
51 * cron array, causing the function to return the filtered value instead. |
|
52 * |
|
53 * Both single events and recurring events are passed through this filter; |
|
54 * single events have `$event->schedule` as false, whereas recurring events |
|
55 * have this set to a recurrence from wp_get_schedules(). Recurring |
|
56 * events also have the integer recurrence interval set as `$event->interval`. |
|
57 * |
|
58 * For plugins replacing wp-cron, it is recommended you check for an |
|
59 * identical event within ten minutes and apply the {@see 'schedule_event'} |
|
60 * filter to check if another plugin has disallowed the event before scheduling. |
|
61 * |
|
62 * Return true if the event was scheduled, false if not. |
|
63 * |
|
64 * @since 5.1.0 |
|
65 * |
|
66 * @param null|bool $pre Value to return instead. Default null to continue adding the event. |
|
67 * @param stdClass $event { |
|
68 * An object containing an event's data. |
|
69 * |
|
70 * @type string $hook Action hook to execute when the event is run. |
|
71 * @type int $timestamp Unix timestamp (UTC) for when to next run the event. |
|
72 * @type string|false $schedule How often the event should subsequently recur. |
|
73 * @type array $args Array containing each separate argument to pass to the hook's callback function. |
|
74 * @type int $interval The interval time in seconds for the schedule. Only present for recurring events. |
|
75 * } |
|
76 */ |
|
77 $pre = apply_filters( 'pre_schedule_event', null, $event ); |
|
78 if ( null !== $pre ) { |
|
79 return $pre; |
|
80 } |
|
81 |
|
82 /* |
|
83 * Check for a duplicated event. |
|
84 * |
|
85 * Don't schedule an event if there's already an identical event |
|
86 * within 10 minutes. |
|
87 * |
|
88 * When scheduling events within ten minutes of the current time, |
|
89 * all past identical events are considered duplicates. |
|
90 * |
|
91 * When scheduling an event with a past timestamp (ie, before the |
|
92 * current time) all events scheduled within the next ten minutes |
|
93 * are considered duplicates. |
|
94 */ |
|
95 $crons = (array) _get_cron_array(); |
|
96 $key = md5( serialize( $event->args ) ); |
|
97 $duplicate = false; |
|
98 |
|
99 if ( $event->timestamp < time() + 10 * MINUTE_IN_SECONDS ) { |
|
100 $min_timestamp = 0; |
|
101 } else { |
|
102 $min_timestamp = $event->timestamp - 10 * MINUTE_IN_SECONDS; |
|
103 } |
|
104 |
|
105 if ( $event->timestamp < time() ) { |
|
106 $max_timestamp = time() + 10 * MINUTE_IN_SECONDS; |
|
107 } else { |
|
108 $max_timestamp = $event->timestamp + 10 * MINUTE_IN_SECONDS; |
|
109 } |
|
110 |
|
111 foreach ( $crons as $event_timestamp => $cron ) { |
|
112 if ( $event_timestamp < $min_timestamp ) { |
|
113 continue; |
|
114 } |
|
115 if ( $event_timestamp > $max_timestamp ) { |
|
116 break; |
|
117 } |
|
118 if ( isset( $cron[ $event->hook ][ $key ] ) ) { |
|
119 $duplicate = true; |
|
120 break; |
|
121 } |
|
122 } |
|
123 |
|
124 if ( $duplicate ) { |
|
125 return false; |
|
126 } |
|
127 |
|
128 /** |
|
129 * Modify an event before it is scheduled. |
43 * |
130 * |
44 * @since 3.1.0 |
131 * @since 3.1.0 |
45 * |
132 * |
46 * @param stdClass $event { |
133 * @param stdClass $event { |
47 * An object containing an event's data. |
134 * An object containing an event's data. |
48 * |
135 * |
49 * @type string $hook Action hook to execute when event is run. |
136 * @type string $hook Action hook to execute when the event is run. |
50 * @type int $timestamp Unix timestamp (UTC) for when to run the event. |
137 * @type int $timestamp Unix timestamp (UTC) for when to next run the event. |
51 * @type string|false $schedule How often the event should recur. See `wp_get_schedules()`. |
138 * @type string|false $schedule How often the event should subsequently recur. |
52 * @type array $args Arguments to pass to the hook's callback function. |
139 * @type array $args Array containing each separate argument to pass to the hook's callback function. |
|
140 * @type int $interval The interval time in seconds for the schedule. Only present for recurring events. |
53 * } |
141 * } |
54 */ |
142 */ |
55 $event = apply_filters( 'schedule_event', $event ); |
143 $event = apply_filters( 'schedule_event', $event ); |
56 |
144 |
57 // A plugin disallowed this event |
145 // A plugin disallowed this event |
58 if ( ! $event ) |
146 if ( ! $event ) { |
59 return false; |
147 return false; |
60 |
148 } |
61 $key = md5(serialize($event->args)); |
149 |
62 |
150 $crons[ $event->timestamp ][ $event->hook ][ $key ] = array( |
63 $crons[$event->timestamp][$event->hook][$key] = array( 'schedule' => $event->schedule, 'args' => $event->args ); |
151 'schedule' => $event->schedule, |
64 uksort( $crons, "strnatcasecmp" ); |
152 'args' => $event->args, |
65 _set_cron_array( $crons ); |
153 ); |
66 } |
154 uksort( $crons, 'strnatcasecmp' ); |
67 |
155 return _set_cron_array( $crons ); |
68 /** |
156 } |
69 * Schedule a recurring event. |
157 |
70 * |
158 /** |
71 * Schedules a hook which will be executed by the WordPress actions core on a |
159 * Schedules a recurring event. |
72 * specific interval, specified by you. The action will trigger when someone |
160 * |
73 * visits your WordPress site, if the scheduled time has passed. |
161 * Schedules a hook which will be triggered by WordPress at the specified interval. |
74 * |
162 * The action will trigger when someone visits your WordPress site if the scheduled |
75 * Valid values for the recurrence are hourly, daily, and twicedaily. These can |
163 * time has passed. |
|
164 * |
|
165 * 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(). |
166 * be extended using the {@see 'cron_schedules'} filter in wp_get_schedules(). |
77 * |
167 * |
78 * Use wp_next_scheduled() to prevent duplicates |
168 * Note that scheduling an event to occur within 10 minutes of an existing event |
79 * |
169 * with the same action hook will be ignored unless you pass unique `$args` values |
80 * @since 2.1.0 |
170 * for each scheduled event. |
81 * |
171 * |
82 * @param int $timestamp Unix timestamp (UTC) for when to run the event. |
172 * Use wp_next_scheduled() to prevent duplicate events. |
83 * @param string $recurrence How often the event should recur. |
173 * |
84 * @param string $hook Action hook to execute when event is run. |
174 * Use wp_schedule_single_event() to schedule a non-recurring event. |
85 * @param array $args Optional. Arguments to pass to the hook's callback function. |
175 * |
86 * @return false|void False if the event does not get scheduled. |
176 * @since 2.1.0 |
87 */ |
177 * @since 5.1.0 Return value modified to boolean indicating success or failure, |
88 function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array()) { |
178 * {@see 'pre_schedule_event'} filter added to short-circuit the function. |
|
179 * |
|
180 * @link https://codex.wordpress.org/Function_Reference/wp_schedule_event |
|
181 * |
|
182 * @param int $timestamp Unix timestamp (UTC) for when to next run the event. |
|
183 * @param string $recurrence How often the event should subsequently recur. See wp_get_schedules() for accepted values. |
|
184 * @param string $hook Action hook to execute when the event is run. |
|
185 * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. |
|
186 * @return bool True if event successfully scheduled. False for failure. |
|
187 */ |
|
188 function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array() ) { |
89 // Make sure timestamp is a positive integer |
189 // Make sure timestamp is a positive integer |
90 if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) { |
190 if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) { |
91 return false; |
191 return false; |
92 } |
192 } |
93 |
193 |
94 $crons = _get_cron_array(); |
|
95 $schedules = wp_get_schedules(); |
194 $schedules = wp_get_schedules(); |
96 |
195 |
97 if ( !isset( $schedules[$recurrence] ) ) |
196 if ( ! isset( $schedules[ $recurrence ] ) ) { |
98 return false; |
197 return false; |
99 |
198 } |
100 $event = (object) array( 'hook' => $hook, 'timestamp' => $timestamp, 'schedule' => $recurrence, 'args' => $args, 'interval' => $schedules[$recurrence]['interval'] ); |
199 |
|
200 $event = (object) array( |
|
201 'hook' => $hook, |
|
202 'timestamp' => $timestamp, |
|
203 'schedule' => $recurrence, |
|
204 'args' => $args, |
|
205 'interval' => $schedules[ $recurrence ]['interval'], |
|
206 ); |
|
207 |
|
208 /** This filter is documented in wp-includes/cron.php */ |
|
209 $pre = apply_filters( 'pre_schedule_event', null, $event ); |
|
210 if ( null !== $pre ) { |
|
211 return $pre; |
|
212 } |
|
213 |
101 /** This filter is documented in wp-includes/cron.php */ |
214 /** This filter is documented in wp-includes/cron.php */ |
102 $event = apply_filters( 'schedule_event', $event ); |
215 $event = apply_filters( 'schedule_event', $event ); |
103 |
216 |
104 // A plugin disallowed this event |
217 // A plugin disallowed this event |
105 if ( ! $event ) |
218 if ( ! $event ) { |
106 return false; |
219 return false; |
107 |
220 } |
108 $key = md5(serialize($event->args)); |
221 |
109 |
222 $key = md5( serialize( $event->args ) ); |
110 $crons[$event->timestamp][$event->hook][$key] = array( 'schedule' => $event->schedule, 'args' => $event->args, 'interval' => $event->interval ); |
223 |
111 uksort( $crons, "strnatcasecmp" ); |
224 $crons = _get_cron_array(); |
112 _set_cron_array( $crons ); |
225 $crons[ $event->timestamp ][ $event->hook ][ $key ] = array( |
113 } |
226 'schedule' => $event->schedule, |
114 |
227 'args' => $event->args, |
115 /** |
228 'interval' => $event->interval, |
116 * Reschedule a recurring event. |
229 ); |
117 * |
230 uksort( $crons, 'strnatcasecmp' ); |
118 * @since 2.1.0 |
231 return _set_cron_array( $crons ); |
119 * |
232 } |
120 * @param int $timestamp Unix timestamp (UTC) for when to run the event. |
233 |
121 * @param string $recurrence How often the event should recur. |
234 /** |
122 * @param string $hook Action hook to execute when event is run. |
235 * Reschedules a recurring event. |
123 * @param array $args Optional. Arguments to pass to the hook's callback function. |
236 * |
124 * @return false|void False if the event does not get rescheduled. |
237 * Mainly for internal use, this takes the time stamp of a previously run |
|
238 * recurring event and reschedules it for its next run. |
|
239 * |
|
240 * To change upcoming scheduled events, use wp_schedule_event() to |
|
241 * change the recurrence frequency. |
|
242 * |
|
243 * @since 2.1.0 |
|
244 * @since 5.1.0 Return value modified to boolean indicating success or failure, |
|
245 * {@see 'pre_reschedule_event'} filter added to short-circuit the function. |
|
246 * |
|
247 * @param int $timestamp Unix timestamp (UTC) for when the event was scheduled. |
|
248 * @param string $recurrence How often the event should subsequently recur. See wp_get_schedules() for accepted values. |
|
249 * @param string $hook Action hook to execute when the event is run. |
|
250 * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. |
|
251 * @return bool True if event successfully rescheduled. False for failure. |
125 */ |
252 */ |
126 function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) { |
253 function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array() ) { |
127 // Make sure timestamp is a positive integer |
254 // Make sure timestamp is a positive integer |
128 if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) { |
255 if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) { |
129 return false; |
256 return false; |
130 } |
257 } |
131 |
258 |
132 $crons = _get_cron_array(); |
|
133 $schedules = wp_get_schedules(); |
259 $schedules = wp_get_schedules(); |
134 $key = md5( serialize( $args ) ); |
260 $interval = 0; |
135 $interval = 0; |
261 |
136 |
262 // First we try to get the interval from the schedule. |
137 // First we try to get it from the schedule |
|
138 if ( isset( $schedules[ $recurrence ] ) ) { |
263 if ( isset( $schedules[ $recurrence ] ) ) { |
139 $interval = $schedules[ $recurrence ]['interval']; |
264 $interval = $schedules[ $recurrence ]['interval']; |
140 } |
265 } |
141 // Now we try to get it from the saved interval in case the schedule disappears |
266 |
142 if ( 0 == $interval ) { |
267 // Now we try to get it from the saved interval in case the schedule disappears. |
143 $interval = $crons[ $timestamp ][ $hook ][ $key ]['interval']; |
268 if ( 0 === $interval ) { |
144 } |
269 $scheduled_event = wp_get_scheduled_event( $hook, $args, $timestamp ); |
|
270 if ( $scheduled_event && isset( $scheduled_event->interval ) ) { |
|
271 $interval = $scheduled_event->interval; |
|
272 } |
|
273 } |
|
274 |
|
275 $event = (object) array( |
|
276 'hook' => $hook, |
|
277 'timestamp' => $timestamp, |
|
278 'schedule' => $recurrence, |
|
279 'args' => $args, |
|
280 'interval' => $interval, |
|
281 ); |
|
282 |
|
283 /** |
|
284 * Filter to preflight or hijack rescheduling of events. |
|
285 * |
|
286 * Returning a non-null value will short-circuit the normal rescheduling |
|
287 * process, causing the function to return the filtered value instead. |
|
288 * |
|
289 * For plugins replacing wp-cron, return true if the event was successfully |
|
290 * rescheduled, false if not. |
|
291 * |
|
292 * @since 5.1.0 |
|
293 * |
|
294 * @param null|bool $pre Value to return instead. Default null to continue adding the event. |
|
295 * @param stdClass $event { |
|
296 * An object containing an event's data. |
|
297 * |
|
298 * @type string $hook Action hook to execute when the event is run. |
|
299 * @type int $timestamp Unix timestamp (UTC) for when to next run the event. |
|
300 * @type string|false $schedule How often the event should subsequently recur. |
|
301 * @type array $args Array containing each separate argument to pass to the hook's callback function. |
|
302 * @type int $interval The interval time in seconds for the schedule. Only present for recurring events. |
|
303 * } |
|
304 */ |
|
305 $pre = apply_filters( 'pre_reschedule_event', null, $event ); |
|
306 if ( null !== $pre ) { |
|
307 return $pre; |
|
308 } |
|
309 |
145 // Now we assume something is wrong and fail to schedule |
310 // Now we assume something is wrong and fail to schedule |
146 if ( 0 == $interval ) { |
311 if ( 0 == $interval ) { |
147 return false; |
312 return false; |
148 } |
313 } |
149 |
314 |
153 $timestamp = $now + $interval; |
318 $timestamp = $now + $interval; |
154 } else { |
319 } else { |
155 $timestamp = $now + ( $interval - ( ( $now - $timestamp ) % $interval ) ); |
320 $timestamp = $now + ( $interval - ( ( $now - $timestamp ) % $interval ) ); |
156 } |
321 } |
157 |
322 |
158 wp_schedule_event( $timestamp, $recurrence, $hook, $args ); |
323 return wp_schedule_event( $timestamp, $recurrence, $hook, $args ); |
159 } |
324 } |
160 |
325 |
161 /** |
326 /** |
162 * Unschedule a previously scheduled event. |
327 * Unschedule a previously scheduled event. |
163 * |
328 * |
164 * The $timestamp and $hook parameters are required so that the event can be |
329 * The $timestamp and $hook parameters are required so that the event can be |
165 * identified. |
330 * identified. |
166 * |
331 * |
167 * @since 2.1.0 |
332 * @since 2.1.0 |
168 * |
333 * @since 5.1.0 Return value modified to boolean indicating success or failure, |
169 * @param int $timestamp Unix timestamp (UTC) for when to run the event. |
334 * {@see 'pre_unschedule_event'} filter added to short-circuit the function. |
170 * @param string $hook Action hook, the execution of which will be unscheduled. |
335 * |
171 * @param array $args Arguments to pass to the hook's callback function. |
336 * @param int $timestamp Unix timestamp (UTC) of the event. |
172 * Although not passed to a callback function, these arguments are used |
337 * @param string $hook Action hook of the event. |
173 * to uniquely identify the scheduled event, so they should be the same |
338 * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. |
174 * as those used when originally scheduling the event. |
339 * Although not passed to a callback, these arguments are used to uniquely identify the |
175 * @return false|void False if the event does not get unscheduled. |
340 * event, so they should be the same as those used when originally scheduling the event. |
|
341 * @return bool True if event successfully unscheduled. False for failure. |
176 */ |
342 */ |
177 function wp_unschedule_event( $timestamp, $hook, $args = array() ) { |
343 function wp_unschedule_event( $timestamp, $hook, $args = array() ) { |
178 // Make sure timestamp is a positive integer |
344 // Make sure timestamp is a positive integer |
179 if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) { |
345 if ( ! is_numeric( $timestamp ) || $timestamp <= 0 ) { |
180 return false; |
346 return false; |
181 } |
347 } |
182 |
348 |
|
349 /** |
|
350 * Filter to preflight or hijack unscheduling of events. |
|
351 * |
|
352 * Returning a non-null value will short-circuit the normal unscheduling |
|
353 * process, causing the function to return the filtered value instead. |
|
354 * |
|
355 * For plugins replacing wp-cron, return true if the event was successfully |
|
356 * unscheduled, false if not. |
|
357 * |
|
358 * @since 5.1.0 |
|
359 * |
|
360 * @param null|bool $pre Value to return instead. Default null to continue unscheduling the event. |
|
361 * @param int $timestamp Timestamp for when to run the event. |
|
362 * @param string $hook Action hook, the execution of which will be unscheduled. |
|
363 * @param array $args Arguments to pass to the hook's callback function. |
|
364 */ |
|
365 $pre = apply_filters( 'pre_unschedule_event', null, $timestamp, $hook, $args ); |
|
366 if ( null !== $pre ) { |
|
367 return $pre; |
|
368 } |
|
369 |
183 $crons = _get_cron_array(); |
370 $crons = _get_cron_array(); |
184 $key = md5(serialize($args)); |
371 $key = md5( serialize( $args ) ); |
185 unset( $crons[$timestamp][$hook][$key] ); |
372 unset( $crons[ $timestamp ][ $hook ][ $key ] ); |
186 if ( empty($crons[$timestamp][$hook]) ) |
373 if ( empty( $crons[ $timestamp ][ $hook ] ) ) { |
187 unset( $crons[$timestamp][$hook] ); |
374 unset( $crons[ $timestamp ][ $hook ] ); |
188 if ( empty($crons[$timestamp]) ) |
375 } |
189 unset( $crons[$timestamp] ); |
376 if ( empty( $crons[ $timestamp ] ) ) { |
190 _set_cron_array( $crons ); |
377 unset( $crons[ $timestamp ] ); |
|
378 } |
|
379 return _set_cron_array( $crons ); |
191 } |
380 } |
192 |
381 |
193 /** |
382 /** |
194 * Unschedules all events attached to the hook with the specified arguments. |
383 * Unschedules all events attached to the hook with the specified arguments. |
195 * |
384 * |
196 * @since 2.1.0 |
385 * Warning: This function may return Boolean FALSE, but may also return a non-Boolean |
|
386 * value which evaluates to FALSE. For information about casting to booleans see the |
|
387 * {@link https://php.net/manual/en/language.types.boolean.php PHP documentation}. Use |
|
388 * the `===` operator for testing the return value of this function. |
|
389 * |
|
390 * @since 2.1.0 |
|
391 * @since 5.1.0 Return value modified to indicate success or failure, |
|
392 * {@see 'pre_clear_scheduled_hook'} filter added to short-circuit the function. |
197 * |
393 * |
198 * @param string $hook Action hook, the execution of which will be unscheduled. |
394 * @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. |
395 * @param array $args Optional. Arguments that were to be passed to the hook's callback function. |
|
396 * @return bool|int On success an integer indicating number of events unscheduled (0 indicates no |
|
397 * events were registered with the hook and arguments combination), false if |
|
398 * unscheduling one or more events fail. |
200 */ |
399 */ |
201 function wp_clear_scheduled_hook( $hook, $args = array() ) { |
400 function wp_clear_scheduled_hook( $hook, $args = array() ) { |
202 // Backward compatibility |
401 // Backward compatibility |
203 // Previously this function took the arguments as discrete vars rather than an array like the rest of the API |
402 // Previously this function took the arguments as discrete vars rather than an array like the rest of the API |
204 if ( !is_array($args) ) { |
403 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.') ); |
404 _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 ); |
405 $args = array_slice( func_get_args(), 1 ); |
|
406 } |
|
407 |
|
408 /** |
|
409 * Filter to preflight or hijack clearing a scheduled hook. |
|
410 * |
|
411 * Returning a non-null value will short-circuit the normal unscheduling |
|
412 * process, causing the function to return the filtered value instead. |
|
413 * |
|
414 * For plugins replacing wp-cron, return the number of events successfully |
|
415 * unscheduled (zero if no events were registered with the hook) or false |
|
416 * if unscheduling one or more events fails. |
|
417 * |
|
418 * @since 5.1.0 |
|
419 * |
|
420 * @param null|array $pre Value to return instead. Default null to continue unscheduling the event. |
|
421 * @param string $hook Action hook, the execution of which will be unscheduled. |
|
422 * @param array $args Arguments to pass to the hook's callback function. |
|
423 */ |
|
424 $pre = apply_filters( 'pre_clear_scheduled_hook', null, $hook, $args ); |
|
425 if ( null !== $pre ) { |
|
426 return $pre; |
207 } |
427 } |
208 |
428 |
209 // This logic duplicates wp_next_scheduled() |
429 // This logic duplicates wp_next_scheduled() |
210 // It's required due to a scenario where wp_unschedule_event() fails due to update_option() failing, |
430 // 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. |
431 // and, wp_next_scheduled() returns the same schedule in an infinite loop. |
212 $crons = _get_cron_array(); |
432 $crons = _get_cron_array(); |
213 if ( empty( $crons ) ) |
433 if ( empty( $crons ) ) { |
214 return; |
434 return 0; |
215 |
435 } |
216 $key = md5( serialize( $args ) ); |
436 |
|
437 $results = array(); |
|
438 $key = md5( serialize( $args ) ); |
217 foreach ( $crons as $timestamp => $cron ) { |
439 foreach ( $crons as $timestamp => $cron ) { |
218 if ( isset( $cron[ $hook ][ $key ] ) ) { |
440 if ( isset( $cron[ $hook ][ $key ] ) ) { |
219 wp_unschedule_event( $timestamp, $hook, $args ); |
441 $results[] = wp_unschedule_event( $timestamp, $hook, $args ); |
220 } |
442 } |
221 } |
443 } |
|
444 if ( in_array( false, $results, true ) ) { |
|
445 return false; |
|
446 } |
|
447 return count( $results ); |
222 } |
448 } |
223 |
449 |
224 /** |
450 /** |
225 * Unschedules all events attached to the hook. |
451 * Unschedules all events attached to the hook. |
226 * |
452 * |
227 * Can be useful for plugins when deactivating to clean up the cron queue. |
453 * Can be useful for plugins when deactivating to clean up the cron queue. |
228 * |
454 * |
|
455 * Warning: This function may return Boolean FALSE, but may also return a non-Boolean |
|
456 * value which evaluates to FALSE. For information about casting to booleans see the |
|
457 * {@link https://php.net/manual/en/language.types.boolean.php PHP documentation}. Use |
|
458 * the `===` operator for testing the return value of this function. |
|
459 * |
229 * @since 4.9.0 |
460 * @since 4.9.0 |
|
461 * @since 5.1.0 Return value added to indicate success or failure. |
230 * |
462 * |
231 * @param string $hook Action hook, the execution of which will be unscheduled. |
463 * @param string $hook Action hook, the execution of which will be unscheduled. |
|
464 * @return bool|int On success an integer indicating number of events unscheduled (0 indicates no |
|
465 * events were registered on the hook), false if unscheduling fails. |
232 */ |
466 */ |
233 function wp_unschedule_hook( $hook ) { |
467 function wp_unschedule_hook( $hook ) { |
|
468 /** |
|
469 * Filter to preflight or hijack clearing all events attached to the hook. |
|
470 * |
|
471 * Returning a non-null value will short-circuit the normal unscheduling |
|
472 * process, causing the function to return the filtered value instead. |
|
473 * |
|
474 * For plugins replacing wp-cron, return the number of events successfully |
|
475 * unscheduled (zero if no events were registered with the hook) or false |
|
476 * if unscheduling one or more events fails. |
|
477 * |
|
478 * @since 5.1.0 |
|
479 * |
|
480 * @param null|array $pre Value to return instead. Default null to continue unscheduling the hook. |
|
481 * @param string $hook Action hook, the execution of which will be unscheduled. |
|
482 */ |
|
483 $pre = apply_filters( 'pre_unschedule_hook', null, $hook ); |
|
484 if ( null !== $pre ) { |
|
485 return $pre; |
|
486 } |
|
487 |
234 $crons = _get_cron_array(); |
488 $crons = _get_cron_array(); |
235 |
489 if ( empty( $crons ) ) { |
236 foreach( $crons as $timestamp => $args ) { |
490 return 0; |
|
491 } |
|
492 |
|
493 $results = array(); |
|
494 foreach ( $crons as $timestamp => $args ) { |
|
495 if ( ! empty( $crons[ $timestamp ][ $hook ] ) ) { |
|
496 $results[] = count( $crons[ $timestamp ][ $hook ] ); |
|
497 } |
237 unset( $crons[ $timestamp ][ $hook ] ); |
498 unset( $crons[ $timestamp ][ $hook ] ); |
238 |
499 |
239 if ( empty( $crons[ $timestamp ] ) ) { |
500 if ( empty( $crons[ $timestamp ] ) ) { |
240 unset( $crons[ $timestamp ] ); |
501 unset( $crons[ $timestamp ] ); |
241 } |
502 } |
242 } |
503 } |
243 |
504 |
244 _set_cron_array( $crons ); |
505 /* |
|
506 * If the results are empty (zero events to unschedule), no attempt |
|
507 * to update the cron array is required. |
|
508 */ |
|
509 if ( empty( $results ) ) { |
|
510 return 0; |
|
511 } |
|
512 if ( _set_cron_array( $crons ) ) { |
|
513 return array_sum( $results ); |
|
514 } |
|
515 return false; |
|
516 } |
|
517 |
|
518 /** |
|
519 * Retrieve a scheduled event. |
|
520 * |
|
521 * Retrieve the full event object for a given event, if no timestamp is specified the next |
|
522 * scheduled event is returned. |
|
523 * |
|
524 * @since 5.1.0 |
|
525 * |
|
526 * @param string $hook Action hook of the event. |
|
527 * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. |
|
528 * Although not passed to a callback, these arguments are used to uniquely identify the |
|
529 * event, so they should be the same as those used when originally scheduling the event. |
|
530 * @param int|null $timestamp Optional. Unix timestamp (UTC) of the event. If not specified, the next scheduled event is returned. |
|
531 * @return bool|object The event object. False if the event does not exist. |
|
532 */ |
|
533 function wp_get_scheduled_event( $hook, $args = array(), $timestamp = null ) { |
|
534 /** |
|
535 * Filter to preflight or hijack retrieving a scheduled event. |
|
536 * |
|
537 * Returning a non-null value will short-circuit the normal process, |
|
538 * returning the filtered value instead. |
|
539 * |
|
540 * Return false if the event does not exist, otherwise an event object |
|
541 * should be returned. |
|
542 * |
|
543 * @since 5.1.0 |
|
544 * |
|
545 * @param null|bool $pre Value to return instead. Default null to continue retrieving the event. |
|
546 * @param string $hook Action hook of the event. |
|
547 * @param array $args Array containing each separate argument to pass to the hook's callback function. |
|
548 * Although not passed to a callback, these arguments are used to uniquely identify the |
|
549 * event. |
|
550 * @param int|null $timestamp Unix timestamp (UTC) of the event. Null to retrieve next scheduled event. |
|
551 */ |
|
552 $pre = apply_filters( 'pre_get_scheduled_event', null, $hook, $args, $timestamp ); |
|
553 if ( null !== $pre ) { |
|
554 return $pre; |
|
555 } |
|
556 |
|
557 if ( null !== $timestamp && ! is_numeric( $timestamp ) ) { |
|
558 return false; |
|
559 } |
|
560 |
|
561 $crons = _get_cron_array(); |
|
562 if ( empty( $crons ) ) { |
|
563 return false; |
|
564 } |
|
565 |
|
566 $key = md5( serialize( $args ) ); |
|
567 |
|
568 if ( ! $timestamp ) { |
|
569 // Get next event. |
|
570 $next = false; |
|
571 foreach ( $crons as $timestamp => $cron ) { |
|
572 if ( isset( $cron[ $hook ][ $key ] ) ) { |
|
573 $next = $timestamp; |
|
574 break; |
|
575 } |
|
576 } |
|
577 if ( ! $next ) { |
|
578 return false; |
|
579 } |
|
580 |
|
581 $timestamp = $next; |
|
582 } elseif ( ! isset( $crons[ $timestamp ][ $hook ][ $key ] ) ) { |
|
583 return false; |
|
584 } |
|
585 |
|
586 $event = (object) array( |
|
587 'hook' => $hook, |
|
588 'timestamp' => $timestamp, |
|
589 'schedule' => $crons[ $timestamp ][ $hook ][ $key ]['schedule'], |
|
590 'args' => $args, |
|
591 ); |
|
592 |
|
593 if ( isset( $crons[ $timestamp ][ $hook ][ $key ]['interval'] ) ) { |
|
594 $event->interval = $crons[ $timestamp ][ $hook ][ $key ]['interval']; |
|
595 } |
|
596 |
|
597 return $event; |
245 } |
598 } |
246 |
599 |
247 /** |
600 /** |
248 * Retrieve the next timestamp for an event. |
601 * Retrieve the next timestamp for an event. |
249 * |
602 * |
250 * @since 2.1.0 |
603 * @since 2.1.0 |
251 * |
604 * |
252 * @param string $hook Action hook to execute when event is run. |
605 * @param string $hook Action hook of the event. |
253 * @param array $args Optional. Arguments to pass to the hook's callback function. |
606 * @param array $args Optional. Array containing each separate argument to pass to the hook's callback function. |
254 * @return false|int The Unix timestamp of the next time the scheduled event will occur. |
607 * Although not passed to a callback, these arguments are used to uniquely identify the |
|
608 * event, so they should be the same as those used when originally scheduling the event. |
|
609 * @return false|int The Unix timestamp of the next time the event will occur. False if the event doesn't exist. |
255 */ |
610 */ |
256 function wp_next_scheduled( $hook, $args = array() ) { |
611 function wp_next_scheduled( $hook, $args = array() ) { |
257 $crons = _get_cron_array(); |
612 $next_event = wp_get_scheduled_event( $hook, $args ); |
258 $key = md5(serialize($args)); |
613 if ( ! $next_event ) { |
259 if ( empty($crons) ) |
614 return false; |
260 return false; |
615 } |
261 foreach ( $crons as $timestamp => $cron ) { |
616 |
262 if ( isset( $cron[$hook][$key] ) ) |
617 return $next_event->timestamp; |
263 return $timestamp; |
|
264 } |
|
265 return false; |
|
266 } |
618 } |
267 |
619 |
268 /** |
620 /** |
269 * Sends a request to run cron through HTTP request that doesn't halt page loading. |
621 * Sends a request to run cron through HTTP request that doesn't halt page loading. |
270 * |
622 * |
271 * @since 2.1.0 |
623 * @since 2.1.0 |
|
624 * @since 5.1.0 Return values added. |
272 * |
625 * |
273 * @param int $gmt_time Optional. Unix timestamp (UTC). Default 0 (current time is used). |
626 * @param int $gmt_time Optional. Unix timestamp (UTC). Default 0 (current time is used). |
|
627 * @return bool True if spawned, false if no events spawned. |
274 */ |
628 */ |
275 function spawn_cron( $gmt_time = 0 ) { |
629 function spawn_cron( $gmt_time = 0 ) { |
276 if ( ! $gmt_time ) |
630 if ( ! $gmt_time ) { |
277 $gmt_time = microtime( true ); |
631 $gmt_time = microtime( true ); |
278 |
632 } |
279 if ( defined('DOING_CRON') || isset($_GET['doing_wp_cron']) ) |
633 |
280 return; |
634 if ( defined( 'DOING_CRON' ) || isset( $_GET['doing_wp_cron'] ) ) { |
|
635 return false; |
|
636 } |
281 |
637 |
282 /* |
638 /* |
283 * Get the cron lock, which is a Unix timestamp of when the last cron was spawned |
639 * Get the cron lock, which is a Unix timestamp of when the last cron was spawned |
284 * and has not finished running. |
640 * and has not finished running. |
285 * |
641 * |
286 * Multiple processes on multiple web servers can run this code concurrently, |
642 * Multiple processes on multiple web servers can run this code concurrently, |
287 * this lock attempts to make spawning as atomic as possible. |
643 * this lock attempts to make spawning as atomic as possible. |
288 */ |
644 */ |
289 $lock = get_transient('doing_cron'); |
645 $lock = get_transient( 'doing_cron' ); |
290 |
646 |
291 if ( $lock > $gmt_time + 10 * MINUTE_IN_SECONDS ) |
647 if ( $lock > $gmt_time + 10 * MINUTE_IN_SECONDS ) { |
292 $lock = 0; |
648 $lock = 0; |
|
649 } |
293 |
650 |
294 // don't run if another process is currently running it or more than once every 60 sec. |
651 // 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 ) |
652 if ( $lock + WP_CRON_LOCK_TIMEOUT > $gmt_time ) { |
296 return; |
653 return false; |
|
654 } |
297 |
655 |
298 //sanity check |
656 //sanity check |
299 $crons = _get_cron_array(); |
657 $crons = wp_get_ready_cron_jobs(); |
300 if ( !is_array($crons) ) |
658 if ( empty( $crons ) ) { |
301 return; |
659 return false; |
|
660 } |
302 |
661 |
303 $keys = array_keys( $crons ); |
662 $keys = array_keys( $crons ); |
304 if ( isset($keys[0]) && $keys[0] > $gmt_time ) |
663 if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) { |
305 return; |
664 return false; |
|
665 } |
306 |
666 |
307 if ( defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) { |
667 if ( defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) { |
308 if ( 'GET' !== $_SERVER['REQUEST_METHOD'] || defined( 'DOING_AJAX' ) || defined( 'XMLRPC_REQUEST' ) ) { |
668 if ( 'GET' !== $_SERVER['REQUEST_METHOD'] || defined( 'DOING_AJAX' ) || defined( 'XMLRPC_REQUEST' ) ) { |
309 return; |
669 return false; |
310 } |
670 } |
311 |
671 |
312 $doing_wp_cron = sprintf( '%.22F', $gmt_time ); |
672 $doing_wp_cron = sprintf( '%.22F', $gmt_time ); |
313 set_transient( 'doing_cron', $doing_wp_cron ); |
673 set_transient( 'doing_cron', $doing_wp_cron ); |
314 |
674 |
315 ob_start(); |
675 ob_start(); |
316 wp_redirect( add_query_arg( 'doing_wp_cron', $doing_wp_cron, wp_unslash( $_SERVER['REQUEST_URI'] ) ) ); |
676 wp_redirect( add_query_arg( 'doing_wp_cron', $doing_wp_cron, wp_unslash( $_SERVER['REQUEST_URI'] ) ) ); |
317 echo ' '; |
677 echo ' '; |
318 |
678 |
319 // flush any buffers and send the headers |
679 // flush any buffers and send the headers |
320 while ( @ob_end_flush() ); |
680 while ( @ob_end_flush() ) { |
|
681 } |
321 flush(); |
682 flush(); |
322 |
683 |
323 WP_DEBUG ? include_once( ABSPATH . 'wp-cron.php' ) : @include_once( ABSPATH . 'wp-cron.php' ); |
684 WP_DEBUG ? include_once( ABSPATH . 'wp-cron.php' ) : @include_once( ABSPATH . 'wp-cron.php' ); |
324 return; |
685 return true; |
325 } |
686 } |
326 |
687 |
327 // Set the cron lock with the current unix timestamp, when the cron is being spawned. |
688 // Set the cron lock with the current unix timestamp, when the cron is being spawned. |
328 $doing_wp_cron = sprintf( '%.22F', $gmt_time ); |
689 $doing_wp_cron = sprintf( '%.22F', $gmt_time ); |
329 set_transient( 'doing_cron', $doing_wp_cron ); |
690 set_transient( 'doing_cron', $doing_wp_cron ); |