Test Failed
Push — master ( cd44a0...d8bbfb )
by Devin
01:14
created

Give_Updates::__pause_db_update()   C

Complexity

Conditions 7
Paths 3

Size

Total Lines 32
Code Lines 17

Duplication

Lines 9
Ratio 28.13 %

Importance

Changes 0
Metric Value
cc 7
eloc 17
nc 3
nop 0
dl 9
loc 32
rs 6.7272
c 0
b 0
f 0
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
	 * @return bool
320
	 */
321
	public function __pause_db_update() {
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...
322
		// Bailout.
323 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...
324
			wp_doing_ajax() ||
325
			! isset( $_GET['page'] ) ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
326
			'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...
327
			! 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...
328
			self::$background_updater->is_paused_process()
329
		) {
330
			return false;
331
		}
332
333
		$batch = self::$background_updater->get_all_batch();
334
335
		if ( ! empty( $batch ) ) {
336
			update_option( 'give_paused_batches', $batch,  'no' );
337
			delete_option( $batch->key );
338
			delete_site_transient( self::$background_updater->get_identifier() . '_process_lock' );
339
			wp_clear_scheduled_hook( self::$background_updater->get_cron_identifier() );
340
341
			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...
342
343
			/**
344
			 * Fire action when pause db updates
345
			 *
346
			 * @since 2.0.1
347
			 */
348
			do_action( 'give_pause_db_upgrade', $this );
349
		}
350
351
		return true;
352
	}
353
354
	/**
355
	 * Restart db upgrade
356
	 *
357
	 * @since  2.0.1
358
	 * @access public
359
	 *
360
	 * @return bool
361
	 */
362
	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...
363
		// Bailout.
364 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...
365
			wp_doing_ajax() ||
366
			! isset( $_GET['page'] ) ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
367
			'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...
368
			! 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...
369
			! self::$background_updater->is_paused_process()
370
		) {
371
			return false;
372
		}
373
374
		$batch = get_option( 'give_paused_batches' );
375
376
		if ( ! empty( $batch ) ) {
377
			update_option( $batch->key, $batch->data );
378
			delete_option( 'give_paused_batches' );
379
380
			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...
381
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
382
383
			/** Fire action when restart db updates
384
			 *
385
			 * @since 2.0.1
386
			 */
387
			do_action( 'give_restart_db_upgrade', $this );
388
389
			self::$background_updater->dispatch();
390
		}
391
392
		return true;
393
	}
394
395
	/**
396
	 * Health check for updates.
397
	 *
398
	 * @since  2.0
399
	 * @access public
400
	 *
401
	 * @param Give_Updates $give_updates
402
	 */
403
	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...
404
		if ( ! $this->is_doing_updates() ) {
405
			return;
406
		}
407
408
		$batch                = Give_Updates::$background_updater->get_all_batch();
409
		$batch_data_count     = count( $batch->data );
410
		$all_updates          = $give_updates->get_updates( 'database', 'all' );
411
		$all_update_ids       = wp_list_pluck( $all_updates, 'id' );
412
		$all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : array();
413
		$log_data             = '';
414
		$doing_upgrade_args   = get_option( 'give_doing_upgrade' );
415
416
		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...
417
			$log_data .= 'Doing update:' . "\n";
418
			$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...
419
		}
420
421
		if ( ! empty( $batch->data ) ) {
422
423
			foreach ( $batch->data as $index => $update ) {
424
				$log_data = print_r( $update, true ) . "\n";
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
425
426
				if ( ! is_callable( $update['callback'] ) ) {
427
					$log_data .= 'Removing missing callback update: ' . "{$update['id']}\n";
428
					unset( $batch->data[ $index ] );
429
				}
430
431
				if ( ! empty( $update['depend'] ) ) {
432
433
					foreach ( $update['depend'] as $depend ) {
434
						if ( give_has_upgrade_completed( $depend ) ) {
435
							$log_data .= 'Completed update: ' . "{$depend}\n";
436
							continue;
437
						}
438
439
						if ( in_array( $depend, $all_update_ids ) && ! in_array( $depend, $all_batch_update_ids ) ) {
440
							$log_data .= 'Adding missing update: ' . "{$depend}\n";
441
							array_unshift( $batch->data, $all_updates[ array_search( $depend, $all_update_ids ) ] );
442
						}
443
					}
444
				}
445
			}
446
		}
