Test Failed
Pull Request — master (#2814)
by Devin
05:29
created

Give_Background_Updater::dispatch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Background Updater
4
 *
5
 * Uses https://github.com/A5hleyRich/wp-background-processing to handle DB
6
 * updates in the background.
7
 *
8
 * @class    Give_Background_Updater
9
 * @version  2.0.0
10
 * @package  Give/Classes
11
 * @category Class
12
 * @author   WordImpress
13
 */
14
if ( ! defined( 'ABSPATH' ) ) {
15
	exit;
16
}
17
18
/**
19
 * Give_Background_Updater Class.
20
 */
21
class Give_Background_Updater extends WP_Background_Process {
22
23
	/**
24
	 * @var string
25
	 */
26
	protected $action = 'give_db_updater';
27
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
		/* @var WP_Background_Process $dispatched */
35
		parent::dispatch();
36
	}
37
38
39
	/**
40
	 * Get all batches.
41
	 *
42
	 * @since  2.0
43
	 * @access public
44
	 * @return stdClass
45
	 */
46
	public function get_all_batch() {
47
		return parent::get_batch();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (get_batch() instead of get_all_batch()). Are you sure this is correct? If so, you might want to change this to $this->get_batch().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
48
	}
49
50
	/**
51
	 * Is queue empty
52
	 *
53
	 * @since 2.0.3
54
	 *
55
	 * @return bool
56
	 */
57
	public function has_queue() {
58
		return ( ! parent::is_queue_empty() );
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (is_queue_empty() instead of has_queue()). Are you sure this is correct? If so, you might want to change this to $this->is_queue_empty().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
59
	}
60
61
62
	/**
63
	 * Lock process
64
	 *
65
	 * Lock the process so that multiple instances can't run simultaneously.
66
	 * Override if applicable, but the duration should be greater than that
67
	 * defined in the time_exceeded() method.
68
	 *
69
	 *
70
	 * @since 2.0.3
71
	 */
72
	protected function lock_process() {
73
		// Check if admin want to pause upgrade.
74
		if( get_option('give_pause_upgrade') ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
75
			self::flush_cache();
76
77
			delete_option( 'give_paused_batches' );
78
79
			Give_Updates::get_instance()->__pause_db_update( true );
80
81
			delete_option('give_pause_upgrade');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
82
83
			/**
84
			 * Fire action when pause db updates
85
			 *
86
			 * @since 2.0.1
87
			 */
88
			do_action( 'give_pause_db_upgrade', Give_Updates::get_instance() );
89
90
			wp_die();
91
		}
92
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
93
94
		$this->start_time = time(); // Set start time of current process.
95
96
		$lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
97
		$lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
98
99
		set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
100
	}
101
102
	/**
103
	 * Handle cron healthcheck
104
	 *
105
	 * Restart the background process if not already running
106
	 * and data exists in the queue.
107
	 */
108
	public function handle_cron_healthcheck() {
109
		if ( $this->is_process_running() || $this->is_paused_process()  ) {
110
			// Background process already running.
111
			return;
112
		}
113
114
		if ( $this->is_queue_empty() ) {
115
			// No data to process.
116
			$this->clear_scheduled_event();
117
118
			return;
119
		}
120
121
		$this->handle();
122
	}
123
124
	/**
125
	 * Schedule fallback event.
126
	 */
127
	protected function schedule_event() {
128
		if ( ! wp_next_scheduled( $this->cron_hook_identifier ) && ! $this->is_paused_process() ) {
129
			wp_schedule_event( time() + 10, $this->cron_interval_identifier, $this->cron_hook_identifier );
130
		}
131
	}
132
133
	/**
134
	 * Task
135
	 *
136
	 * Override this method to perform any actions required on each
137
	 * queue item. Return the modified item for further processing
138
	 * in the next pass through. Or, return false to remove the
139
	 * item from the queue.
140
	 *
141
	 * @param array $update Update info
142
	 *
143
	 * @return mixed
144
	 */
145
	protected function task( $update ) {
146
		// Pause upgrade immediately if admin pausing upgrades.
147
		if( $this->is_paused_process() ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
148
			wp_die();
149
		}
150
151
		if ( empty( $update ) ) {
152
			return false;
153
		}
154
155
		// Delete cache.
156
		self::flush_cache();
157
158
		/* @var  Give_Updates $give_updates */
159
		$give_updates  = Give_Updates::get_instance();
160
		$resume_update = get_option(
161
			'give_doing_upgrade',
162
0 ignored issues
show
Coding Style introduced by
There should be no empty lines in a multi-line function call.
Loading history...
163
			// Default update.
164
			array(
165
				'update_info'      => $update,
166
				'step'             => 1,
167
				'update'           => 1,
168
				'heading'          => sprintf( 'Update %s of {update_count}', 1 ),
169
				'percentage'       => $give_updates->percentage,
170
				'total_percentage' => 0,
171
			)
172
		);
173
174
		// Continuously skip update if previous update does not complete yet.
175
		if (
176
			$resume_update['update_info']['id'] !== $update['id'] &&
177
			! give_has_upgrade_completed( $resume_update['update_info']['id'] )
178
		) {
179
			return $update;
180
		}
181
182
		// Set params.
183
		$resume_update['update_info'] = $update;
184
		$give_updates->step           = absint( $resume_update['step'] );
185
		$give_updates->update         = absint( $resume_update['update'] );
186
		$is_parent_update_completed   = $give_updates->is_parent_updates_completed( $update );
187
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
188
189
		// Skip update if dependency update does not complete yet.
190
		if ( empty( $is_parent_update_completed ) ) {
191
			// @todo: set error when you have only one update with invalid dependency
192
			if ( ! is_null( $is_parent_update_completed ) ) {
193
				return $update;
194
			}
195
196
			return false;
197
		}
198
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
199
200
		// Pause upgrade immediately if found following:
201
		// 1. Running update number greater then total update count
202
		// 2. Processing percentage greater then 100%
203
		if( (
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
204
			101 < $resume_update['total_percentage'] ) ||
205
		    ( $give_updates->get_total_db_update_count() < $resume_update['update'] ) ||
206
		    ! in_array( $resume_update['update_info']['id'], $give_updates->get_update_ids() )
207
		) {
208
			if( ! $this->is_paused_process() ){
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
209
				$give_updates->__pause_db_update(true);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
210
			}
211
212
			update_option( 'give_upgrade_error', 1 );
213
214
			$log_data = 'Update Task' . "\n";
215
			$log_data .= "Total update count: {$give_updates->get_total_db_update_count()}\n";
216
			$log_data .= 'Update IDs: ' . print_r( $give_updates->get_update_ids() , true );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
217
			$log_data .= 'Update: ' . print_r( $resume_update , true );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
218
219
			Give()->logs->add( 'Update Error', $log_data, 0, 'update' );
220
221
			wp_die();
222
		}
223
224
		// Disable cache.
225
		Give_Cache::disable();
226
227
		try{
228
			// Run update.
229
			if ( is_array( $update['callback'] ) ) {
230
				$update['callback'][0]->$update['callback'][1]();
231
			} else {
232
				$update['callback']();
233
			}
234
		} catch ( Exception $e ){
235
236
			if( ! $this->is_paused_process() ){
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
237
				$give_updates->__pause_db_update(true);
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
238
			}
239
240
			$log_data = 'Update Task' . "\n";
241
			$log_data .= print_r( $resume_update, true ) . "\n\n";
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
242
			$log_data .= "Error\n {$e->getMessage()}";
243
244
			Give()->logs->add( 'Update Error', $log_data, 0, 'update' );
245
			update_option( 'give_upgrade_error', 1 );
246
247
			wp_die();
248
		}
249
250
		// Set update info.
251
		$doing_upgrade_args = array(
252
			'update_info'      => $update,
253
			'step'             => ++ $give_updates->step,
254
			'update'           => $give_updates->update,
255
			'heading'          => sprintf( 'Update %s of %s', $give_updates->update, get_option( 'give_db_update_count' ) ),
256
			'percentage'       => $give_updates->percentage,
257
			'total_percentage' => $give_updates->get_db_update_processing_percentage(),
258
		);
259
260
		// Cache upgrade.
261
		update_option( 'give_doing_upgrade', $doing_upgrade_args );
262
263
		// Enable cache.
264
		Give_Cache::enable();
265
266
		// Check if current update completed or not.
267
		if ( give_has_upgrade_completed( $update['id'] ) ) {
268
			return false;
269
		}
270
271
		return $update;
272
	}
273
274
	/**
275
	 * Complete
276
	 *
277
	 * Override if applicable, but ensure that the below actions are
278
	 * performed, or, call parent::complete().
279
	 */
280
	public function complete() {
281
		if ( $this->is_paused_process() ) {
282
			return false;
283
		}
284
285
		parent::complete();
286
287
		delete_option( 'give_pause_upgrade' );
288
		delete_option( 'give_upgrade_error' );
289
		delete_option( 'give_db_update_count' );
290
		delete_option( 'give_doing_upgrade' );
291
		add_option( 'give_show_db_upgrade_complete_notice', 1, '', 'no' );
292
293
		// Flush cache.
294
		Give_Cache::get_instance()->flush_cache();
295
296
		if ( $cache_keys = Give_Cache::get_options_like( '' ) ) {
297
			Give_Cache::delete( $cache_keys );
298
		}
299
	}
300
301
	/**
302
	 * Get memory limit
303
	 *
304
	 * @return int
305
	 */
306
	protected function get_memory_limit() {
307
		if ( function_exists( 'ini_get' ) ) {
308
			$memory_limit = ini_get( 'memory_limit' );
309
		} else {
310
			// Sensible default.
311
			$memory_limit = '128M';
312
		}
313
314
		if ( ! $memory_limit || '-1' === $memory_limit ) {
315
			// Unlimited, set to 32GB.
316
			$memory_limit = '32000M';
317
		}
318
319
		return intval( $memory_limit ) * 1024 * 1024;
320
	}
321
322
	/**
323
	 * Maybe process queue
324
	 *
325
	 * Checks whether data exists within the queue and that
326
	 * the process is not already running.
327
	 */
328
	public function maybe_handle() {
329
		// Don't lock up other requests while processing
330
		session_write_close();
0 ignored issues
show
introduced by
The use of PHP session function session_write_close() is prohibited.
Loading history...
331
332
		if ( $this->is_process_running() || $this->is_paused_process() ) {
333
			// Background process already running.
334
			wp_die();
335
		}
336
337
		if ( $this->is_queue_empty() ) {
338
			// No data to process.
339
			wp_die();
340
		}
341
342
		check_ajax_referer( $this->identifier, 'nonce' );
343
344
		$this->handle();
345
346
		wp_die();
347
	}
348
349
350
	/**
351
	 * Check if backgound upgrade paused or not.
352
	 *
353
	 * @since 2.0
354
	 * @access public
355
	 * @return bool
356
	 */
357
	public function is_paused_process(){
358
		// Delete cache.
359
		wp_cache_delete( 'give_paused_batches', 'options' );
360
361
		$paused_batches = get_option('give_paused_batches');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
362
363
		return ! empty( $paused_batches );
364
	}
365
366
367
	/**
368
	 * Get identifier
369
	 *
370
	 * @since  2.0
371
	 * @access public
372
	 * @return mixed|string
373
	 */
374
	public function get_identifier() {
375
		return $this->identifier;
376
	}
377
378
	/**
379
	 * Get cron identifier
380
	 *
381
	 * @since  2.0
382
	 * @access public
383
	 * @return mixed|string
384
	 */
385
	public function get_cron_identifier() {
386
		return $this->cron_hook_identifier;
387
	}
388
389
390
	/**
391
	 * Flush background update related cache to prevent task to go to stalled state.
392
	 *
393
	 * @since 2.0.3
394
	 */
395
	public static function flush_cache() {
396
397
		$options = array(
398
			'give_completed_upgrades',
399
			'give_doing_upgrade',
400
			'give_paused_batches',
401
			'give_upgrade_error',
402
			'give_db_update_count',
403
			'give_doing_upgrade',
404
			'give_pause_upgrade',
405
			'give_show_db_upgrade_complete_notice',
406
		);
407
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
408
409
		foreach ( $options as $option ) {
410
			wp_cache_delete( $option, 'options' );
411
		}
412
	}
413
}
414