Test Failed
Push — feature/upgrdae-auto-pause ( 36ce2e...015823 )
by Ravinder
04:41
created

Give_Updates   D

Complexity

Total Complexity 137

Size/Duplication

Total Lines 1055
Duplicated Lines 2.94 %

Coupling/Cohesion

Components 3
Dependencies 5

Importance

Changes 0
Metric Value
dl 31
loc 1055
rs 4.4249
c 0
b 0
f 0
wmc 137
lcom 3
cbo 5

33 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 2 1
C register() 0 29 7
A get_instance() 0 7 2
B __register_plugin_addon_updates() 0 12 5
A __register_upgrade() 0 12 2
B setup() 0 27 2
C __change_donations_label() 0 27 8
C __register_menu() 0 47 9
B __redirect_admin() 0 14 5
C __pause_db_update() 13 41 8
C __restart_db_update() 9 35 7
D __health_background_update() 0 96 21
C __show_notice() 9 117 12
A render_complete_page() 0 3 1
A render_page() 0 3 1
B run_db_update() 0 25 4
A __flush_resume_updates() 0 11 2
A __give_start_updating() 0 19 4
A __give_db_updates_info() 0 17 2
B send_ajax_response() 0 31 3
A set_percentage() 0 7 3
B is_parent_updates_completed() 0 23 5
A is_doing_updates() 0 3 1
A has_valid_dependency() 0 14 1
C get_updates() 0 33 8
A get_total_plugin_update_count() 0 3 1
A get_total_update_count() 0 6 1
A get_pending_db_update_count() 0 3 1
A get_total_db_update_count() 0 3 1
A get_total_new_db_update_count() 0 5 2
A get_running_db_update() 0 7 2
A get_db_update_processing_percentage() 0 20 4
A get_update_ids() 0 6 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Give_Updates often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Give_Updates, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Class Give_Updates
5
 *
6
 * @since 1.8.12
7
 */
8
class Give_Updates {
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
9
10
	/**
11
	 * Instance.
12
	 *
13
	 * @since
14
	 * @access static
15
	 * @var
16
	 */
17
	static private $instance;
18
19
	/**
20
	 * Instance.
21
	 *
22
	 * @since
23
	 * @access public
24
	 * @var Give_Background_Updater
25
	 */
26
	static public $background_updater;
27
28
	/**
29
	 * Updates
30
	 *
31
	 * @since  1.8.12
32
	 * @access private
33
	 * @var array
34
	 */
35
	private $updates = array();
36
37
	/**
38
	 * Current update percentage number
39
	 *
40
	 * @since  1.8.12
41
	 * @access private
42
	 * @var array
43
	 */
44
	public $percentage = 0;
45
46
	/**
47
	 * Current update step number
48
	 *
49
	 * @since  1.8.12
50
	 * @access private
51
	 * @var array
52
	 */
53
	public $step = 1;
54
55
	/**
56
	 * Current update number
57
	 *
58
	 * @since  1.8.12
59
	 * @access private
60
	 * @var array
61
	 */
62
	public $update = 1;
63
64
	/**
65
	 * Singleton pattern.
66
	 *
67
	 * @since  1.8.12
68
	 * @access private
69
	 *
70
	 * @param Give_Updates .
71
	 */
72
	private function __construct() {
73
	}
74
75
	/**
76
	 * Register updates
77
	 *
78
	 * @since  1.8.12
79
	 * @access public
80
	 *
81
	 * @param array $args
82
	 */
83
	public function register( $args ) {
84
		$args_default = array(
85
			'id'       => '',
86
			'version'  => '',
87
			'callback' => '',
88
		);
89
90
		$args = wp_parse_args( $args, $args_default );
91
92
		// You can only register database upgrade.
93
		$args['type'] = 'database';
94
95
		// Bailout.
96
		if (
97
			empty( $args['id'] ) ||
98
			empty( $args['version'] ) ||
99
			empty( $args['callback'] ) ||
100
			! is_callable( $args['callback'] )
101
		) {
102
			return;
103
		}
104
105
		// Change depend param to array.
106
		if ( isset( $args['depend'] ) && is_string( $args['depend'] ) ) {
107
			$args['depend'] = array( $args['depend'] );
108
		}
109
110
		$this->updates[ $args['type'] ][] = $args;
111
	}
112
113
	/**
114
	 * Get instance.
115
	 *
116
	 * @since
117
	 * @access static
118
	 * @return static
119
	 */
120
	static function get_instance() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
121
		if ( is_null( self::$instance ) ) {
122
			self::$instance = new self();
123
		}
124
125
		return self::$instance;
126
	}
127
128
	/**
129
	 *
130
	 * Setup hook
131
	 *
132
	 * @since  1.8.12
133
	 * @access public
134
	 */