447
448
		if ( $new_updates = $this->get_updates( 'database', 'new' ) ) {
449
			$all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : array();
450
451
			foreach ( $new_updates as $index => $new_update ) {
452
				if ( give_has_upgrade_completed( $new_update['id'] ) || in_array( $new_update['id'], $all_batch_update_ids ) ) {
453
					unset( $new_updates[ $index ] );
454
				}
455
			}
456
457
			if ( ! empty( $new_updates ) ) {
458
				$log_data .= 'Adding new update: ' . "\n";
459
				$log_data .= print_r( $new_updates, true ) . "\n";
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
460
461
				$batch->data = array_merge( (array) $batch->data, $new_updates );
462
				update_option( 'give_db_update_count', ( absint( get_option( 'give_db_update_count' ) ) + count( $new_updates ) ) );
463
			}
464
		}
465
466
		if ( $batch_data_count !== count( $batch->data ) ) {
467
			$log_data .= 'Updating batch' . "\n";
468
			$log_data .= print_r( $batch, true );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
469
470
			$doing_upgrade_args['heading']          = sprintf( 'Update %s of %s', $doing_upgrade_args['update'], get_option( 'give_db_update_count' ) );
471
			$doing_upgrade_args['total_percentage'] = $this->get_db_update_processing_percentage();
472
			update_option( 'give_doing_upgrade', $doing_upgrade_args );
473
474
			if ( ! empty( $batch->key ) ) {
475
				update_option( $batch->key, $batch->data );
476
			} else {
477
478
				update_option( 'give_db_update_count', count( $batch->data ) );
479
480
				$doing_upgrade_args['update']  = $give_updates->update;
481
				$doing_upgrade_args['heading'] = sprintf( 'Update %s of %s', 1, count( $batch->data ) );
482
483
				update_option( 'give_doing_upgrade', $doing_upgrade_args );
484
485
				foreach ( $batch->data as $data ) {
486
					Give_Updates::$background_updater->push_to_queue( $data );
487
				}
488
489
				Give_Updates::$background_updater->save();
490
			}
491
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
492
493
			Give()->logs->add( 'Update Health Check', $log_data, 0, 'update' );
494
		}
495
	}
496
497
498
	/**
499
	 * Show update related notices
500
	 *
501
	 * @since  2.0
502
	 * @access public
503
	 */
504
	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...
505
		// Bailout.
506
		if ( ! current_user_can( 'manage_give_settings' ) ) {
507
			return;
508
		}
509
510
		// Run DB updates.
511
		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...
512
			$this->run_db_update();
513
		}
514
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
515
516
		// Bailout.
517
		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...
518
			return;
519
		}
520
521
		// Show notice if upgrade paused.
522 View Code Duplication
		if ( self::$background_updater->is_paused_process() ) {
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...
523
			ob_start();
524
			?>
525
			<p>
526
				<strong><?php _e( 'Database Update', 'give' ); ?></strong>
527
				&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' ); ?>
528
			</p>
529
			<p class="submit">
530
				<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">
531
					<?php _e( 'Restart the updater', 'give' ); ?>
532
				</a>
533
			</p>
534
			<script type="text/javascript">
535
				jQuery('.give-restart-updater-btn').click('click', function () {
536
					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
537
				});
538
			</script>
539
			<?php
540
			$desc_html = ob_get_clean();
541
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
542
543
			Give()->notices->register_notice( array(
544
				'id'          => 'give_upgrade_db',
545
				'type'        => 'error',
546
				'dismissible' => false,
547
				'description' => $desc_html,
548
			) );
549
		}
550
551
		// Bailout if doing upgrades.
552
		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...
553
			return;
554
		}
555
556
		// Show notice if ajax is not working.
557
		if ( ! give_test_ajax_works() ) {
558
			Give()->notices->register_notice(
559
				array(
560
					'id'          => 'give_db_upgrade_ajax_inaccessible',
561
					'type'        => 'error',
562
					'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;' ),
563
					'show'        => true,
564
				)
565
			);
