PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.17.0
GiveWP – Donation Plugin and Fundraising Platform v4.17.0
4.17.0 4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 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 All 256 releases
← All changes | includes/class-give-background-updater.php +539 -368 2.3.1 → 4.17.0 View file →
@@ -1,5 +1,8 @@
1 1 <?php
2 +
3 +use Give\Framework\WordPressLibraries\WPBackgroundProcess;
4 +
2 5 /**
3 6 * Background Updater
4 7 *
5 8 * Uses https://github.com/A5hleyRich/wp-background-processing to handle DB
@@ -4,463 +7,631 @@
4 7 *
5 8 * Uses https://github.com/A5hleyRich/wp-background-processing to handle DB
6 9 * updates in the background.
7 10 *
8 - * @class Give_Background_Updater
9 - * @version 2.0.0
10 - * @package Give/Classes
11 - * @category Class
12 - * @author GiveWP
11 + * @package Give/Classes
12 + *
13 + * @class Give_Background_Updater
14 + * @version 2.0.0
15 + * @category Class
16 + * @author GiveWP
17 + *
18 + * @since 2.32.0 updated to extend WPBackgroundProcess
13 19 */
14 -if ( ! defined( 'ABSPATH' ) ) {
15 - exit;
20 +if ( ! defined('ABSPATH')) {
21 + exit;
16 22 }
17 23
18 24 /**
19 25 * Give_Background_Updater Class.
20 26 */
21 -class Give_Background_Updater extends WP_Background_Process {
27 +class Give_Background_Updater extends WPBackgroundProcess
28 +{
22 29
23 - /**
24 - * @var string
25 - */
26 - protected $action = 'give_db_updater';
30 + /**
31 + * @var string
32 + */
33 + protected $action = 'give_db_updater';
27 34
28 - /**
29 - * Dispatch updater.
30 - *
31 - * Updater will still run via cron job if this fails for any reason.
32 - */
33 - public function dispatch() {
34 - if ( give_test_ajax_works() ) {
35 - parent::dispatch();
36 - } elseif ( wp_doing_ajax() ) {
37 - $this->maybe_handle();
38 - }
39 - }
35 + /**
36 + * Dispatch updater.
37 + *
38 + * Updater will still run via cron job if this fails for any reason.
39 + */
40 + public function dispatch()
41 + {
42 + if (give_test_ajax_works()) {
43 + parent::dispatch();
44 + } elseif (wp_doing_ajax()) {
45 + $this->maybe_handle();
46 + }
47 + }
40 48
41 49
42 - /**
43 - * Get all batches.
44 - *
45 - * @since 2.0
46 - * @access public
47 - * @return stdClass
48 - */
49 - public function get_all_batch() {
50 - return parent::get_batch();
51 - }
50 + /**
51 + * Get all batches.
52 + *
53 + * @since 2.0
54 + * @access public
55 + * @return stdClass
56 + */
57 + public function get_all_batch()
58 + {
59 + return $this->get_batch();
60 + }
52 61
53 - /**
54 - * Is queue empty
55 - *
56 - * @since 2.0.3
57 - *
58 - * @return bool
59 - */
60 - public function has_queue() {
61 - return ( ! parent::is_queue_empty() );
62 - }
62 + /**
63 + * Is queue empty
64 + *
65 + * @since 2.0.3
66 + *
67 + * @return bool
68 + */
69 + public function has_queue()
70 + {
71 + return ( ! $this->is_queue_empty());
72 + }
63 73
64 74
65 - /**
66 - * Lock process
67 - *
68 - * Lock the process so that multiple instances can't run simultaneously.
69 - * Override if applicable, but the duration should be greater than that
70 - * defined in the time_exceeded() method.
71 - *
72 - *
73 - * @since 2.0.3
74 - */
75 - protected function lock_process() {
76 - // Check if admin want to pause upgrade.
77 - if( get_option('give_pause_upgrade') ) {
78 - self::flush_cache();
75 + /**
76 + * Lock process
77 + *
78 + * Lock the process so that multiple instances can't run simultaneously.
79 + * Override if applicable, but the duration should be greater than that
80 + * defined in the time_exceeded() method.
81 + *
82 + * @since 2.0.3
83 + */
84 + protected function lock_process()
85 + {
86 + // Check if admin want to pause upgrade.
87 + if (get_option('give_pause_upgrade')) {
88 + self::flush_cache();
79 89
80 - delete_option( 'give_paused_batches' );
90 + delete_option('give_paused_batches');
81 91
82 - Give_Updates::get_instance()->__pause_db_update( true );
92 + Give_Updates::get_instance()->pause_db_update(true);
83 93
84 - delete_option('give_pause_upgrade');
94 + delete_option('give_pause_upgrade');
85 95
86 - /**
87 - * Fire action when pause db updates
88 - *
89 - * @since 2.0.1
90 - */
91 - do_action( 'give_pause_db_upgrade', Give_Updates::get_instance() );
96 + /**
97 + * Fire action when pause db updates
98 + *
99 + * @since 2.0.1
100 + */
101 + do_action('give_pause_db_upgrade', Give_Updates::get_instance());
92 102
93 - wp_die();
94 - }
103 + wp_die();
104 + }
95 105
106 + $this->start_time = time(); // Set start time of current process.
96 107
97 - $this->start_time = time(); // Set start time of current process.
108 + $lock_duration = (property_exists($this, 'queue_lock_time')) ? $this->queue_lock_time : 60; // 1 minute
109 + $lock_duration = apply_filters($this->identifier . '_queue_lock_time', $lock_duration);
98 110
99 - $lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
100 - $lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
111 + set_transient($this->identifier . '_process_lock', microtime(), $lock_duration);
112 + }
101 113
102 - set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
103 - }
114 + /**
115 + * Handle cron healthcheck
116 + *
117 + * Restart the background process if not already running
118 + * and data exists in the queue.
119 + */
120 + public function handle_cron_healthcheck()
121 + {
122 + if ($this->is_process_running() || $this->is_paused_process()) {
123 + // Background process already running.
124 + return;
125 + }
104 126
105 - /**
106 - * Handle cron healthcheck
107 - *
108 - * Restart the background process if not already running
109 - * and data exists in the queue.
110 - */
111 - public function handle_cron_healthcheck() {
112 - if ( $this->is_process_running() || $this->is_paused_process() ) {
113 - // Background process already running.
114 - return;
115 - }
127 + if ($this->is_queue_empty()) {
128 + // No data to process.
129 + $this->clear_scheduled_event();
116 130
117 - if ( $this->is_queue_empty() ) {
118 - // No data to process.
119 - $this->clear_scheduled_event();
131 + return;
132 + }
120 133
121 - return;
122 - }
134 + $this->handle();
135 + }
123 136
124 - $this->handle();
125 - }
137 + /**
138 + * Schedule fallback event.
139 + */
140 + protected function schedule_event()
141 + {
142 + if ( ! wp_next_scheduled($this->cron_hook_identifier) && ! $this->is_paused_process()) {
143 + wp_schedule_event(time() + 10, $this->cron_interval_identifier, $this->cron_hook_identifier);
144 + }
145 + }
126 146
127 - /**
128 - * Schedule fallback event.
129 - */
130 - protected function schedule_event() {
131 - if ( ! wp_next_scheduled( $this->cron_hook_identifier ) && ! $this->is_paused_process() ) {
132 - wp_schedule_event( time() + 10, $this->cron_interval_identifier, $this->cron_hook_identifier );
133 - }
134 - }
147 + /**
148 + * Is queue empty
149 + *
150 + * @since 2.4.5
151 + *
152 + * @return bool
153 + */
154 + protected function is_queue_empty()
155 + {
156 + global $wpdb;
135 157
136 - /**
137 - * Task
138 - *
139 - * Override this method to perform any actions required on each
140 - * queue item. Return the modified item for further processing
141 - * in the next pass through. Or, return false to remove the
142 - * item from the queue.
143 - *
144 - * @param array $update Update info
145 - *
146 - * @return mixed
147 - */
148 - protected function task( $update ) {
149 - // Pause upgrade immediately if admin pausing upgrades.
150 - if( $this->is_paused_process() ) {
151 - wp_die();
152 - }
158 + $table = $wpdb->options;
159 + $column = 'option_name';
153 160
154 - if ( empty( $update ) ) {
155 - return false;
156 - }
161 + $key = $wpdb->esc_like($this->identifier . '_batch_') . '%';
157 162
158 - // Delete cache.
159 - self::flush_cache();
163 + $count = $wpdb->get_var(
164 + $wpdb->prepare(
165 + "
166 + SELECT COUNT(*)
167 + FROM {$table}
168 + WHERE {$column} LIKE %s
169 + ",
170 + $key
171 + )
172 + );
160 173
161 - /* @var Give_Updates $give_updates */
162 - $give_updates = Give_Updates::get_instance();
163 - $resume_update = get_option(
164 - 'give_doing_upgrade',
174 + return ! ($count > 0);
175 + }
165 176
166 - // Default update.
167 - array(
168 - 'update_info' => $update,
169 - 'step' => 1,
170 - 'update' => 1,
171 - 'heading' => sprintf( 'Update %s of {update_count}', 1 ),
172 - 'percentage' => $give_updates->percentage,
173 - 'total_percentage' => 0,
174 - )
175 - );
177 + /**
178 + * Get batch
179 + *
180 + * @since 2.4.5
181 + *
182 + * @return stdClass Return the first batch from the queue
183 + */
184 + protected function get_batch()
185 + {
186 + global $wpdb;
176 187
177 - // Continuously skip update if previous update does not complete yet.
178 - if (
179 - $resume_update['update_info']['id'] !== $update['id'] &&
180 - ! give_has_upgrade_completed( $resume_update['update_info']['id'] )
181 - ) {
182 - return $update;
183 - }
188 + $table = $wpdb->options;
189 + $column = 'option_name';
190 + $key_column = 'option_id';
191 + $value_column = 'option_value';
184 192
185 - // Set params.
186 - $resume_update['update_info'] = $update;
187 - $give_updates->step = absint( $resume_update['step'] );
188 - $give_updates->update = absint( $resume_update['update'] );
189 - $is_parent_update_completed = $give_updates->is_parent_updates_completed( $update );
193 + $key = $wpdb->esc_like($this->identifier . '_batch_') . '%';
190 194
195 + $query = $wpdb->get_row(
196 + $wpdb->prepare(
197 + "
198 + SELECT *
199 + FROM {$table}
200 + WHERE {$column} LIKE %s
201 + ORDER BY {$key_column} ASC
202 + LIMIT 1
203 + ",
204 + $key
205 + )
206 + );
191 207
192 - // Skip update if dependency update does not complete yet.
193 - if ( empty( $is_parent_update_completed ) ) {
194 - // @todo: set error when you have only one update with invalid dependency
195 - if ( ! is_null( $is_parent_update_completed ) ) {
196 - return $update;
197 - }
208 + $batch = new stdClass();
209 + $batch->key = $query->$column;
210 + $batch->data = maybe_unserialize($query->$value_column);
198 211
199 - return false;
200 - }
212 + return $batch;
213 + }
201 214
215 + /**
216 + * Save queue
217 + *
218 + * @since 2.4.5
219 + *
220 + * @return $this
221 + */
222 + public function save()
223 + {
224 + $key = $this->generate_key();
202 225
203 - // Pause upgrade immediately if found following:
204 - // 1. Running update number greater then total update count
205 - // 2. Processing percentage greater then 100%
206 - if( (
207 - 101 < $resume_update['total_percentage'] ) ||
208 - ( $give_updates->get_total_db_update_count() < $resume_update['update'] ) ||
209 - ! in_array( $resume_update['update_info']['id'], $give_updates->get_update_ids() )
210 - ) {
211 - if( ! $this->is_paused_process() ){
212 - $give_updates->__pause_db_update(true);
213 - }
226 + if ( ! empty($this->data)) {
227 + update_option($key, $this->data);
228 + }
214 229
215 - update_option( 'give_upgrade_error', 1, false );
230 + return $this;
231 + }
216 232
217 - $log_data = 'Update Task' . "\n";
218 - $log_data .= "Total update count: {$give_updates->get_total_db_update_count()}\n";
219 - $log_data .= 'Update IDs: ' . print_r( $give_updates->get_update_ids() , true );
220 - $log_data .= 'Update: ' . print_r( $resume_update , true );
233 + /**
234 + * Update queue
235 + *
236 + * @since 2.4.5
237 + *
238 + * @param string $key Key.
239 + * @param array $data Data.
240 + *
241 + * @return $this
242 + */
243 + public function update($key, $data)
244 + {
245 + if ( ! empty($data)) {
246 + update_option($key, $data);
247 + }
221 248
222 - Give()->logs->add( 'Update Error', $log_data, 0, 'update' );
249 + return $this;
250 + }
223 251
224 - wp_die();
225 - }
252 + /**
253 + * Delete queue
254 + *
255 + * @since 2.4.5
256 + *
257 + * @param string $key Key.
258 + *
259 + * @return $this
260 + */
261 + public function delete($key)
262 + {
263 + delete_option($key);
226 264
227 - // Disable cache.
228 - Give_Cache::disable();
265 + return $this;
266 + }
229 267
230 - try{
231 - // Run update.
232 - if ( is_array( $update['callback'] ) ) {
233 - $update['callback'][0]->$update['callback'][1]();
234 - } else {
235 - $update['callback']();
236 - }
237 - } catch ( Exception $e ){
268 + /**
269 + * Is process running
270 + *
271 + * @since 2.4.5
272 + *
273 + * Check whether the current process is already running
274 + * in a background process.
275 + */
276 + public function is_process_running()
277 + {
278 + if (get_transient($this->identifier . '_process_lock')) {
279 + // Process already running.
280 + return true;
281 + }
238 282
239 - if( ! $this->is_paused_process() ){
240 - $give_updates->__pause_db_update(true);
241 - }
283 + return false;
284 + }
242 285
243 - $log_data = 'Update Task' . "\n";
244 - $log_data .= print_r( $resume_update, true ) . "\n\n";
245 - $log_data .= "Error\n {$e->getMessage()}";
286 + /**
287 + * Unlock process
288 + *
289 + * Unlock the process so that other instances can spawn.
290 + *
291 + * @since 2.4.5
292 + *
293 + * @return $this
294 + */
295 + protected function unlock_process()
296 + {
297 + delete_transient($this->identifier . '_process_lock');
246 298
247 - Give()->logs->add( 'Update Error', $log_data, 0, 'update' );
248 - update_option( 'give_upgrade_error', 1, false );
299 + return $this;
300 + }
249 301
250 - wp_die();
251 - }
302 + /**
303 + * Task
304 + *
305 + * Override this method to perform any actions required on each
306 + * queue item. Return the modified item for further processing
307 + * in the next pass through. Or, return false to remove the
308 + * item from the queue.
309 + *
310 + * @param array $update Update info
311 + *
312 + * @return mixed
313 + */
314 + protected function task($update)
315 + {
316 + // Pause upgrade immediately if admin pausing upgrades.
317 + if ($this->is_paused_process()) {
318 + wp_die();
319 + }
252 320
253 - // Set update info.
254 - $doing_upgrade_args = array(
255 - 'update_info' => $update,
256 - 'step' => ++ $give_updates->step,
257 - 'update' => $give_updates->update,
258 - 'heading' => sprintf( 'Update %s of %s', $give_updates->update, get_option( 'give_db_update_count' ) ),
259 - 'percentage' => $give_updates->percentage,
260 - 'total_percentage' => $give_updates->get_db_update_processing_percentage(),
261 - );
321 + if (empty($update)) {
322 + return false;
323 + }
262 324
263 - // Cache upgrade.
264 - update_option( 'give_doing_upgrade', $doing_upgrade_args, false );
325 + // Delete cache.
326 + self::flush_cache();
265 327
266 - // Enable cache.
267 - Give_Cache::enable();
328 + /* @var Give_Updates $give_updates */
329 + $give_updates = Give_Updates::get_instance();
330 + $resume_update = get_option(
331 + 'give_doing_upgrade',
332 + // Default update.
333 + [
334 + 'update_info' => $update,
335 + 'step' => 1,
336 + 'update' => 1,
337 + 'heading' => sprintf('Update %s of {update_count}', 1),
338 + 'percentage' => $give_updates->percentage,
339 + 'total_percentage' => 0,
340 + ]
341 + );
268 342
269 - // Check if current update completed or not.
270 - if ( give_has_upgrade_completed( $update['id'] ) ) {
271 - return false;
272 - }
343 + // Continuously skip update if previous update does not complete yet.
344 + if (
345 + $resume_update['update_info']['id'] !== $update['id'] &&
346 + ! give_has_upgrade_completed($resume_update['update_info']['id'])
347 + ) {
348 + return $update;
349 + }
273 350
274 - return $update;
275 - }
351 + // Set params.
352 + $resume_update['update_info'] = $update;
353 + $give_updates->step = absint($resume_update['step']);
354 + $give_updates->update = absint($resume_update['update']);
355 + $is_parent_update_completed = $give_updates->is_parent_updates_completed($update);
276 356
277 - /**
278 - * Complete
279 - *
280 - * Override if applicable, but ensure that the below actions are
281 - * performed, or, call parent::complete().
282 - */
283 - public function complete() {
284 - if ( $this->is_paused_process() ) {
285 - return false;
286 - }
357 + // Skip update if dependency update does not complete yet.
358 + if (empty($is_parent_update_completed)) {
359 + // @todo: set error when you have only one update with invalid dependency
360 + if ( ! is_null($is_parent_update_completed)) {
361 + return $update;
362 + }
287 363
288 - parent::complete();
364 + return false;
365 + }
289 366
290 - delete_option( 'give_pause_upgrade' );
291 - delete_option( 'give_upgrade_error' );
292 - delete_option( 'give_db_update_count' );
293 - delete_option( 'give_doing_upgrade' );
294 - add_option( 'give_show_db_upgrade_complete_notice', 1, '', false );
367 + // Pause upgrade immediately if found following:
368 + // 1. Running update number greater then total update count
369 + // 2. Processing percentage greater then 100%
370 + if ((
371 + 101 < $resume_update['total_percentage']) ||
372 + ($give_updates->get_total_db_update_count() < $resume_update['update']) ||
373 + ! in_array($resume_update['update_info']['id'], $give_updates->get_update_ids())
374 + ) {
375 + if ( ! $this->is_paused_process()) {
376 + $give_updates->pause_db_update(true);
377 + }
295 378
296 - // Flush cache.
297 - Give_Cache::flush_cache( true );
379 + update_option('give_upgrade_error', 1, false);
298 380
299 - if ( $cache_keys = Give_Cache::get_options_like( '' ) ) {
300 - Give_Cache::delete( $cache_keys );
301 - }
302 - }
381 + $log_data = 'Update Task' . "\n";
382 + $log_data .= "Total update count: {$give_updates->get_total_db_update_count()}\n";
383 + $log_data .= 'Update IDs: ' . print_r($give_updates->get_update_ids(), true);
384 + $log_data .= 'Update: ' . print_r($resume_update, true);
303 385
304 - /**
305 - * Get memory limit
306 - *
307 - * @return int
308 - */
309 - protected function get_memory_limit() {
310 - if ( function_exists( 'ini_get' ) ) {
311 - $memory_limit = ini_get( 'memory_limit' );
312 - } else {
313 - // Sensible default.
314 - $memory_limit = '128M';
315 - }
386 + Give()->logs->add('Update Error', $log_data, 0, 'update');
316 387
317 - if ( ! $memory_limit || '-1' === $memory_limit ) {
318 - // Unlimited, set to 32GB.
319 - $memory_limit = '32000M';
320 - }
388 + wp_die();
389 + }
321 390
322 - return intval( $memory_limit ) * 1024 * 1024;
323 - }
391 + // Disable cache.
392 + Give_Cache::disable();
324 393
325 - /**
326 - * Maybe process queue
327 - *
328 - * Checks whether data exists within the queue and that
329 - * the process is not already running.
330 - */
331 - public function maybe_handle() {
332 - // Don't lock up other requests while processing
333 - session_write_close();
394 + try {
395 + // Run update.
396 + if (is_array($update['callback'])) {
397 + $object = $update['callback'][0];
398 + $method_name = $update['callback'][1];
334 399
335 - if ( $this->is_process_running() || $this->is_paused_process() ) {
336 - // Background process already running.
337 - wp_die();
338 - }
400 + $object->$method_name();
401 + } else {
402 + $update['callback']();
403 + }
404 + } catch (Exception $e) {
405 + if ( ! $this->is_paused_process()) {
406 + $give_updates->pause_db_update(true);
407 + }
339 408
340 - if ( $this->is_queue_empty() ) {
341 - // No data to process.
342 - wp_die();
343 - }
409 + $log_data = 'Update Task' . "\n";
410 + $log_data .= print_r($resume_update, true) . "\n\n";
411 + $log_data .= "Error\n {$e->getMessage()}";
344 412
345 - check_ajax_referer( $this->identifier, 'nonce' );
413 + Give()->logs->add('Update Error', $log_data, 0, 'update');
414 + update_option('give_upgrade_error', 1, false);
346 415
347 - $this->handle();
416 + wp_die();
417 + }
348 418
349 - wp_die();
350 - }
419 + // Set update info.
420 + $doing_upgrade_args = [
421 + 'update_info' => $update,
422 + 'step' => ++$give_updates->step,
423 + 'update' => $give_updates->update,
424 + 'heading' => sprintf('Update %s of %s', $give_updates->update, get_option('give_db_update_count')),
425 + 'percentage' => $give_updates->percentage,
426 + 'total_percentage' => $give_updates->get_db_update_processing_percentage(),
427 + ];
351 428
352 - /**
353 - * Handle
354 - *
355 - * Pass each queue item to the task handler, while remaining
356 - * within server memory and time limit constraints.
357 - */
358 - protected function handle() {
359 - $this->lock_process();
429 + // Cache upgrade.
430 + update_option('give_doing_upgrade', $doing_upgrade_args, false);
360 431
361 - do {
362 - $batch = $this->get_batch();
432 + // Enable cache.
433 + Give_Cache::enable();
363 434
364 - foreach ( $batch->data as $key => $value ) {
365 - $task = $this->task( $value );
435 + // Check if current update completed or not.
436 + if (give_has_upgrade_completed($update['id'])) {
437 + return false;
438 + }
366 439
367 - if ( false !== $task ) {
368 - $batch->data[ $key ] = $task;
369 - } else {
370 - unset( $batch->data[ $key ] );
371 - }
440 + return $update;
441 + }
372 442
373 - if ( $this->time_exceeded() || $this->memory_exceeded() ) {
374 - // Batch limits reached.
375 - break;
376 - }
377 - }
443 + /**
444 + * Complete
445 + *
446 + * Override if applicable, but ensure that the below actions are
447 + * performed, or, call parent::complete().
448 + */
449 + public function complete()
450 + {
451 + if ($this->is_paused_process()) {
452 + return false;
453 + }
378 454
379 - // Update or delete current batch.
380 - if ( ! empty( $batch->data ) ) {
381 - $this->update( $batch->key, $batch->data );
382 - } else {
383 - $this->delete( $batch->key );
384 - }
385 - } while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
455 + parent::complete();
386 456
387 - $this->unlock_process();
457 + delete_option('give_pause_upgrade');
458 + delete_option('give_upgrade_error');
459 + delete_option('give_db_update_count');
460 + delete_option('give_doing_upgrade');
461 + add_option('give_show_db_upgrade_complete_notice', 1, '', false);
388 462
389 - // Start next batch or complete process.
390 - if ( ! $this->is_queue_empty() ) {
463 + // Flush cache.
464 + Give_Cache::flush_cache(true);
391 465
392 - // Dispatch only if ajax works.
393 - if( give_test_ajax_works() ) {
394 - $this->dispatch();
395 - }
396 - } else {
397 - $this->complete();
398 - }
466 + if ($cache_keys = Give_Cache::get_options_like('')) {
467 + Give_Cache::delete($cache_keys);
468 + }
469 + }
399 470
400 - wp_die();
401 - }
471 + /**
472 + * Get memory limit
473 + *
474 + * @return int
475 + */
476 + protected function get_memory_limit()
477 + {
478 + if (function_exists('ini_get')) {
479 + $memory_limit = ini_get('memory_limit');
480 + } else {
481 + // Sensible default.
482 + $memory_limit = '128M';
483 + }
402 484
485 + if ( ! $memory_limit || '-1' === $memory_limit) {
486 + // Unlimited, set to 32GB.
487 + $memory_limit = '32G';
488 + }
403 489
404 - /**
405 - * Check if backgound upgrade paused or not.
406 - *
407 - * @since 2.0
408 - * @access public
409 - * @return bool
410 - */
411 - public function is_paused_process(){
412 - // Delete cache.
413 - wp_cache_delete( 'give_paused_batches', 'options' );
490 + return give_let_to_num($memory_limit);
491 + }
414 492
415 - $paused_batches = get_option('give_paused_batches');
493 + /**
494 + * Maybe process queue
495 + *
496 + * Checks whether data exists within the queue and that
497 + * the process is not already running.
498 + */
499 + public function maybe_handle()
500 + {
501 + // Don't lock up other requests while processing
502 + session_write_close();
416 503
417 - return ! empty( $paused_batches );
418 - }
504 + if ($this->is_process_running() || $this->is_paused_process()) {
505 + // Background process already running.
506 + wp_die();
507 + }
419 508
509 + if ($this->is_queue_empty()) {
510 + // No data to process.
511 + wp_die();
512 + }
420 513
421 - /**
422 - * Get identifier
423 - *
424 - * @since 2.0
425 - * @access public
426 - * @return mixed|string
427 - */
428 - public function get_identifier() {
429 - return $this->identifier;
430 - }
514 + check_ajax_referer($this->identifier, 'nonce');
431 515
432 - /**
433 - * Get cron identifier
434 - *
435 - * @since 2.0
436 - * @access public
437 - * @return mixed|string
438 - */
439 - public function get_cron_identifier() {
440 - return $this->cron_hook_identifier;
441 - }
516 + $this->handle();
442 517
518 + wp_die();
519 + }
443 520
444 - /**
445 - * Flush background update related cache to prevent task to go to stalled state.
446 - *
447 - * @since 2.0.3
448 - */
449 - public static function flush_cache() {
521 + /**
522 + * Handle
523 + *
524 + * Pass each queue item to the task handler, while remaining
525 + * within server memory and time limit constraints.
526 + */
527 + protected function handle()
528 + {
529 + $this->lock_process();
450 530
451 - $options = array(
452 - 'give_completed_upgrades',
453 - 'give_doing_upgrade',
454 - 'give_paused_batches',
455 - 'give_upgrade_error',
456 - 'give_db_update_count',
457 - 'give_pause_upgrade',
458 - 'give_show_db_upgrade_complete_notice',
459 - );
531 + do {
532 + $batch = $this->get_batch();
460 533
534 + foreach ($batch->data as $key => $value) {
535 + $task = $this->task($value);
461 536
462 - foreach ( $options as $option ) {
463 - wp_cache_delete( $option, 'options' );
464 - }
465 - }
537 + if (false !== $task) {
538 + $batch->data[$key] = $task;
539 + } else {
540 + unset($batch->data[$key]);
541 + }
542 +
543 + if ($this->time_exceeded() || $this->memory_exceeded()) {
544 + // Batch limits reached.
545 + break;
546 + }
547 + }
548 +
549 + // Update or delete current batch.
550 + if ( ! empty($batch->data)) {
551 + $this->update($batch->key, $batch->data);
552 + } else {
553 + $this->delete($batch->key);
554 + }
555 + } while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty());
556 +
557 + $this->unlock_process();
558 +
559 + // Start next batch or complete process.
560 + if ( ! $this->is_queue_empty()) {
561 + // Dispatch only if ajax works.
562 + if (give_test_ajax_works()) {
563 + $this->dispatch();
564 + }
565 + } else {
566 + $this->complete();
567 + }
568 +
569 + wp_die();
570 + }
571 +
572 +
573 + /**
574 + * Check if backgound upgrade paused or not.
575 + *
576 + * @since 2.0
577 + * @access public
578 + * @return bool
579 + */
580 + public function is_paused_process()
581 + {
582 + // Delete cache.
583 + wp_cache_delete('give_paused_batches', 'options');
584 +
585 + $paused_batches = Give_Cache_Setting::get_option('give_paused_batches');
586 +
587 + return ! empty($paused_batches);
588 + }
589 +
590 +
591 + /**
592 + * Get identifier
593 + *
594 + * @since 2.0
595 + * @access public
596 + * @return mixed|string
597 + */
598 + public function get_identifier()
599 + {
600 + return $this->identifier;
601 + }
602 +
603 + /**
604 + * Get cron identifier
605 + *
606 + * @since 2.0
607 + * @access public
608 + * @return mixed|string
609 + */
610 + public function get_cron_identifier()
611 + {
612 + return $this->cron_hook_identifier;
613 + }
614 +
615 +
616 + /**
617 + * Flush background update related cache to prevent task to go to stalled state.
618 + *
619 + * @since 2.0.3
620 + */
621 + public static function flush_cache()
622 + {
623 + $options = [
624 + 'give_completed_upgrades',
625 + 'give_doing_upgrade',
626 + 'give_paused_batches',
627 + 'give_upgrade_error',
628 + 'give_db_update_count',
629 + 'give_pause_upgrade',
630 + 'give_show_db_upgrade_complete_notice',
631 + ];
632 +
633 + foreach ($options as $option) {
634 + wp_cache_delete($option, 'options');
635 + }
636 + }
466 637 }