135
	public function setup() {
136
		/**
137
		 * Load file
138
		 */
139
		require_once GIVE_PLUGIN_DIR . 'includes/class-give-background-updater.php';
140
		require_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/upgrade-functions.php';
141
142
		self::$background_updater = new Give_Background_Updater();
143
144
		/**
145
		 * Setup hooks.
146
		 */
147
		add_action( 'init', array( $this, '__register_upgrade' ), 9999 );
148
		add_action( 'give_set_upgrade_completed', array( $this, '__flush_resume_updates' ), 9999 );
149
		add_action( 'wp_ajax_give_db_updates_info', array( $this, '__give_db_updates_info' ) );
150
		add_action( 'wp_ajax_give_run_db_updates', array( $this, '__give_start_updating' ) );
151
		add_action( 'admin_init', array( $this, '__redirect_admin' ) );
152
		add_action( 'admin_init', array( $this, '__pause_db_update' ), -1 );
153
		add_action( 'admin_init', array( $this, '__restart_db_update' ), -1 );
154
		add_action( 'admin_notices', array( $this, '__show_notice' ) );
155
		add_action( 'give_restart_db_upgrade', array( $this, '__health_background_update' ) );
156
157
		if ( is_admin() ) {
158
			add_action( 'admin_init', array( $this, '__change_donations_label' ), 9999 );
159
			add_action( 'admin_menu', array( $this, '__register_menu' ), 9999 );
160
		}
161
	}
162
163
	/**
164
	 * Register plugin add-on updates.
165
	 *
166
	 * @since  1.8.12
167
	 * @access public
168
	 */
169
	public function __register_plugin_addon_updates() {
0 ignored issues
show
Coding Style introduced by
Method name "Give_Updates::__register_plugin_addon_updates" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
170
		$addons         = give_get_plugins();
171
		$plugin_updates = get_plugin_updates();
172
173
		foreach ( $addons as $key => $info ) {
174
			if ( 'active' != $info['Status'] || 'add-on' != $info['Type'] || empty( $plugin_updates[ $key ] ) ) {
175
				continue;
176
			}
177
178
			$this->updates['plugin'][] = array_merge( $info, (array) $plugin_updates[ $key ] );
179
		}
180
	}
181
182
183
	/**
184
	 * Fire custom action hook to register updates
185
	 *
186
	 * @since  1.8.12
187
	 * @access public
188
	 */
189
	public function __register_upgrade() {
0 ignored issues
show
Coding Style introduced by
Method name "Give_Updates::__register_upgrade" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
190
		if ( ! is_admin() ) {
191
			return;
192
		}
193
194
		/**
195
		 * Fire the hook
196
		 *
197
		 * @since 1.8.12
198
		 */
199
		do_action( 'give_register_updates', $this );
200
	}
201
202
	/**
203
	 * Rename `Donations` menu title if updates exists
204
	 *
205
	 * @since  1.8.12
206
	 * @access public
207
	 */
208
	function __change_donations_label() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Coding Style introduced by
Method name "Give_Updates::__change_donations_label" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
209
		global $menu;
210
211
		// Bailout.
212
		if ( empty( $menu ) || ! $this->get_total_update_count() ) {
213
			return;
214
		}
215
216
		$is_update = ( $this->is_doing_updates() && ! self::$background_updater->is_paused_process() );
217
218
		foreach ( $menu as $index => $menu_item ) {
219
			if ( 'edit.php?post_type=give_forms' !== $menu_item[2] ) {
220
				continue;
221
			}
222
223
			$menu[ $index ][0] = sprintf(
224
				'%1$s <span class="update-plugins"><span class="plugin-count give-update-progress-count">%2$s%3$s</span></span>',
225
				__( 'Donations', 'give' ),
226
				$is_update ?
227
					$this->get_db_update_processing_percentage() :
228
					$this->get_total_update_count(),
229
				$is_update ? '%' : ''
230
			);
231
232
			break;
233
		}
234
	}
235
236
	/**
237
	 * Register updates menu
238
	 *
239
	 * @since  1.8.12
240
	 * @access public
241
	 */