566
567
			return;
568
		}
569
570
		// Show db upgrade completed notice.
571
		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...
572
			Give()->notices->register_notice( array(
573
				'id'          => 'give_db_upgrade_completed',
574
				'type'        => 'updated',
575
				'description' => __( 'Give database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
576
				'show'        => true,
577
			) );
578
579
			// Start update.
580
		} 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...
581
			$this->run_db_update();
582
583
			// Show run the update notice.
584 View Code Duplication
		} elseif ( $this->get_total_new_db_update_count() ) {
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...
585
			ob_start();
586
			?>
587
			<p>
588
				<strong><?php _e( 'Database Update', 'give' ); ?></strong>
589
				&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' ); ?>
590
			</p>
591
			<p class="submit">
592
				<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">
593
					<?php _e( 'Run the updater', 'give' ); ?>
594
				</a>
595
			</p>
596
			<script type="text/javascript">
597
				jQuery('.give-run-update-now').click('click', function () {
598
					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
599
				});
600
			</script>
601
			<?php
602
			$desc_html = ob_get_clean();
603
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
604
605
			Give()->notices->register_notice( array(
606
				'id'          => 'give_upgrade_db',
607
				'type'        => 'updated',
608
				'dismissible' => false,
609
				'description' => $desc_html,
610
			) );
611
		}
612
	}
613
614
	/**
615
	 * Render Give Updates Completed page
616
	 *
617
	 * @since  1.8.12
618
	 * @access public
619
	 */
620
	public function render_complete_page() {
621
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades-complete.php';
622
	}
623
624
	/**
625
	 * Render Give Updates page
626
	 *
627
	 * @since  1.8.12
628
	 * @access public
629
	 */
630
	public function render_page() {
631
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades.php';
632
	}
633
634
	/**
635
	 * Run database upgrades
636
	 *
637
	 * @since  2.0
638
	 * @access private
639
	 */
640
	private function run_db_update() {
641
		// Bailout.
642
		if ( $this->is_doing_updates() || ! $this->get_total_new_db_update_count() ) {
643
			return;
644
		}
645
646
		$updates = $this->get_updates( 'database', 'new' );
647
648
		foreach ( $updates as $update ) {
649
			self::$background_updater->push_to_queue( $update );
650
		}
651
652
		add_option( 'give_db_update_count', count( $updates ), '', 'no' );
653
654
		add_option( 'give_doing_upgrade', array(
655
			'update_info' => $updates[0],
656
			'step'        => 1,
657
			'update'      => 1,
658
			'heading'     => sprintf( 'Update %s of %s', 1, count( $updates ) ),
659
			'percentage'  => 0,
660
			'total_percentage'  => 0,
661
		), '', 'no' );
662
663
		self::$background_updater->save()->dispatch();
664
	}
665
666
667
	/**
668
	 * Delete resume updates
669
	 *
670
	 * @since  1.8.12
671
	 * @access public
672
	 */
673
	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...
674
		//delete_option( 'give_doing_upgrade' );
675
		update_option( 'give_version', preg_replace( '/[^0-9.].*/', '', GIVE_VERSION ) );
676
677
		// Reset counter.
678
		$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...
679
		++ $this->update;
680
	}
681
682
683
	/**
684
	 * Initialize updates
685
	 *
686
	 * @since  2.0
687
	 * @access public
688
	 *
689
	 * @return void
690
	 */
691
	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...
692
		// Check permission.
693
		if (
694
			! current_user_can( 'manage_give_settings' ) ||
695
			$this->is_doing_updates()
696
		) {
697
			wp_send_json_error();
698
		}
699
700
		// @todo: validate nonce
701
		// @todo: set http method to post
702
		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...
703
			wp_send_json_error();
704
		}
705
706
		$this->run_db_update();
707
708
		wp_send_json_success();
709
	}
710
711
712
	/**
713
	 * This function handle ajax query for dn update status.
714
	 *
715
	 * @since  2.0
716
	 * @access public
717
	 *
718
	 * @return string
719
	 */
720
	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...
721
		$update_info   = get_option( 'give_doing_upgrade' );
