PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
← All changes | inc/libraries/wp-background-process/classes/wp-background-process.php +505 -505 4.3.94.4.8 View file →
@@ -1,505 +1,505 @@
1 -<?php
2 -/**
3 - * WP Background Process
4 - *
5 - * @package WP-Background-Processing
6 - */
7 -
8 -/**
9 - * Abstract WP_Background_Process class.
10 - *
11 - * @abstract
12 - * @extends WP_Async_Request
13 - */
14 -abstract class WP_Background_Process extends WP_Async_Request {
15 -
16 - /**
17 - * Action
18 - *
19 - * (default value: 'background_process')
20 - *
21 - * @var string
22 - * @access protected
23 - */
24 - protected $action = 'background_process';
25 -
26 - /**
27 - * Start time of current process.
28 - *
29 - * (default value: 0)
30 - *
31 - * @var int
32 - * @access protected
33 - */
34 - protected $start_time = 0;
35 -
36 - /**
37 - * Cron_hook_identifier
38 - *
39 - * @var mixed
40 - * @access protected
41 - */
42 - protected $cron_hook_identifier;
43 -
44 - /**
45 - * Cron_interval_identifier
46 - *
47 - * @var mixed
48 - * @access protected
49 - */
50 - protected $cron_interval_identifier;
51 -
52 - /**
53 - * Initiate new background process
54 - */
55 - public function __construct() {
56 - parent::__construct();
57 -
58 - $this->cron_hook_identifier = $this->identifier . '_cron';
59 - $this->cron_interval_identifier = $this->identifier . '_cron_interval';
60 -
61 - add_action( $this->cron_hook_identifier, array( $this, 'handle_cron_healthcheck' ) );
62 - add_filter( 'cron_schedules', array( $this, 'schedule_cron_healthcheck' ) );
63 - }
64 -
65 - /**
66 - * Dispatch
67 - *
68 - * @access public
69 - * @return array|WP_Error
70 - */
71 - public function dispatch() {
72 - // Schedule the cron healthcheck.
73 - $this->schedule_event();
74 -
75 - // Perform remote post.
76 - return parent::dispatch();
77 - }
78 -
79 - /**
80 - * Push to queue
81 - *
82 - * @param mixed $data Data.
83 - *
84 - * @return $this
85 - */
86 - public function push_to_queue( $data ) {
87 - $this->data[] = $data;
88 -
89 - return $this;
90 - }
91 -
92 - /**
93 - * Save queue
94 - *
95 - * @return $this
96 - */
97 - public function save() {
98 - $key = $this->generate_key();
99 -
100 - if ( ! empty( $this->data ) ) {
101 - update_site_option( $key, $this->data );
102 - }
103 -
104 - return $this;
105 - }
106 -
107 - /**
108 - * Update queue
109 - *
110 - * @param string $key Key.
111 - * @param array $data Data.
112 - *
113 - * @return $this
114 - */
115 - public function update( $key, $data ) {
116 - if ( ! empty( $data ) ) {
117 - update_site_option( $key, $data );
118 - }
119 -
120 - return $this;
121 - }
122 -
123 - /**
124 - * Delete queue
125 - *
126 - * @param string $key Key.
127 - *
128 - * @return $this
129 - */
130 - public function delete( $key ) {
131 - delete_site_option( $key );
132 -
133 - return $this;
134 - }
135 -
136 - /**
137 - * Generate key
138 - *
139 - * Generates a unique key based on microtime. Queue items are
140 - * given a unique key so that they can be merged upon save.
141 - *
142 - * @param int $length Length.
143 - *
144 - * @return string
145 - */
146 - protected function generate_key( $length = 64 ) {
147 - $unique = md5( microtime() . rand() );
148 - $prepend = $this->identifier . '_batch_';
149 -
150 - return substr( $prepend . $unique, 0, $length );
151 - }
152 -
153 - /**
154 - * Maybe process queue
155 - *
156 - * Checks whether data exists within the queue and that
157 - * the process is not already running.
158 - */
159 - public function maybe_handle() {
160 - // Don't lock up other requests while processing
161 - session_write_close();
162 -
163 - if ( $this->is_process_running() ) {
164 - // Background process already running.
165 - wp_die();
166 - }
167 -
168 - if ( $this->is_queue_empty() ) {
169 - // No data to process.
170 - wp_die();
171 - }
172 -
173 - check_ajax_referer( $this->identifier, 'nonce' );
174 -
175 - $this->handle();
176 -
177 - wp_die();
178 - }
179 -
180 - /**
181 - * Is queue empty
182 - *
183 - * @return bool
184 - */
185 - protected function is_queue_empty() {
186 - global $wpdb;
187 -
188 - $table = $wpdb->options;
189 - $column = 'option_name';
190 -
191 - if ( is_multisite() ) {
192 - $table = $wpdb->sitemeta;
193 - $column = 'meta_key';
194 - }
195 -
196 - $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
197 -
198 - $count = $wpdb->get_var( $wpdb->prepare( "
199 - SELECT COUNT(*)
200 - FROM {$table}
201 - WHERE {$column} LIKE %s
202 - ", $key ) );
203 -
204 - return ( $count > 0 ) ? false : true;
205 - }
206 -
207 - /**
208 - * Is process running
209 - *
210 - * Check whether the current process is already running
211 - * in a background process.
212 - */
213 - protected function is_process_running() {
214 - if ( get_site_transient( $this->identifier . '_process_lock' ) ) {
215 - // Process already running.
216 - return true;
217 - }
218 -
219 - return false;
220 - }
221 -
222 - /**
223 - * Lock process
224 - *
225 - * Lock the process so that multiple instances can't run simultaneously.
226 - * Override if applicable, but the duration should be greater than that
227 - * defined in the time_exceeded() method.
228 - */
229 - protected function lock_process() {
230 - $this->start_time = time(); // Set start time of current process.
231 -
232 - $lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
233 - $lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
234 -
235 - set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
236 - }
237 -
238 - /**
239 - * Unlock process
240 - *
241 - * Unlock the process so that other instances can spawn.
242 - *
243 - * @return $this
244 - */
245 - protected function unlock_process() {
246 - delete_site_transient( $this->identifier . '_process_lock' );
247 -
248 - return $this;
249 - }
250 -
251 - /**
252 - * Get batch
253 - *
254 - * @return stdClass Return the first batch from the queue
255 - */
256 - protected function get_batch() {
257 - global $wpdb;
258 -
259 - $table = $wpdb->options;
260 - $column = 'option_name';
261 - $key_column = 'option_id';
262 - $value_column = 'option_value';
263 -
264 - if ( is_multisite() ) {
265 - $table = $wpdb->sitemeta;
266 - $column = 'meta_key';
267 - $key_column = 'meta_id';
268 - $value_column = 'meta_value';
269 - }
270 -
271 - $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
272 -
273 - $query = $wpdb->get_row( $wpdb->prepare( "
274 - SELECT *
275 - FROM {$table}
276 - WHERE {$column} LIKE %s
277 - ORDER BY {$key_column} ASC
278 - LIMIT 1
279 - ", $key ) );
280 -
281 - $batch = new stdClass();
282 - $batch->key = $query->$column;
283 - $batch->data = maybe_unserialize( $query->$value_column );
284 -
285 - return $batch;
286 - }
287 -
288 - /**
289 - * Handle
290 - *
291 - * Pass each queue item to the task handler, while remaining
292 - * within server memory and time limit constraints.
293 - */
294 - protected function handle() {
295 - $this->lock_process();
296 -
297 - do {
298 - $batch = $this->get_batch();
299 -
300 - foreach ( $batch->data as $key => $value ) {
301 - $task = $this->task( $value );
302 -
303 - if ( false !== $task ) {
304 - $batch->data[ $key ] = $task;
305 - } else {
306 - unset( $batch->data[ $key ] );
307 - }
308 -
309 - if ( $this->time_exceeded() || $this->memory_exceeded() ) {
310 - // Batch limits reached.
311 - break;
312 - }
313 - }
314 -
315 - // Update or delete current batch.
316 - if ( ! empty( $batch->data ) ) {
317 - $this->update( $batch->key, $batch->data );
318 - } else {
319 - $this->delete( $batch->key );
320 - }
321 - } while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
322 -
323 - $this->unlock_process();
324 -
325 - // Start next batch or complete process.
326 - if ( ! $this->is_queue_empty() ) {
327 - $this->dispatch();
328 - } else {
329 - $this->complete();
330 - }
331 -
332 - wp_die();
333 - }
334 -
335 - /**
336 - * Memory exceeded
337 - *
338 - * Ensures the batch process never exceeds 90%
339 - * of the maximum WordPress memory.
340 - *
341 - * @return bool
342 - */
343 - protected function memory_exceeded() {
344 - $memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
345 - $current_memory = memory_get_usage( true );
346 - $return = false;
347 -
348 - if ( $current_memory >= $memory_limit ) {
349 - $return = true;
350 - }
351 -
352 - return apply_filters( $this->identifier . '_memory_exceeded', $return );
353 - }
354 -
355 - /**
356 - * Get memory limit
357 - *
358 - * @return int
359 - */
360 - protected function get_memory_limit() {
361 - if ( function_exists( 'ini_get' ) ) {
362 - $memory_limit = ini_get( 'memory_limit' );
363 - } else {
364 - // Sensible default.
365 - $memory_limit = '128M';
366 - }
367 -
368 - if ( ! $memory_limit || - 1 === intval( $memory_limit ) ) {
369 - // Unlimited, set to 32GB.
370 - $memory_limit = '32000M';
371 - }
372 -
373 - return wp_convert_hr_to_bytes( $memory_limit );
374 - }
375 -
376 - /**
377 - * Time exceeded.
378 - *
379 - * Ensures the batch never exceeds a sensible time limit.
380 - * A timeout limit of 30s is common on shared hosting.
381 - *
382 - * @return bool
383 - */
384 - protected function time_exceeded() {
385 - $finish = $this->start_time + apply_filters( $this->identifier . '_default_time_limit', 20 ); // 20 seconds
386 - $return = false;
387 -
388 - if ( time() >= $finish ) {
389 - $return = true;
390 - }
391 -
392 - return apply_filters( $this->identifier . '_time_exceeded', $return );
393 - }
394 -
395 - /**
396 - * Complete.
397 - *
398 - * Override if applicable, but ensure that the below actions are
399 - * performed, or, call parent::complete().
400 - */
401 - protected function complete() {
402 - // Unschedule the cron healthcheck.
403 - $this->clear_scheduled_event();
404 - }
405 -
406 - /**
407 - * Schedule cron healthcheck
408 - *
409 - * @access public
410 - *
411 - * @param mixed $schedules Schedules.
412 - *
413 - * @return mixed
414 - */
415 - public function schedule_cron_healthcheck( $schedules ) {
416 - $interval = apply_filters( $this->identifier . '_cron_interval', 5 );
417 -
418 - if ( property_exists( $this, 'cron_interval' ) ) {
419 - $interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval );
420 - }
421 -
422 - // Adds every 5 minutes to the existing schedules.
423 - $schedules[ $this->identifier . '_cron_interval' ] = array(
424 - 'interval' => MINUTE_IN_SECONDS * $interval,
425 - 'display' => sprintf( __( 'Every %d Minutes' ), $interval ),
426 - );
427 -
428 - return $schedules;
429 - }
430 -
431 - /**
432 - * Handle cron healthcheck
433 - *
434 - * Restart the background process if not already running
435 - * and data exists in the queue.
436 - */
437 - public function handle_cron_healthcheck() {
438 - if ( $this->is_process_running() ) {
439 - // Background process already running.
440 - exit;
441 - }
442 -
443 - if ( $this->is_queue_empty() ) {
444 - // No data to process.
445 - $this->clear_scheduled_event();
446 - exit;
447 - }
448 -
449 - $this->handle();
450 -
451 - exit;
452 - }
453 -
454 - /**
455 - * Schedule event
456 - */
457 - protected function schedule_event() {
458 - if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
459 - wp_schedule_event( time(), $this->cron_interval_identifier, $this->cron_hook_identifier );
460 - }
461 - }
462 -
463 - /**
464 - * Clear scheduled event
465 - */
466 - protected function clear_scheduled_event() {
467 - $timestamp = wp_next_scheduled( $this->cron_hook_identifier );
468 -
469 - if ( $timestamp ) {
470 - wp_unschedule_event( $timestamp, $this->cron_hook_identifier );
471 - }
472 - }
473 -
474 - /**
475 - * Cancel Process
476 - *
477 - * Stop processing queue items, clear cronjob and delete batch.
478 - *
479 - */
480 - public function cancel_process() {
481 - if ( ! $this->is_queue_empty() ) {
482 - $batch = $this->get_batch();
483 -
484 - $this->delete( $batch->key );
485 -
486 - wp_clear_scheduled_hook( $this->cron_hook_identifier );
487 - }
488 -
489 - }
490 -
491 - /**
492 - * Task
493 - *
494 - * Override this method to perform any actions required on each
495 - * queue item. Return the modified item for further processing
496 - * in the next pass through. Or, return false to remove the
497 - * item from the queue.
498 - *
499 - * @param mixed $item Queue item to iterate over.
500 - *
501 - * @return mixed
502 - */
503 - abstract protected function task( $item );
504 -
505 -}
1 +<?php
2 +/**
3 + * WP Background Process
4 + *
5 + * @package WP-Background-Processing
6 + */
7 +
8 +/**
9 + * Abstract WP_Background_Process class.
10 + *
11 + * @abstract
12 + * @extends WP_Async_Request
13 + */
14 +abstract class WP_Background_Process extends WP_Async_Request {
15 +
16 + /**
17 + * Action
18 + *
19 + * (default value: 'background_process')
20 + *
21 + * @var string
22 + * @access protected
23 + */
24 + protected $action = 'background_process';
25 +
26 + /**
27 + * Start time of current process.
28 + *
29 + * (default value: 0)
30 + *
31 + * @var int
32 + * @access protected
33 + */
34 + protected $start_time = 0;
35 +
36 + /**
37 + * Cron_hook_identifier
38 + *
39 + * @var mixed
40 + * @access protected
41 + */
42 + protected $cron_hook_identifier;
43 +
44 + /**
45 + * Cron_interval_identifier
46 + *
47 + * @var mixed
48 + * @access protected
49 + */
50 + protected $cron_interval_identifier;
51 +
52 + /**
53 + * Initiate new background process
54 + */
55 + public function __construct() {
56 + parent::__construct();
57 +
58 + $this->cron_hook_identifier = $this->identifier . '_cron';
59 + $this->cron_interval_identifier = $this->identifier . '_cron_interval';
60 +
61 + add_action( $this->cron_hook_identifier, array( $this, 'handle_cron_healthcheck' ) );
62 + add_filter( 'cron_schedules', array( $this, 'schedule_cron_healthcheck' ) );
63 + }
64 +
65 + /**
66 + * Dispatch
67 + *
68 + * @access public
69 + * @return array|WP_Error
70 + */
71 + public function dispatch() {
72 + // Schedule the cron healthcheck.
73 + $this->schedule_event();
74 +
75 + // Perform remote post.
76 + return parent::dispatch();
77 + }
78 +
79 + /**
80 + * Push to queue
81 + *
82 + * @param mixed $data Data.
83 + *
84 + * @return $this
85 + */
86 + public function push_to_queue( $data ) {
87 + $this->data[] = $data;
88 +
89 + return $this;
90 + }
91 +
92 + /**
93 + * Save queue
94 + *
95 + * @return $this
96 + */
97 + public function save() {
98 + $key = $this->generate_key();
99 +
100 + if ( ! empty( $this->data ) ) {
101 + update_site_option( $key, $this->data );
102 + }
103 +
104 + return $this;
105 + }
106 +
107 + /**
108 + * Update queue
109 + *
110 + * @param string $key Key.
111 + * @param array $data Data.
112 + *
113 + * @return $this
114 + */
115 + public function update( $key, $data ) {
116 + if ( ! empty( $data ) ) {
117 + update_site_option( $key, $data );
118 + }
119 +
120 + return $this;
121 + }
122 +
123 + /**
124 + * Delete queue
125 + *
126 + * @param string $key Key.
127 + *
128 + * @return $this
129 + */
130 + public function delete( $key ) {
131 + delete_site_option( $key );
132 +
133 + return $this;
134 + }
135 +
136 + /**
137 + * Generate key
138 + *
139 + * Generates a unique key based on microtime. Queue items are
140 + * given a unique key so that they can be merged upon save.
141 + *
142 + * @param int $length Length.
143 + *
144 + * @return string
145 + */
146 + protected function generate_key( $length = 64 ) {
147 + $unique = md5( microtime() . rand() );
148 + $prepend = $this->identifier . '_batch_';
149 +
150 + return substr( $prepend . $unique, 0, $length );
151 + }
152 +
153 + /**
154 + * Maybe process queue
155 + *
156 + * Checks whether data exists within the queue and that
157 + * the process is not already running.
158 + */
159 + public function maybe_handle() {
160 + // Don't lock up other requests while processing
161 + session_write_close();
162 +
163 + if ( $this->is_process_running() ) {
164 + // Background process already running.
165 + wp_die();
166 + }
167 +
168 + if ( $this->is_queue_empty() ) {
169 + // No data to process.
170 + wp_die();
171 + }
172 +
173 + check_ajax_referer( $this->identifier, 'nonce' );
174 +
175 + $this->handle();
176 +
177 + wp_die();
178 + }
179 +
180 + /**
181 + * Is queue empty
182 + *
183 + * @return bool
184 + */
185 + protected function is_queue_empty() {
186 + global $wpdb;
187 +
188 + $table = $wpdb->options;
189 + $column = 'option_name';
190 +
191 + if ( is_multisite() ) {
192 + $table = $wpdb->sitemeta;
193 + $column = 'meta_key';
194 + }
195 +
196 + $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
197 +
198 + $count = $wpdb->get_var( $wpdb->prepare( "
199 + SELECT COUNT(*)
200 + FROM {$table}
201 + WHERE {$column} LIKE %s
202 + ", $key ) );
203 +
204 + return ( $count > 0 ) ? false : true;
205 + }
206 +
207 + /**
208 + * Is process running
209 + *
210 + * Check whether the current process is already running
211 + * in a background process.
212 + */
213 + protected function is_process_running() {
214 + if ( get_site_transient( $this->identifier . '_process_lock' ) ) {
215 + // Process already running.
216 + return true;
217 + }
218 +
219 + return false;
220 + }
221 +
222 + /**
223 + * Lock process
224 + *
225 + * Lock the process so that multiple instances can't run simultaneously.
226 + * Override if applicable, but the duration should be greater than that
227 + * defined in the time_exceeded() method.
228 + */
229 + protected function lock_process() {
230 + $this->start_time = time(); // Set start time of current process.
231 +
232 + $lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
233 + $lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
234 +
235 + set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
236 + }
237 +
238 + /**
239 + * Unlock process
240 + *
241 + * Unlock the process so that other instances can spawn.
242 + *
243 + * @return $this
244 + */
245 + protected function unlock_process() {
246 + delete_site_transient( $this->identifier . '_process_lock' );
247 +
248 + return $this;
249 + }
250 +
251 + /**
252 + * Get batch
253 + *
254 + * @return stdClass Return the first batch from the queue
255 + */
256 + protected function get_batch() {
257 + global $wpdb;
258 +
259 + $table = $wpdb->options;
260 + $column = 'option_name';
261 + $key_column = 'option_id';
262 + $value_column = 'option_value';
263 +
264 + if ( is_multisite() ) {
265 + $table = $wpdb->sitemeta;
266 + $column = 'meta_key';
267 + $key_column = 'meta_id';
268 + $value_column = 'meta_value';
269 + }
270 +
271 + $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
272 +
273 + $query = $wpdb->get_row( $wpdb->prepare( "
274 + SELECT *
275 + FROM {$table}
276 + WHERE {$column} LIKE %s
277 + ORDER BY {$key_column} ASC
278 + LIMIT 1
279 + ", $key ) );
280 +
281 + $batch = new stdClass();
282 + $batch->key = $query->$column;
283 + $batch->data = maybe_unserialize( $query->$value_column );
284 +
285 + return $batch;
286 + }
287 +
288 + /**
289 + * Handle
290 + *
291 + * Pass each queue item to the task handler, while remaining
292 + * within server memory and time limit constraints.
293 + */
294 + protected function handle() {
295 + $this->lock_process();
296 +
297 + do {
298 + $batch = $this->get_batch();
299 +
300 + foreach ( $batch->data as $key => $value ) {
301 + $task = $this->task( $value );
302 +
303 + if ( false !== $task ) {
304 + $batch->data[ $key ] = $task;
305 + } else {
306 + unset( $batch->data[ $key ] );
307 + }
308 +
309 + if ( $this->time_exceeded() || $this->memory_exceeded() ) {
310 + // Batch limits reached.
311 + break;
312 + }
313 + }
314 +
315 + // Update or delete current batch.
316 + if ( ! empty( $batch->data ) ) {
317 + $this->update( $batch->key, $batch->data );
318 + } else {
319 + $this->delete( $batch->key );
320 + }
321 + } while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
322 +
323 + $this->unlock_process();
324 +
325 + // Start next batch or complete process.
326 + if ( ! $this->is_queue_empty() ) {
327 + $this->dispatch();
328 + } else {
329 + $this->complete();
330 + }
331 +
332 + wp_die();
333 + }
334 +
335 + /**
336 + * Memory exceeded
337 + *
338 + * Ensures the batch process never exceeds 90%
339 + * of the maximum WordPress memory.
340 + *
341 + * @return bool
342 + */
343 + protected function memory_exceeded() {
344 + $memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
345 + $current_memory = memory_get_usage( true );
346 + $return = false;
347 +
348 + if ( $current_memory >= $memory_limit ) {
349 + $return = true;
350 + }
351 +
352 + return apply_filters( $this->identifier . '_memory_exceeded', $return );
353 + }
354 +
355 + /**
356 + * Get memory limit
357 + *
358 + * @return int
359 + */
360 + protected function get_memory_limit() {
361 + if ( function_exists( 'ini_get' ) ) {
362 + $memory_limit = ini_get( 'memory_limit' );
363 + } else {
364 + // Sensible default.
365 + $memory_limit = '128M';
366 + }
367 +
368 + if ( ! $memory_limit || - 1 === intval( $memory_limit ) ) {
369 + // Unlimited, set to 32GB.
370 + $memory_limit = '32000M';
371 + }
372 +
373 + return wp_convert_hr_to_bytes( $memory_limit );
374 + }
375 +
376 + /**
377 + * Time exceeded.
378 + *
379 + * Ensures the batch never exceeds a sensible time limit.
380 + * A timeout limit of 30s is common on shared hosting.
381 + *
382 + * @return bool
383 + */
384 + protected function time_exceeded() {
385 + $finish = $this->start_time + apply_filters( $this->identifier . '_default_time_limit', 20 ); // 20 seconds
386 + $return = false;
387 +
388 + if ( time() >= $finish ) {
389 + $return = true;
390 + }
391 +
392 + return apply_filters( $this->identifier . '_time_exceeded', $return );
393 + }
394 +
395 + /**
396 + * Complete.
397 + *
398 + * Override if applicable, but ensure that the below actions are
399 + * performed, or, call parent::complete().
400 + */
401 + protected function complete() {
402 + // Unschedule the cron healthcheck.
403 + $this->clear_scheduled_event();
404 + }
405 +
406 + /**
407 + * Schedule cron healthcheck
408 + *
409 + * @access public
410 + *
411 + * @param mixed $schedules Schedules.
412 + *
413 + * @return mixed
414 + */
415 + public function schedule_cron_healthcheck( $schedules ) {
416 + $interval = apply_filters( $this->identifier . '_cron_interval', 5 );
417 +
418 + if ( property_exists( $this, 'cron_interval' ) ) {
419 + $interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval );
420 + }
421 +
422 + // Adds every 5 minutes to the existing schedules.
423 + $schedules[ $this->identifier . '_cron_interval' ] = array(
424 + 'interval' => MINUTE_IN_SECONDS * $interval,
425 + 'display' => sprintf( __( 'Every %d Minutes' ), $interval ),
426 + );
427 +
428 + return $schedules;
429 + }
430 +
431 + /**
432 + * Handle cron healthcheck
433 + *
434 + * Restart the background process if not already running
435 + * and data exists in the queue.
436 + */
437 + public function handle_cron_healthcheck() {
438 + if ( $this->is_process_running() ) {
439 + // Background process already running.
440 + exit;
441 + }
442 +
443 + if ( $this->is_queue_empty() ) {
444 + // No data to process.
445 + $this->clear_scheduled_event();
446 + exit;
447 + }
448 +
449 + $this->handle();
450 +
451 + exit;
452 + }
453 +
454 + /**
455 + * Schedule event
456 + */
457 + protected function schedule_event() {
458 + if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
459 + wp_schedule_event( time(), $this->cron_interval_identifier, $this->cron_hook_identifier );
460 + }
461 + }
462 +
463 + /**
464 + * Clear scheduled event
465 + */
466 + protected function clear_scheduled_event() {
467 + $timestamp = wp_next_scheduled( $this->cron_hook_identifier );
468 +
469 + if ( $timestamp ) {
470 + wp_unschedule_event( $timestamp, $this->cron_hook_identifier );
471 + }
472 + }
473 +
474 + /**
475 + * Cancel Process
476 + *
477 + * Stop processing queue items, clear cronjob and delete batch.
478 + *
479 + */
480 + public function cancel_process() {
481 + if ( ! $this->is_queue_empty() ) {
482 + $batch = $this->get_batch();
483 +
484 + $this->delete( $batch->key );
485 +
486 + wp_clear_scheduled_hook( $this->cron_hook_identifier );
487 + }
488 +
489 + }
490 +
491 + /**
492 + * Task
493 + *
494 + * Override this method to perform any actions required on each
495 + * queue item. Return the modified item for further processing
496 + * in the next pass through. Or, return false to remove the
497 + * item from the queue.
498 + *
499 + * @param mixed $item Queue item to iterate over.
500 + *
501 + * @return mixed
502 + */
503 + abstract protected function task( $item );
504 +
505 +}