PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 3.0.4
GiveWP – Donation Plugin and Fundraising Platform v3.0.4
4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / includes / libraries / wp-background-process.php
give / includes / libraries Last commit date
googlechartlib 8 years ago array2xml.php 8 years ago browser.php 8 years ago give-pdf.php 6 years ago wp-async-request.php 2 years ago wp-background-process.php 2 years ago
wp-background-process.php
508 lines
1 <?php
2 /**
3 * @deprecated Use src/Framework/WordPressLibraries\WPBackgroundProcess.
4 * WP Background Process
5 *
6 * @package WP-Background-Processing
7 */
8
9 if ( ! class_exists( 'WP_Background_Process' ) ) {
10
11 /**
12 * Abstract WP_Background_Process class.
13 *
14 * @abstract
15 * @extends WP_Async_Request
16 */
17 abstract class WP_Background_Process extends WP_Async_Request {
18
19 /**
20 * Action
21 *
22 * (default value: 'background_process')
23 *
24 * @var string
25 * @access protected
26 */
27 protected $action = 'background_process';
28
29 /**
30 * Start time of current process.
31 *
32 * (default value: 0)
33 *
34 * @var int
35 * @access protected
36 */
37 protected $start_time = 0;
38
39 /**
40 * Cron_hook_identifier
41 *
42 * @var mixed
43 * @access protected
44 */
45 protected $cron_hook_identifier;
46
47 /**
48 * Cron_interval_identifier
49 *
50 * @var mixed
51 * @access protected
52 */
53 protected $cron_interval_identifier;
54
55 /**
56 * Initiate new background process
57 */
58 public function __construct() {
59 parent::__construct();
60
61 $this->cron_hook_identifier = $this->identifier . '_cron';
62 $this->cron_interval_identifier = $this->identifier . '_cron_interval';
63
64 add_action( $this->cron_hook_identifier, array( $this, 'handle_cron_healthcheck' ) );
65 add_filter( 'cron_schedules', array( $this, 'schedule_cron_healthcheck' ) );
66 }
67
68 /**
69 * Dispatch
70 *
71 * @access public
72 * @return void
73 */
74 public function dispatch() {
75 // Schedule the cron healthcheck.
76 $this->schedule_event();
77
78 // Perform remote post.
79 return parent::dispatch();
80 }
81
82 /**
83 * Push to queue
84 *
85 * @param mixed $data Data.
86 *
87 * @return $this
88 */
89 public function push_to_queue( $data ) {
90 $this->data[] = $data;
91
92 return $this;
93 }
94
95 /**
96 * Save queue
97 *
98 * @return $this
99 */
100 public function save() {
101 $key = $this->generate_key();
102
103 if ( ! empty( $this->data ) ) {
104 update_site_option( $key, $this->data );
105 }
106
107 return $this;
108 }
109
110 /**
111 * Update queue
112 *
113 * @param string $key Key.
114 * @param array $data Data.
115 *
116 * @return $this
117 */
118 public function update( $key, $data ) {
119 if ( ! empty( $data ) ) {
120 update_site_option( $key, $data );
121 }
122
123 return $this;
124 }
125
126 /**
127 * Delete queue
128 *
129 * @param string $key Key.
130 *
131 * @return $this
132 */
133 public function delete( $key ) {
134 delete_site_option( $key );
135
136 return $this;
137 }
138
139 /**
140 * Generate key
141 *
142 * Generates a unique key based on microtime. Queue items are
143 * given a unique key so that they can be merged upon save.
144 *
145 * @param int $length Length.
146 *
147 * @return string
148 */
149 protected function generate_key( $length = 64 ) {
150 $unique = md5( microtime() . rand() );
151 $prepend = $this->identifier . '_batch_';
152
153 return substr( $prepend . $unique, 0, $length );
154 }
155
156 /**
157 * Maybe process queue
158 *
159 * Checks whether data exists within the queue and that
160 * the process is not already running.
161 */
162 public function maybe_handle() {
163 // Don't lock up other requests while processing
164 session_write_close();
165
166 if ( $this->is_process_running() ) {
167 // Background process already running.
168 wp_die();
169 }
170
171 if ( $this->is_queue_empty() ) {
172 // No data to process.
173 wp_die();
174 }
175
176 check_ajax_referer( $this->identifier, 'nonce' );
177
178 $this->handle();
179
180 wp_die();
181 }
182
183 /**
184 * Is queue empty
185 *
186 * @return bool
187 */
188 protected function is_queue_empty() {
189 global $wpdb;
190
191 $table = $wpdb->options;
192 $column = 'option_name';
193
194 if ( is_multisite() ) {
195 $table = $wpdb->sitemeta;
196 $column = 'meta_key';
197 }
198
199 $key = $this->identifier . '_batch_%';
200
201 $count = $wpdb->get_var( $wpdb->prepare( "
202 SELECT COUNT(*)
203 FROM {$table}
204 WHERE {$column} LIKE %s
205 ", $key ) );
206
207 return ( $count > 0 ) ? false : true;
208 }
209
210 /**
211 * Is process running
212 *
213 * Check whether the current process is already running
214 * in a background process.
215 */
216 public function is_process_running() {
217 if ( get_site_transient( $this->identifier . '_process_lock' ) ) {
218 // Process already running.
219 return true;
220 }
221
222 return false;
223 }
224
225 /**
226 * Lock process
227 *
228 * Lock the process so that multiple instances can't run simultaneously.
229 * Override if applicable, but the duration should be greater than that
230 * defined in the time_exceeded() method.
231 */
232 protected function lock_process() {
233 $this->start_time = time(); // Set start time of current process.
234
235 $lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
236 $lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
237
238 set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
239 }
240
241 /**
242 * Unlock process
243 *
244 * Unlock the process so that other instances can spawn.
245 *
246 * @return $this
247 */
248 protected function unlock_process() {
249 delete_site_transient( $this->identifier . '_process_lock' );
250
251 return $this;
252 }
253
254 /**
255 * Get batch
256 *
257 * @return stdClass Return the first batch from the queue
258 */
259 protected function get_batch() {
260 global $wpdb;
261
262 $table = $wpdb->options;
263 $column = 'option_name';
264 $key_column = 'option_id';
265 $value_column = 'option_value';
266
267 if ( is_multisite() ) {
268 $table = $wpdb->sitemeta;
269 $column = 'meta_key';
270 $key_column = 'meta_id';
271 $value_column = 'meta_value';
272 }
273
274 $key = $this->identifier . '_batch_%';
275
276 $query = $wpdb->get_row( $wpdb->prepare( "
277 SELECT *
278 FROM {$table}
279 WHERE {$column} LIKE %s
280 ORDER BY {$key_column} ASC
281 LIMIT 1
282 ", $key ) );
283
284 $batch = new stdClass();
285 $batch->key = $query->$column;
286 $batch->data = maybe_unserialize( $query->$value_column );
287
288 return $batch;
289 }
290
291 /**
292 * Handle
293 *
294 * Pass each queue item to the task handler, while remaining
295 * within server memory and time limit constraints.
296 */
297 protected function handle() {
298 $this->lock_process();
299
300 do {
301 $batch = $this->get_batch();
302
303 foreach ( $batch->data as $key => $value ) {
304 $task = $this->task( $value );
305
306 if ( false !== $task ) {
307 $batch->data[ $key ] = $task;
308 } else {
309 unset( $batch->data[ $key ] );
310 }
311
312 if ( $this->time_exceeded() || $this->memory_exceeded() ) {
313 // Batch limits reached.
314 break;
315 }
316 }
317
318 // Update or delete current batch.
319 if ( ! empty( $batch->data ) ) {
320 $this->update( $batch->key, $batch->data );
321 } else {
322 $this->delete( $batch->key );
323 }
324 } while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
325
326 $this->unlock_process();
327
328 // Start next batch or complete process.
329 if ( ! $this->is_queue_empty() ) {
330 $this->dispatch();
331 } else {
332 $this->complete();
333 }
334
335 wp_die();
336 }
337
338 /**
339 * Memory exceeded
340 *
341 * Ensures the batch process never exceeds 90%
342 * of the maximum WordPress memory.
343 *
344 * @return bool
345 */
346 protected function memory_exceeded() {
347 $memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
348 $current_memory = memory_get_usage( true );
349 $return = false;
350
351 if ( $current_memory >= $memory_limit ) {
352 $return = true;
353 }
354
355 return apply_filters( $this->identifier . '_memory_exceeded', $return );
356 }
357
358 /**
359 * Get memory limit
360 *
361 * @return int
362 */
363 protected function get_memory_limit() {
364 if ( function_exists( 'ini_get' ) ) {
365 $memory_limit = ini_get( 'memory_limit' );
366 } else {
367 // Sensible default.
368 $memory_limit = '128M';
369 }
370
371 if ( ! $memory_limit || -1 === $memory_limit ) {
372 // Unlimited, set to 32GB.
373 $memory_limit = '32000M';
374 }
375
376 return intval( $memory_limit ) * 1024 * 1024;
377 }
378
379 /**
380 * Time exceeded.
381 *
382 * Ensures the batch never exceeds a sensible time limit.
383 * A timeout limit of 30s is common on shared hosting.
384 *
385 * @return bool
386 */
387 protected function time_exceeded() {
388 $finish = $this->start_time + apply_filters( $this->identifier . '_default_time_limit', 20 ); // 20 seconds
389 $return = false;
390
391 if ( time() >= $finish ) {
392 $return = true;
393 }
394
395 return apply_filters( $this->identifier . '_time_exceeded', $return );
396 }
397
398 /**
399 * Complete.
400 *
401 * Override if applicable, but ensure that the below actions are
402 * performed, or, call parent::complete().
403 */
404 protected function complete() {
405 // Unschedule the cron healthcheck.
406 $this->clear_scheduled_event();
407 }
408
409 /**
410 * Schedule cron healthcheck
411 *
412 * @access public
413 * @param mixed $schedules Schedules.
414 * @return mixed
415 */
416 public function schedule_cron_healthcheck( $schedules ) {
417 $interval = apply_filters( $this->identifier . '_cron_interval', 5 );
418
419 if ( property_exists( $this, 'cron_interval' ) ) {
420 $interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval_identifier );
421 }
422
423 // Adds every 5 minutes to the existing schedules.
424 $schedules[ $this->identifier . '_cron_interval' ] = array(
425 'interval' => MINUTE_IN_SECONDS * $interval,
426 'display' => sprintf( __( 'Every %d Minutes', 'give' ), $interval ),
427 );
428
429 return $schedules;
430 }
431
432 /**
433 * Handle cron healthcheck
434 *
435 * Restart the background process if not already running
436 * and data exists in the queue.
437 */
438 public function handle_cron_healthcheck() {
439 if ( $this->is_process_running() ) {
440 // Background process already running.
441 exit;
442 }
443
444 if ( $this->is_queue_empty() ) {
445 // No data to process.
446 $this->clear_scheduled_event();
447 exit;
448 }
449
450 $this->handle();
451
452 exit;
453 }
454
455 /**
456 * Schedule event
457 */
458 protected function schedule_event() {
459 if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
460 wp_schedule_event( time(), $this->cron_interval_identifier, $this->cron_hook_identifier );
461 }
462 }
463
464 /**
465 * Clear scheduled event
466 */
467 protected function clear_scheduled_event() {
468 $timestamp = wp_next_scheduled( $this->cron_hook_identifier );
469
470 if ( $timestamp ) {
471 wp_unschedule_event( $timestamp, $this->cron_hook_identifier );
472 }
473 }
474
475 /**
476 * Cancel Process
477 *
478 * Stop processing queue items, clear cronjob and delete batch.
479 *
480 */
481 public function cancel_process() {
482 if ( ! $this->is_queue_empty() ) {
483 $batch = $this->get_batch();
484
485 $this->delete( $batch->key );
486
487 wp_clear_scheduled_hook( $this->cron_hook_identifier );
488 }
489
490 }
491
492 /**
493 * Task
494 *
495 * Override this method to perform any actions required on each
496 * queue item. Return the modified item for further processing
497 * in the next pass through. Or, return false to remove the
498 * item from the queue.
499 *
500 * @param mixed $item Queue item to iterate over.
501 *
502 * @return mixed
503 */
504 abstract protected function task( $item );
505
506 }
507 }
508