722
		$response_type = '';
723
724
		if ( empty( $update_info ) ) {
725
			$update_info   = array(
726
				'message'    => __( 'Give database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
727
				'heading'    => __( 'Updates Completed.', 'give' ),
728
				'percentage' => 0,
729
			);
730
			$response_type = 'success';
731
732
			delete_option( 'give_show_db_upgrade_complete_notice' );
733
		}
734
735
		$this->send_ajax_response( $update_info, $response_type );
736
	}
737
738
	/**
739
	 * Send ajax response
740
	 *
741
	 * @since  1.8.12
742
	 * @access public
743
	 *
744
	 * @param        $data
745
	 * @param string $type
746
	 */
747
	public function send_ajax_response( $data, $type = '' ) {
748
		$default = array(
749
			'message'    => '',
750
			'heading'    => '',
751
			'percentage' => 0,
752
			'step'       => 0,
753
			'update'     => 0,
754
		);
755
756
		// Set data.
757
		$data = wp_parse_args( $data, $default );
758
759
		// Enable cache.
760
		Give_Cache::enable();
761
762
		switch ( $type ) {
763
			case 'success':
764
				wp_send_json_success( $data );
765
				break;
766
767
			case 'error':
768
				wp_send_json_error( $data );
769
				break;
770
771
			default:
772
				wp_send_json( array(
773
					'data' => $data,
774
				) );
775
				break;
776
		}
777
	}
778
779
	/**
780
	 * Set current update percentage.
781
	 *
782
	 * @since  1.8.12
783
	 * @access public
784
	 *
785
	 * @param $total
786
	 * @param $current_total
787
	 */
788
	public function set_percentage( $total, $current_total ) {
789
		// Set percentage.
790
		$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...
791
792
		// Verify percentage.
793
		$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...
794
	}
795
796
	/**
797
	 * Check if parent update completed or not.
798
	 *
799
	 * @since  2.0
800
	 * @access private
801
	 *
802
	 * @param array $update
803
	 *
804
	 * @return bool|null
805
	 */
806
	public function is_parent_updates_completed( $update ) {
807
		// Bailout.
808
		if ( empty( $update['depend'] ) ) {
809
			return true;
810
		}
811
812
		// Check if dependency is valid or not.
813
		if ( ! $this->has_valid_dependency( $update ) ) {
814
			return null;
815
		}
816
817
		$is_dependency_completed = true;
818
819
		foreach ( $update['depend'] as $depend ) {
820
821
			if ( ! give_has_upgrade_completed( $depend ) ) {
822
				$is_dependency_completed = false;
823
				break;
824
			}
825
		}
826
827
		return $is_dependency_completed;
828
	}
829
830
	/**
831
	 * Flag to check if DB updates running or not.
832
	 *
833
	 * @since  2.0
834
	 * @access public
835
	 * @return bool
836
	 */
837
	public function is_doing_updates() {
838
		return (bool) get_option( 'give_doing_upgrade' );
839
	}
840
841
842
	/**
843
	 * Check if update has valid dependency or not.
844
	 *
845
	 * @since  2.0
846
	 * @access public
847
	 *
848
	 * @param $update
849
	 *
850
	 * @return bool
851
	 */
852
	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...
853
		$is_valid_dependency = true;
854
		// $update_ids          = wp_list_pluck( $this->get_updates( 'database', 'all' ), 'id' );
855
		//
856
		// foreach ( $update['depend'] as $depend ) {
857
		// 	// Check if dependency is valid or not.
858
		// 	if ( ! in_array( $depend, $update_ids ) ) {
859
		// 		$is_valid_dependency = false;
860
		// 		break;
861
		// 	}
862
		// }
863
864
		return $is_valid_dependency;
865
	}
866
867
	/**
868
	 * Get updates.
869
	 *
870
	 * @since  1.8.12
871
	 * @access public
872
	 *
873
	 * @param string $update_type Tye of update.
874
	 * @param string $status      Tye of update.
875
	 *
876
	 * @return array
877
	 */