242
	public function __register_menu() {
0 ignored issues
show
Coding Style introduced by
Method name "Give_Updates::__register_menu" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
243
		// Bailout.
244
		if( ! give_test_ajax_works() ) {
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...
245
			return;
246
		}
247
248
		// Load plugin updates.
249
		$this->__register_plugin_addon_updates();
250
251
		// Bailout.
252
		if ( ! $this->get_total_update_count() ) {
253
			// Show complete update message if still on update setting page.
254
			if ( isset( $_GET['page'] ) && 'give-updates' === $_GET['page'] ) {
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
255
				// Upgrades
256
				add_submenu_page(
257
					'edit.php?post_type=give_forms',
258
					esc_html__( 'Give Updates Complete', 'give' ),
259
					__( 'Updates', 'give' ),
260
					'manage_give_settings',
261
					'give-updates',
262
					array( $this, 'render_complete_page' )
263
				);
264
			}
265
266
			return;
267
		}
268
269
		$is_update = ( $this->is_doing_updates() && ! self::$background_updater->is_paused_process() );
270
271
		// Upgrades
272
		add_submenu_page(
273
			'edit.php?post_type=give_forms',
274
			esc_html__( 'Give Updates', 'give' ),
275
			sprintf(
276
				'%1$s <span class="update-plugins"%2$s><span class="plugin-count give-update-progress-count">%3$s%4$s</span></span>',
277
				__( 'Updates', 'give' ),
278
				isset( $_GET['give-pause-db-upgrades'] ) ? ' style="display:none;"' : '',
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
279
				$is_update ?
280
					$this->get_db_update_processing_percentage() :
281
					$this->get_total_update_count(),
282
				$is_update ? '%' : ''
283
			),
284
			'manage_give_settings',
285
			'give-updates',
286
			array( $this, 'render_page' )
287
		);
288
	}
289
290
291
	/**
292
	 * Show update related notices
293
	 *
294
	 * @since  2.0
295
	 * @access public
296
	 */
297
	public function __redirect_admin() {
0 ignored issues
show
Coding Style introduced by
Method name "Give_Updates::__redirect_admin" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
298
		// Show db upgrade completed notice.
299
		if (
300
			! wp_doing_ajax() &&
301
			current_user_can( 'manage_give_settings' ) &&
302
			get_option( 'give_show_db_upgrade_complete_notice' ) &&
303
			! isset( $_GET['give-db-update-completed'] )
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
304
		) {
305
			delete_option( 'give_show_db_upgrade_complete_notice' );
306
307
			wp_redirect( add_query_arg( array( 'give-db-update-completed' => 'give_db_upgrade_completed' ) ) );
308
			exit();
309
		}
310
	}
311
312
313
	/**
314
	 * Pause db upgrade
315
	 *
316
	 * @since  2.0.1
317
	 * @access public
318
	 *
319
	 * @param bool $force
320
	 *
321
	 * @return bool
322
	 */
323
	public function __pause_db_update( $force = false ) {
0 ignored issues
show
Coding Style introduced by
Method name "Give_Updates::__pause_db_update" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
324
		// Bailout.
325 View Code Duplication
		if (
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
326
			! $force &&
327
			(
328
				wp_doing_ajax() ||
329
				! isset( $_GET['page'] ) ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
330
				'give-updates' !== $_GET['page'] ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
331
				! isset( $_GET['give-pause-db-upgrades'] ) ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
332
				self::$background_updater->is_paused_process()
333
			)
334
335
		) {
336
			return false;
337
		}
338
339
		$batch = self::$background_updater->get_all_batch();
340
341
		if ( ! empty( $batch ) ) {
342
			// Delete cache if any.
343
			wp_cache_delete( 'give_upgrade_error', 'options' );
344
			wp_cache_delete( 'give_paused_batches', 'options' );
345
346
			delete_option('give_upgrade_error');
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...
347
			update_option( 'give_paused_batches', $batch,  'no' );
348
			delete_option( $batch->key );
349
			delete_site_transient( self::$background_updater->get_identifier() . '_process_lock' );
350
			wp_clear_scheduled_hook( self::$background_updater->get_cron_identifier() );
351
352
			Give()->logs->add( 'Update Pause', print_r( $batch, true ), 0, 'update' );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
353
354
			/**
355
			 * Fire action when pause db updates
356
			 *
357
			 * @since 2.0.1
358
			 */
359
			do_action( 'give_pause_db_upgrade', $this );
360
		}
361
362
		return true;
363
	}
364
365
	/**
366
	 * Restart db upgrade
367
	 *
368
	 * @since  2.0.1
369
	 * @access public
370
	 *
371
	 * @return bool
372
	 */
373
	public function __restart_db_update() {
0 ignored issues
show
Coding Style introduced by
Method name "Give_Updates::__restart_db_update" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
374
		// Bailout.
375 View Code Duplication
		if (
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
376
			wp_doing_ajax() ||
377
			! isset( $_GET['page'] ) ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
378
			'give-updates' !== $_GET['page'] ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
379
			! isset( $_GET['give-restart-db-upgrades'] ) ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
380
			! self::$background_updater->is_paused_process()
381
		) {
382
			return false;
383
		}
384
385
		wp_cache_delete( 'give_paused_batches', 'options' );
386
		$batch = get_option( 'give_paused_batches' );
387
388
		if ( ! empty( $batch ) ) {
389
			wp_cache_delete( $batch->key, 'options' );
390
			update_option( $batch->key, $batch->data );
391
392
			delete_option( 'give_paused_batches' );
393
394
			Give()->logs->add( 'Update Restart', print_r( $batch, true ), 0, 'update' );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
395
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
396
397
			/** Fire action when restart db updates
398
			 *
399
			 * @since 2.0.1
400
			 */
401
			do_action( 'give_restart_db_upgrade', $this );
402
403
			self::$background_updater->dispatch();
404
		}
405
406
		return true;
407
	}