878
	public function get_updates( $update_type = '', $status = 'all' ) {
879
		// return all updates.
880
		if ( empty( $update_type ) ) {
881
			return $this->updates;
882
		}
883
884
		// Get specific update.
885
		$updates = ! empty( $this->updates[ $update_type ] ) ? $this->updates[ $update_type ] : array();
886
887
		// Bailout.
888
		if ( empty( $updates ) ) {
889
			return $updates;
890
		}
891
892
		switch ( $status ) {
893
			case 'new':
894
				// Remove already completed updates.
895
				$completed_updates = give_get_completed_upgrades();
896
897
				if ( ! empty( $completed_updates ) ) {
898
					foreach ( $updates as $index => $update ) {
899
						if ( in_array( $update['id'], $completed_updates ) ) {
900
							unset( $updates[ $index ] );
901
						}
902
					}
903
					$updates = array_values( $updates );
904
				}
905
906
				break;
907
		}
908
909
		return $updates;
910
	}
911
912
	/**
913
	 * Get addon update count.
914
	 *
915
	 * @since  1.8.12
916
	 * @access public
917
	 * @return int
918
	 */
919
	public function get_total_plugin_update_count() {
920
		return count( $this->get_updates( 'plugin' ) );
921
	}
922
923
	/**
924
	 * Get total update count
925
	 *
926
	 * @since  1.8.12
927
	 * @access public
928
	 *
929
	 * @return int
930
	 */
931
	public function get_total_update_count() {
932
		$db_update_count     = $this->get_pending_db_update_count();
933
		$plugin_update_count = $this->get_total_plugin_update_count();
934
935
		return ( $db_update_count + $plugin_update_count );
936
	}
937
938
	/**
939
	 * Get total pending updates count
940
	 *
941
	 * @since  1.8.12
942
	 * @access public
943
	 *
944
	 * @return int
945
	 */
946
	public function get_pending_db_update_count() {
947
		return count( $this->get_updates( 'database', 'new' ) );
948
	}
949
950
	/**
951
	 * Get total updates count
952
	 *
953
	 * @since  1.8.18
954
	 * @access public
955
	 *
956
	 * @return int
957
	 */
958
	public function get_total_db_update_count() {
959
		return count( $this->get_updates( 'database', 'all' ) );
960
	}
961
962
	/**
963
	 * Get total new updates count
964
	 *
965
	 * @since  2.0
966
	 * @access public
967
	 *
968
	 * @return int
969
	 */
970
	public function get_total_new_db_update_count() {
971
		return $this->is_doing_updates() ?
972
			get_option( 'give_db_update_count' ) :
973
			$this->get_pending_db_update_count();
974
	}
975
976
	/**
977
	 * Get total new updates count
978
	 *
979
	 * @since  2.0
980
	 * @access public
981
	 *
982
	 * @return int
983
	 */
984
	public function get_running_db_update() {
985
		$current_update = get_option( 'give_doing_upgrade' );
986
987
		return $this->is_doing_updates() ?
988
			$current_update['update'] :
989
			1;
990
	}
991
992
	/**
993
	 * Get database update processing percentage.
994
	 *
995
	 * @since  2.0
996
	 * @access public
997
	 * @return float|int
998
	 */
999
	public function get_db_update_processing_percentage() {
1000
		// Bailout.
1001
		if ( ! $this->get_total_new_db_update_count() ) {
1002
			return 0;
1003
		}
1004
1005
		$resume_update            = get_option( 'give_doing_upgrade' );
1006
		$update_count_percentages = ( ( $this->get_running_db_update() - 1 ) / $this->get_total_new_db_update_count() ) * 100;
1007
		$update_percentage_share  = ( 1 / $this->get_total_new_db_update_count() ) * 100;
1008
		$upgrade_percentage       = ( ( $resume_update['percentage'] * $update_percentage_share ) / 100 );
1009
1010
		$final_percentage = $update_count_percentages + $upgrade_percentage;
1011
1012
		return $this->is_doing_updates() ?
1013
			( absint( $final_percentage ) ?
1014
				absint( $final_percentage ) :
1015
				round( $final_percentage, 2 )
1016
			) :
1017
			0;
1018
	}
1019
}
1020
1021
Give_Updates::get_instance()->setup();
1022