408
409
	/**
410
	 * Health check for updates.
411
	 *
412
	 * @since  2.0
413
	 * @access public
414
	 *
415
	 * @param Give_Updates $give_updates
416
	 */
417
	public function __health_background_update( $give_updates ) {
0 ignored issues
show
Coding Style introduced by
Method name "Give_Updates::__health_background_update" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
418
		if ( ! $this->is_doing_updates() ) {
419
			return;
420
		}
421
422
		wp_cache_delete( 'give_paused_batches', 'options' );
423
424
		$batch                = Give_Updates::$background_updater->get_all_batch();
425
		$batch_data_count     = count( $batch->data );
426
		$all_updates          = $give_updates->get_updates( 'database', 'all' );
427
		$all_update_ids       = wp_list_pluck( $all_updates, 'id' );
428
		$all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : array();
429
		$log_data             = '';
430
		$doing_upgrade_args   = get_option( 'give_doing_upgrade' );
431
432
		if( ! empty( $doing_upgrade_args ) ) {
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...
433
			$log_data .= 'Doing update:' . "\n";
434
			$log_data .= print_r( $doing_upgrade_args, true ) . "\n";
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
435
		}
436
437
		if ( ! empty( $batch->data ) ) {
438
439
			foreach ( $batch->data as $index => $update ) {
440
				$log_data = print_r( $update, true ) . "\n";
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
441
442
				if ( ! is_callable( $update['callback'] ) ) {
443
					$log_data .= 'Removing missing callback update: ' . "{$update['id']}\n";
444
					unset( $batch->data[ $index ] );
445
				}
446
447
				if ( ! empty( $update['depend'] ) ) {
448
449
					foreach ( $update['depend'] as $depend ) {
450
						if ( give_has_upgrade_completed( $depend ) ) {
451
							$log_data .= 'Completed update: ' . "{$depend}\n";
452
							continue;
453
						}
454
455
						if ( in_array( $depend, $all_update_ids ) && ! in_array( $depend, $all_batch_update_ids ) ) {
456
							$log_data .= 'Adding missing update: ' . "{$depend}\n";
457
							array_unshift( $batch->data, $all_updates[ array_search( $depend, $all_update_ids ) ] );
458
						}
459
					}
460
				}
461
			}
462
		}
463
464
		if ( $new_updates = $this->get_updates( 'database', 'new' ) ) {
465
			$all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : array();
466
467
			foreach ( $new_updates as $index => $new_update ) {
468
				if ( give_has_upgrade_completed( $new_update['id'] ) || in_array( $new_update['id'], $all_batch_update_ids ) ) {
469
					unset( $new_updates[ $index ] );
470
				}
471
			}
472
473
			if ( ! empty( $new_updates ) ) {
474
				$log_data .= 'Adding new update: ' . "\n";
475
				$log_data .= print_r( $new_updates, true ) . "\n";
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
476
477
				$batch->data = array_merge( (array) $batch->data, $new_updates );
478
				update_option( 'give_db_update_count', ( absint( get_option( 'give_db_update_count' ) ) + count( $new_updates ) ) );
479
			}
480
		}
481
482
		if ( $batch_data_count !== count( $batch->data ) ) {
483
			$log_data .= 'Updating batch' . "\n";
484
			$log_data .= print_r( $batch, true );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
485
486
			$doing_upgrade_args['heading']          = sprintf( 'Update %s of %s', $doing_upgrade_args['update'], get_option( 'give_db_update_count' ) );
487
			$doing_upgrade_args['total_percentage'] = $this->get_db_update_processing_percentage();
488
			update_option( 'give_doing_upgrade', $doing_upgrade_args );
489
490
			if ( ! empty( $batch->key ) ) {
491
				wp_cache_delete( $batch->key, 'options' );
492
				update_option( $batch->key, $batch->data );
493
			} else {
494
495
				update_option( 'give_db_update_count', count( $batch->data ) );
496
497
				$doing_upgrade_args['update']  = $give_updates->update;
498
				$doing_upgrade_args['heading'] = sprintf( 'Update %s of %s', 1, count( $batch->data ) );
499
500
				update_option( 'give_doing_upgrade', $doing_upgrade_args );
501
502
				foreach ( $batch->data as $data ) {
503
					Give_Updates::$background_updater->push_to_queue( $data );
504
				}
505
506
				Give_Updates::$background_updater->save();
507
			}
508
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
509
510
			Give()->logs->add( 'Update Health Check', $log_data, 0, 'update' );
511
		}
512
	}
513
514
515
	/**
516
	 * Show update related notices
517
	 *
518
	 * @since  2.0
519
	 * @access public
520
	 */
521
	public function __show_notice() {
0 ignored issues
show
Coding Style introduced by
Method name "Give_Updates::__show_notice" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
522
		// Bailout.
523
		if ( ! current_user_can( 'manage_give_settings' ) ) {
524
			return;
525
		}
526
527
		// Run DB updates.
528
		if ( ! empty( $_GET['give-run-db-update'] ) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
529
			$this->run_db_update();
530
		}
531
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
532
533
		// Bailout.
534
		if ( isset( $_GET['page'] ) && 'give-updates' === $_GET['page'] ) {
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
535
			return;
536
		}
537
538
		// Show notice if upgrade paused.
539
		if ( self::$background_updater->is_paused_process() ) {
540
			ob_start();
541
542
			if ( ! get_option( 'give_upgrade_error' ) ):
543
				?>
544
				<strong><?php _e( 'Database Update', 'give' ); ?></strong>
545
				&nbsp;&#8211;&nbsp;<?php _e( 'GiveWP needs to update your database to the latest version. The following process will make updates to your site\'s database. Please create a backup before proceeding.', 'give' ); ?>
546
				<br>
547
				<br>
548
				<a href="<?php echo esc_url( add_query_arg( array( 'give-restart-db-upgrades' => 1 ), admin_url( 'edit.php?post_type=give_forms&page=give-updates' ) ) ); ?>" class="button button-primary give-restart-updater-btn">
549
					<?php _e( 'Restart the updater', 'give' ); ?>
550
				</a>
551
				<script type="text/javascript">
552
					jQuery('.give-restart-updater-btn').click('click', function () {
553
						return window.confirm('<?php echo esc_js( __( 'It is recommended that you backup your database before proceeding. Do you want to run the update now?', 'give' ) ); ?>'); // jshint ignore:line
554
					});
555
				</script>
556 View Code Duplication
			<?php else: ?>
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
557
				<strong><?php _e( 'Database Update', 'give' ); ?></strong>
558
				&nbsp;&#8211;&nbsp;<?php echo sprintf(
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'sprintf'
Loading history...
559
					'%s <a href="%s" target="_blank">%s</a>.',
560
					__( 'Database updates stop automatically because some unexpected issue occur during upgrade. Please contact', 'give' ),
561
					esc_url( 'https://givewp.com/support/' ),
562
					__( 'GiveWP support', 'give' )
563
				); ?>
564
			<?php
565
			endif;
566
			$desc_html = ob_get_clean();
567
568
			Give()->notices->register_notice( array(
569
				'id'          => 'give_upgrade_db',
570
				'type'        => 'error',
571
				'dismissible' => false,
572
				'description' => $desc_html,
573
			) );
574
		}
575
576
		// Bailout if doing upgrades.
577
		if( $this->is_doing_updates() ) {
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...
578
			return;
579
		}
580
581
		// Show notice if ajax is not working.
582
		if ( ! give_test_ajax_works() ) {
583
			Give()->notices->register_notice(
584
				array(
585
					'id'          => 'give_db_upgrade_ajax_inaccessible',
586
					'type'        => 'error',
587
					'description' => sprintf( '%1$s <a href="%2$s" target="_blank">%3$s</a>', __( 'Give needs to upgrade the database but cannot because AJAX does not appear accessible. This could be because your website is password protected, in maintenance mode, or has a specific hosting configuration or plugin active that is preventing access.', 'give' ), 'http://docs.givewp.com/admin-ajax-error', __( 'Read More', 'give' ) . ' &raquo;' ),
588
					'show'        => true,
589
				)
590
			);
591
592
			return;
593
		}
594
595
		// Show db upgrade completed notice.
596
		if ( ! empty( $_GET['give-db-update-completed'] ) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
597
			Give()->notices->register_notice( array(
598
				'id'          => 'give_db_upgrade_completed',
599
				'type'        => 'updated',
600
				'description' => __( 'Give database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
601
				'show'        => true,
602
			) );
603
604
			// Start update.
605
		} elseif ( ! empty( $_GET['give-run-db-update'] ) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
606
			$this->run_db_update();
607
608
			// Show run the update notice.
609
		} elseif ( $this->get_total_new_db_update_count() ) {
610
			ob_start();
611
			?>
612
			<p>
613
				<strong><?php _e( 'Database Update', 'give' ); ?></strong>
614
				&nbsp;&#8211;&nbsp;<?php _e( 'GiveWP needs to update your database to the latest version. The following process will make updates to your site\'s database. Please create a complete backup before proceeding.', 'give' ); ?>
615
			</p>
616
			<p class="submit">
617
				<a href="<?php echo esc_url( add_query_arg( array( 'give-run-db-update' => 1 ), admin_url( 'edit.php?post_type=give_forms&page=give-updates' ) ) ); ?>" class="button button-primary give-run-update-now">
618
					<?php _e( 'Run the updater', 'give' ); ?>
619
				</a>
620
			</p>
621
			<script type="text/javascript">
622
				jQuery('.give-run-update-now').click('click', function () {
623
					return window.confirm('<?php echo esc_js( __( 'It is recommended that you backup your database before proceeding. Do you want to run the update now?', 'give' ) ); ?>'); // jshint ignore:line
624
				});
625
			</script>
626
			<?php
627
			$desc_html = ob_get_clean();
628
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
629
630
			Give()->notices->register_notice( array(
631
				'id'          => 'give_upgrade_db',
632
				'type'        => 'updated',
633
				'dismissible' => false,
634
				'description' => $desc_html,
635
			) );
636
		}
637
	}
638
639
	/**
640
	 * Render Give Updates Completed page
641
	 *
642
	 * @since  1.8.12
643
	 * @access public
644
	 */
645
	public function render_complete_page() {
646
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades-complete.php';
647
	}
648
649
	/**
650
	 * Render Give Updates page
651
	 *
652
	 * @since  1.8.12
653
	 * @access public
654
	 */
655
	public function render_page() {
656
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades.php';
657
	}
658
659
	/**
660
	 * Run database upgrades
661
	 *
662
	 * @since  2.0
663
	 * @access private
664
	 */
665
	private function run_db_update() {
666
		// Bailout.
667
		if ( $this->is_doing_updates() || ! $this->get_total_new_db_update_count() ) {
668
			return;
669
		}
670
671
		$updates = $this->get_updates( 'database', 'new' );
672
673
		foreach ( $updates as $update ) {
674
			self::$background_updater->push_to_queue( $update );
675
		}
676
677
		add_option( 'give_db_update_count', count( $updates ), '', 'no' );
678
679
		add_option( 'give_doing_upgrade', array(
680
			'update_info' => $updates[0],
681
			'step'        => 1,
682
			'update'      => 1,
683
			'heading'     => sprintf( 'Update %s of %s', 1, count( $updates ) ),
684
			'percentage'  => 0,
685
			'total_percentage'  => 0,
686
		), '', 'no' );
687
688
		self::$background_updater->save()->dispatch();
689
	}
690
691
692
	/**
693
	 * Delete resume updates
694
	 *
695
	 * @since  1.8.12
696
	 * @access public
697
	 */
698
	public function __flush_resume_updates() {
0 ignored issues
show
Coding Style introduced by
Method name "Give_Updates::__flush_resume_updates" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
699
		//delete_option( 'give_doing_upgrade' );
700
		update_option( 'give_version', preg_replace( '/[^0-9.].*/', '', GIVE_VERSION ) );
701
702
		// Reset counter.
703
		$this->step = $this->percentage = 0;
0 ignored issues
show
Documentation Bug introduced by
It seems like 0 of type integer is incompatible with the declared type array of property $percentage.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
Documentation Bug introduced by
It seems like $this->percentage = 0 of type integer is incompatible with the declared type array of property $step.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
704
705
		$this->update = ( $this->get_total_db_update_count() > $this->update ) ?
706
			( $this->update + 1 ) :
707
			$this->update;
708
	}
709
710
711
	/**
712
	 * Initialize updates
713
	 *
714
	 * @since  2.0
715
	 * @access public
716
	 *
717
	 * @return void
718
	 */
719
	public function __give_start_updating() {
0 ignored issues
show
Coding Style introduced by
Method name "Give_Updates::__give_start_updating" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
720
		// Check permission.
721
		if (
722
			! current_user_can( 'manage_give_settings' ) ||
723
			$this->is_doing_updates()
724
		) {
725
			wp_send_json_error();
726
		}
727
728
		// @todo: validate nonce
729
		// @todo: set http method to post
730
		if ( empty( $_POST['run_db_update'] ) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
731
			wp_send_json_error();
732
		}
733
734
		$this->run_db_update();
735
736
		wp_send_json_success();
737
	}
738
739
740
	/**
741
	 * This function handle ajax query for dn update status.
742
	 *
743
	 * @since  2.0
744
	 * @access public
745
	 *
746
	 * @return string
747
	 */
748
	public function __give_db_updates_info() {
0 ignored issues
show
Coding Style introduced by
Method name "Give_Updates::__give_db_updates_info" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
749
		$update_info   = get_option( 'give_doing_upgrade' );
750
		$response_type = '';
751
752
		if ( empty( $update_info ) ) {
753
			$update_info   = array(
754
				'message'    => __( 'Give database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
755
				'heading'    => __( 'Updates Completed.', 'give' ),
756
				'percentage' => 0,
757
			);
758
			$response_type = 'success';
759
760
			delete_option( 'give_show_db_upgrade_complete_notice' );
761
		}
762
763
		$this->send_ajax_response( $update_info, $response_type );
764
	}
765
766
	/**
767
	 * Send ajax response
768
	 *
769
	 * @since  1.8.12
770
	 * @access public
771
	 *
772
	 * @param        $data
773
	 * @param string $type
774
	 */
775
	public function send_ajax_response( $data, $type = '' ) {
776
		$default = array(
777
			'message'    => '',
778
			'heading'    => '',
779
			'percentage' => 0,
780
			'step'       => 0,
781
			'update'     => 0,
782
		);
783
784
		// Set data.
785
		$data = wp_parse_args( $data, $default );
786
787
		// Enable cache.
788
		Give_Cache::enable();
789
790
		switch ( $type ) {
791
			case 'success':
792
				wp_send_json_success( $data );
793
				break;
794
795
			case 'error':
796
				wp_send_json_error( $data );
797
				break;
798
799
			default:
800
				wp_send_json( array(
801
					'data' => $data,
802
				) );
803
				break;
804
		}
805
	}
806
807
	/**
808
	 * Set current update percentage.
809
	 *
810
	 * @since  1.8.12
811
	 * @access public
812
	 *
813
	 * @param $total
814
	 * @param $current_total
815
	 */
816
	public function set_percentage( $total, $current_total ) {
817
		// Set percentage.
818
		$this->percentage = $total ? ( ( $current_total ) / $total ) * 100 : 0;
0 ignored issues
show
Documentation Bug introduced by
It seems like $total ? $current_total / $total * 100 : 0 of type integer or double is incompatible with the declared type array of property $percentage.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
819
820
		// Verify percentage.
821
		$this->percentage = ( 100 < $this->percentage ) ? 100 : $this->percentage;
0 ignored issues
show
Documentation Bug introduced by
It seems like 100 < $this->percentage ? 100 : $this->percentage of type integer or double is incompatible with the declared type array of property $percentage.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
822
	}
823
824
	/**
825
	 * Check if parent update completed or not.
826
	 *
827
	 * @since  2.0
828
	 * @access private
829
	 *
830
	 * @param array $update
831
	 *
832
	 * @return bool|null
833
	 */
834
	public function is_parent_updates_completed( $update ) {
835
		// Bailout.
836
		if ( empty( $update['depend'] ) ) {
837
			return true;
838
		}
839
840
		// Check if dependency is valid or not.
841
		if ( ! $this->has_valid_dependency( $update ) ) {
842
			return null;
843
		}
844
845
		$is_dependency_completed = true;
846
847
		foreach ( $update['depend'] as $depend ) {
848
849
			if ( ! give_has_upgrade_completed( $depend ) ) {
850
				$is_dependency_completed = false;
851
				break;
852
			}
853
		}
854
855
		return $is_dependency_completed;
856
	}
857
858
	/**
859
	 * Flag to check if DB updates running or not.
860
	 *
861
	 * @since  2.0
862
	 * @access public
863
	 * @return bool
864
	 */
865
	public function is_doing_updates() {
866
		return (bool) get_option( 'give_doing_upgrade' );
867
	}
868
869
870
	/**
871
	 * Check if update has valid dependency or not.
872
	 *
873
	 * @since  2.0
874
	 * @access public
875
	 *
876
	 * @param $update
877
	 *
878
	 * @return bool
879
	 */
880
	public function has_valid_dependency( $update ) {
0 ignored issues
show
Unused Code introduced by
The parameter $update is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
881
		$is_valid_dependency = true;
882
		// $update_ids          = wp_list_pluck( $this->get_updates( 'database', 'all' ), 'id' );
883
		//
884
		// foreach ( $update['depend'] as $depend ) {
885
		// 	// Check if dependency is valid or not.
886
		// 	if ( ! in_array( $depend, $update_ids ) ) {
887
		// 		$is_valid_dependency = false;
888
		// 		break;
889
		// 	}
890
		// }
891
892
		return $is_valid_dependency;
893
	}
894
895
	/**
896
	 * Get updates.
897
	 *
898
	 * @since  1.8.12
899
	 * @access public
900
	 *
901
	 * @param string $update_type Tye of update.
902
	 * @param string $status      Tye of update.
903
	 *
904
	 * @return array
905
	 */
906
	public function get_updates( $update_type = '', $status = 'all' ) {
907
		// return all updates.
908
		if ( empty( $update_type ) ) {
909
			return $this->updates;
910
		}
911
912
		// Get specific update.
913
		$updates = ! empty( $this->updates[ $update_type ] ) ? $this->updates[ $update_type ] : array();
914
915
		// Bailout.
916
		if ( empty( $updates ) ) {
917
			return $updates;
918
		}
919
920
		switch ( $status ) {
921
			case 'new':
922
				// Remove already completed updates.
923
				$completed_updates = give_get_completed_upgrades();
924
925
				if ( ! empty( $completed_updates ) ) {
926
					foreach ( $updates as $index => $update ) {
927
						if ( in_array( $update['id'], $completed_updates ) ) {
928
							unset( $updates[ $index ] );
929
						}
930
					}
931
					$updates = array_values( $updates );
932
				}
933
934
				break;
935
		}
936
937
		return $updates;
938
	}
939
940
	/**
941
	 * Get addon update count.
942
	 *
943
	 * @since  1.8.12
944
	 * @access public
945
	 * @return int
946
	 */
947
	public function get_total_plugin_update_count() {
948
		return count( $this->get_updates( 'plugin' ) );
949
	}
950
951
	/**
952
	 * Get total update count
953
	 *
954
	 * @since  1.8.12
955
	 * @access public
956
	 *
957
	 * @return int
958
	 */
959
	public function get_total_update_count() {
960
		$db_update_count     = $this->get_pending_db_update_count();
961
		$plugin_update_count = $this->get_total_plugin_update_count();
962
963
		return ( $db_update_count + $plugin_update_count );
964
	}
965
966
	/**
967
	 * Get total pending updates count
968
	 *
969
	 * @since  1.8.12
970
	 * @access public
971
	 *
972
	 * @return int
973
	 */
974
	public function get_pending_db_update_count() {
975
		return count( $this->get_updates( 'database', 'new' ) );
976
	}
977
978
	/**
979
	 * Get total updates count
980
	 *
981
	 * @since  1.8.18
982
	 * @access public
983
	 *
984
	 * @return int
985
	 */
986
	public function get_total_db_update_count() {
987
		return count( $this->get_updates( 'database', 'all' ) );
988
	}
989
990
	/**
991
	 * Get total new updates count
992
	 *
993
	 * @since  2.0
994
	 * @access public
995
	 *
996
	 * @return int
997
	 */
998
	public function get_total_new_db_update_count() {
999
		return $this->is_doing_updates() ?
1000
			get_option( 'give_db_update_count' ) :
1001
			$this->get_pending_db_update_count();
1002
	}
1003
1004
	/**
1005
	 * Get total new updates count
1006
	 *
1007
	 * @since  2.0
1008
	 * @access public
1009
	 *
1010
	 * @return int
1011
	 */
1012
	public function get_running_db_update() {
1013
		$current_update = get_option( 'give_doing_upgrade' );
1014
1015
		return $this->is_doing_updates() ?
1016
			$current_update['update'] :
1017
			1;
1018
	}
1019
1020
	/**
1021
	 * Get database update processing percentage.
1022
	 *
1023
	 * @since  2.0
1024
	 * @access public
1025
	 * @return float|int
1026
	 */
1027
	public function get_db_update_processing_percentage() {
1028
		// Bailout.
1029
		if ( ! $this->get_total_new_db_update_count() ) {
1030
			return 0;
1031
		}
1032
1033
		$resume_update            = get_option( 'give_doing_upgrade' );
1034
		$update_count_percentages = ( ( $this->get_running_db_update() - 1 ) / $this->get_total_new_db_update_count() ) * 100;
1035
		$update_percentage_share  = ( 1 / $this->get_total_new_db_update_count() ) * 100;
1036
		$upgrade_percentage       = ( ( $resume_update['percentage'] * $update_percentage_share ) / 100 );
1037
1038
		$final_percentage = $update_count_percentages + $upgrade_percentage;
1039
1040
		return $this->is_doing_updates() ?
1041
			( absint( $final_percentage ) ?
1042
				absint( $final_percentage ) :
1043
				round( $final_percentage, 2 )
1044
			) :
1045
			0;
1046
	}
1047
1048
1049
	/**
1050
	 * Get all update ids.
1051
	 *
1052
	 * @since 2.0.3
1053
	 *
1054
	 * @return array
1055
	 */
1056
	public function get_update_ids() {
1057
		$all_updates    = $this->get_updates( 'database', 'all' );
1058
		$all_update_ids = wp_list_pluck( $all_updates, 'id' );
1059
1060
		return $all_update_ids;
1061
	}
1062
}
1063
1064
Give_Updates::get_instance()->setup();
1065