Give_Updates::__show_notice()   C
last analyzed

Complexity

Conditions 10
Paths 33

Size

Total Lines 94

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
nc 33
nop 0
dl 0
loc 94
rs 6.2642
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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() {
170
		$addons         = give_get_plugins( array( 'only_premium_add_ons' => true ) );
171
		$plugin_updates = get_plugin_updates();
172
173
		foreach ( $addons as $key => $info ) {
174
			if ( 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() {
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...
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() {
243
		// Load plugin updates.
244
		$this->__register_plugin_addon_updates();
245
246
		// Bailout.
247
		if ( ! $this->get_total_update_count() ) {
248
			// Show complete update message if still on update setting page.
249
			if ( isset( $_GET['page'] ) && 'give-updates' === $_GET['page'] ) {
250
				// Upgrades
251
				add_submenu_page(
252
					'edit.php?post_type=give_forms',
253
					esc_html__( 'Give Updates Complete', 'give' ),
254
					__( 'Updates', 'give' ),
255
					'manage_give_settings',
256
					'give-updates',
257
					array( $this, 'render_complete_page' )
258
				);
259
			}
260
261
			return;
262
		}
263
264
		$is_update = ( $this->is_doing_updates() && ! self::$background_updater->is_paused_process() );
265
266
		// Upgrades
267
		add_submenu_page(
268
			'edit.php?post_type=give_forms',
269
			esc_html__( 'Give Updates', 'give' ),
270
			sprintf(
271
				'%1$s <span class="update-plugins"%2$s><span class="plugin-count give-update-progress-count">%3$s%4$s</span></span>',
272
				__( 'Updates', 'give' ),
273
				isset( $_GET['give-pause-db-upgrades'] ) ? ' style="display:none;"' : '',
274
				$is_update ?
275
					$this->get_db_update_processing_percentage() :
276
					$this->get_total_update_count(),
277
				$is_update ? '%' : ''
278
			),
279
			'manage_give_settings',
280
			'give-updates',
281
			array( $this, 'render_page' )
282
		);
283
	}
284
285
286
	/**
287
	 * Show update related notices
288
	 *
289
	 * @since  2.0
290
	 * @access public
291
	 */
292
	public function __redirect_admin() {
293
		// Show db upgrade completed notice.
294
		if (
295
			! wp_doing_ajax() &&
296
			current_user_can( 'manage_give_settings' ) &&
297
			Give_Cache_Setting::get_option( 'give_show_db_upgrade_complete_notice' ) &&
298
			! isset( $_GET['give-db-update-completed'] )
299
		) {
300
			delete_option( 'give_show_db_upgrade_complete_notice' );
301
302
			wp_redirect( admin_url( 'edit.php?post_type=give_forms&page=give-updates&give-db-update-completed=give_db_upgrade_completed' ) );
303
			exit();
304
		}
305
	}
306
307
308
	/**
309
	 * Pause db upgrade
310
	 *
311
	 * @since  2.0.1
312
	 * @access public
313
	 *
314
	 * @param bool $force
315
	 *
316
	 * @return bool
317
	 */
318
	public function __pause_db_update( $force = false ) {
319
		// Bailout.
320 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...
321
			! $force &&
322
			(
323
				wp_doing_ajax() ||
324
				! isset( $_GET['page'] ) ||
325
				'give-updates' !== $_GET['page'] ||
326
				! isset( $_GET['give-pause-db-upgrades'] ) ||
327
				self::$background_updater->is_paused_process()
328
			)
329
330
		) {
331
			return false;
332
		}
333
334
		delete_option( 'give_upgrade_error' );
335
336
		$this->__health_background_update( $this );
337
		$batch = self::$background_updater->get_all_batch();
338
339
		// Bailout: if batch is empty
340
		if ( empty( $batch->data ) ) {
341
			return false;
342
		}
343
344
		// Remove cache.
345
		Give_Background_Updater::flush_cache();
346
347
		// Do not stop background process immediately if task running.
348
		// @see Give_Background_Updater::lock_process
349
		if ( ! $force && self::$background_updater->is_process_running() ) {
350
			update_option( 'give_pause_upgrade', 1, false );
351
352
			return true;
353
		}
354
355
		update_option( 'give_paused_batches', $batch, false );
356
		delete_option( $batch->key );
357
		delete_site_transient( self::$background_updater->get_identifier() . '_process_lock' );
358
		wp_clear_scheduled_hook( self::$background_updater->get_cron_identifier() );
359
360
		Give()->logs->add( 'Update Pause', print_r( $batch, true ), 0, 'update' );
361
362
		/**
363
		 * Fire action when pause db updates
364
		 *
365
		 * @since 2.0.1
366
		 */
367
		do_action( 'give_pause_db_upgrade', $this );
368
369
		return true;
370
	}
371
372
	/**
373
	 * Restart db upgrade
374
	 *
375
	 * @since  2.0.1
376
	 * @access public
377
	 *
378
	 * @return bool
379
	 */
380
	public function __restart_db_update() {
381
		// Bailout.
382 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...
383
			wp_doing_ajax() ||
384
			! isset( $_GET['page'] ) ||
385
			'give-updates' !== $_GET['page'] ||
386
			! isset( $_GET['give-restart-db-upgrades'] ) ||
387
			! self::$background_updater->is_paused_process()
388
		) {
389
			return false;
390
		}
391
392
		Give_Background_Updater::flush_cache();
393
		$batch = get_option( 'give_paused_batches' );
394
395
		if ( ! empty( $batch ) ) {
396
			wp_cache_delete( $batch->key, 'options' );
397
			update_option( $batch->key, $batch->data, false );
398
399
			delete_option( 'give_paused_batches' );
400
401
			Give()->logs->add( 'Update Restart', print_r( $batch, true ), 0, 'update' );
402
403
404
			/** Fire action when restart db updates
405
			 *
406
			 * @since 2.0.1
407
			 */
408
			do_action( 'give_restart_db_upgrade', $this );
409
410
			self::$background_updater->dispatch();
411
		}
412
413
		return true;
414
	}
415
416
	/**
417
	 * Health check for updates.
418
	 *
419
	 * @since  2.0
420
	 * @access public
421
	 *
422
	 * @param Give_Updates $give_updates
423
	 */
424
	public function __health_background_update( $give_updates ) {
425
		if ( ! $this->is_doing_updates() ) {
426
			return;
427
		}
428
429
		Give_Background_Updater::flush_cache();
430
431
		/* @var stdClass $batch */
432
		$batch                = Give_Updates::$background_updater->get_all_batch();
433
		$old_batch_update_ids = is_array( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : array();
434
		$all_updates          = $give_updates->get_updates( 'database', 'all' );
435
		$all_update_ids       = wp_list_pluck( $all_updates, 'id' );
436
		$all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : array();
437
		$log_data             = '';
438
		$doing_upgrade_args   = get_option( 'give_doing_upgrade' );
439
440
		if ( ! empty( $doing_upgrade_args ) ) {
441
			$log_data .= 'Doing update:' . "\n";
442
			$log_data .= print_r( $doing_upgrade_args, true ) . "\n";
443
		}
444
445
		/**
446
		 * Add remove upgrade from batch
447
		 */
448
		if ( ! empty( $batch->data ) ) {
449
450
			foreach ( $batch->data as $index => $update ) {
451
				$log_data = print_r( $update, true ) . "\n";
452
453
				if ( ! is_callable( $update['callback'] ) ) {
454
					$log_data .= 'Removing missing callback update: ' . "{$update['id']}\n";
455
					unset( $batch->data[ $index ] );
456
				} elseif ( give_has_upgrade_completed( $update['id'] ) ) {
457
					$log_data .= 'Removing already completed update: ' . "{$update['id']}\n";
458
					unset( $batch->data[ $index ] );
459
				}
460
461
				if ( ! empty( $update['depend'] ) ) {
462
463
					foreach ( $update['depend'] as $depend ) {
464
						if ( give_has_upgrade_completed( $depend ) ) {
465
							$log_data .= 'Completed update: ' . "{$depend}\n";
466
							continue;
467
						}
468
469
						if ( in_array( $depend, $all_update_ids ) && ! in_array( $depend, $all_batch_update_ids ) ) {
470
							$log_data .= 'Adding missing update: ' . "{$depend}\n";
471
							array_unshift( $batch->data, $all_updates[ array_search( $depend, $all_update_ids ) ] );
472
						}
473
					}
474
				}
475
			}
476
		}
477
478
		/**
479
		 * Add new upgrade to batch
480
		 */
481
		if ( $new_updates = $this->get_updates( 'database', 'new' ) ) {
482
			$all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : array();
483
484
			foreach ( $new_updates as $index => $new_update ) {
485
				if ( give_has_upgrade_completed( $new_update['id'] ) || in_array( $new_update['id'], $all_batch_update_ids ) ) {
486
					unset( $new_updates[ $index ] );
487
				}
488
			}
489
490
			if ( ! empty( $new_updates ) ) {
491
				$log_data .= 'Adding new update: ' . "\n";
492
				$log_data .= print_r( $new_updates, true ) . "\n";
493
494
				$batch->data = array_merge( (array) $batch->data, $new_updates );
495
				update_option( 'give_db_update_count', ( absint( get_option( 'give_db_update_count' ) ) + count( $new_updates ) ), false );
496
			}
497
		}
498
499
		/**
500
		 * Fix batch
501
		 */
502
		if ( empty( $batch->data ) ) {
503
			// Complete batch if do not have any data to process.
504
			self::$background_updater->delete( $batch->key );
505
506
			if ( self::$background_updater->has_queue() ) {
507
				$this->__health_background_update( $this );
508
			} else {
509
				delete_site_transient( self::$background_updater->get_identifier() . '_process_lock' );
510
				wp_clear_scheduled_hook( self::$background_updater->get_cron_identifier() );
511
512
				self::$background_updater->complete();
513
			}
514
515
		} elseif ( array_diff( wp_list_pluck( $batch->data, 'id' ), $old_batch_update_ids ) ) {
516
517
			$log_data .= 'Updating batch' . "\n";
518
			$log_data .= print_r( $batch, true );
519
520
			if ( ! empty( $batch->key ) ) {
521
				wp_cache_delete( $batch->key, 'options' );
522
				update_option( $batch->key, $batch->data, false );
523
			} else {
524
525
				foreach ( $batch->data as $data ) {
526
					Give_Updates::$background_updater->push_to_queue( $data );
527
				}
528
529
				Give_Updates::$background_updater->save();
530
			}
531
		}
532
533
534
		/**
535
		 * Fix give_doing_upgrade option
536
		 */
537
		if( $fresh_new_db_count = $this->get_total_new_db_update_count( true ) ) {
538
			update_option( 'give_db_update_count', $fresh_new_db_count, false );
539
		}
540
541
		$doing_upgrade_args['update']           = 1;
542
		$doing_upgrade_args['heading']          = sprintf( 'Update %s of %s', 1, $fresh_new_db_count );
543
		$doing_upgrade_args['total_percentage'] = $this->get_db_update_processing_percentage( true );
544
545
		// Remove already completed update from info.
546
		if (
547
			empty( $doing_upgrade_args['update_info'] )
548
			|| give_has_upgrade_completed( $doing_upgrade_args['update_info']['id'] )
549
		) {
550
			$doing_upgrade_args['update_info'] = current( array_values( $batch->data ) );
551
			$doing_upgrade_args['step']        = 1;
552
		}
553
554
		// Check if dependency completed or not.
555
		if ( isset( $doing_upgrade_args['update_info']['depend'] ) ) {
556
			foreach ( $doing_upgrade_args['update_info']['depend'] as $depend ) {
557
				if ( give_has_upgrade_completed( $depend ) ) {
558
					continue;
559
				}
560
561
				$doing_upgrade_args['update_info']      = $all_updates[ array_search( $depend, $all_update_ids ) ];
562
				$doing_upgrade_args['step']             = 1;
563
				$doing_upgrade_args['percentage']       = 0;
564
				$doing_upgrade_args['total_percentage'] = 0;
565
566
				break;
567
			}
568
		}
569
570
		if( ! empty( $doing_upgrade_args['update_info'] ) ) {
571
			update_option( 'give_doing_upgrade', $doing_upgrade_args, false );
572
573
			$log_data .= 'Updated doing update:' . "\n";
574
			$log_data .= print_r( $doing_upgrade_args, true ) . "\n";
575
		}
576
577
		Give()->logs->add( 'Update Health Check', $log_data, 0, 'update' );
578
	}
579
580
581
	/**
582
	 * Show update related notices
583
	 *
584
	 * @since  2.0
585
	 * @access public
586
	 */
587
	public function __show_notice() {
588
		$current_screen = get_current_screen();
589
		$hide_on_pages = array(
590
			'give_forms_page_give-updates',
591
			'update-core',
592
			'give_forms_page_give-addons'
593
		);
594
595
		// Bailout.
596
		if ( ! current_user_can( 'manage_give_settings' ) ) {
597
			return;
598
		}
599
600
		// Run DB updates.
601
		if ( ! empty( $_GET['give-run-db-update'] ) ) {
602
			$this->run_db_update();
603
		}
604
605
		// Bailout.
606
		if ( in_array( $current_screen->base, $hide_on_pages ) ) {
607
			return;
608
		}
609
610
		// Show notice if upgrade paused.
611
		if ( self::$background_updater->is_paused_process() ) {
612
			ob_start();
613
614
			$upgrade_error = get_option( 'give_upgrade_error' );
615
			if ( ! $upgrade_error ) : ?>
616
				<strong><?php _e( 'Database Update', 'give' ); ?></strong>
617
				&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' ); ?>
618
				<br>
619
				<br>
620
				<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">
621
					<?php _e( 'Restart the updater', 'give' ); ?>
622
				</a>
623
			<?php else: ?>
624
				<strong><?php _e( 'Database Update', 'give' ); ?></strong>
625
				&nbsp;&#8211;&nbsp;<?php _e( 'An unexpected issue occurred during the database update which caused it to stop automatically. Please contact support for assistance.', 'give' ); ?>
626
				<a href="<?php echo esc_url('http://docs.givewp.com/troubleshooting-db-updates')?>" target="_blank"><?php _e( 'Read More', 'give' ); ?> &raquo;</a>
627
			<?php
628
			endif;
629
			$desc_html = ob_get_clean();
630
631
			Give()->notices->register_notice( array(
632
				'id'          => 'give_upgrade_db',
633
				'type'        => 'error',
634
				'dismissible' => false,
635
				'description' => $desc_html,
636
			) );
637
		}
638
639
		// Bailout if doing upgrades.
640
		if ( $this->is_doing_updates() ) {
641
			return;
642
		}
643
644
		// Show db upgrade completed notice.
645
		if ( ! empty( $_GET['give-db-update-completed'] ) ) {
646
			Give()->notices->register_notice( array(
647
				'id'          => 'give_db_upgrade_completed',
648
				'type'        => 'updated',
649
				'description' => __( 'Give database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
650
				'show'        => true,
651
			) );
652
653
			// Start update.
654
		} elseif ( ! empty( $_GET['give-run-db-update'] ) ) {
655
			$this->run_db_update();
656
657
			// Show run the update notice.
658
		} elseif ( $this->get_total_new_db_update_count() ) {
659
			ob_start();
660
			?>
661
			<p>
662
				<strong><?php _e( 'Database Update', 'give' ); ?></strong>
663
				&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' ); ?>
664
			</p>
665
			<p class="submit">
666
				<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">
667
					<?php _e( 'Run the updater', 'give' ); ?>
668
				</a>
669
			</p>
670
			<?php
671
			$desc_html = ob_get_clean();
672
673
			Give()->notices->register_notice( array(
674
				'id'          => 'give_upgrade_db',
675
				'type'        => 'updated',
676
				'dismissible' => false,
677
				'description' => $desc_html,
678
			) );
679
		}
680
	}
681
682
	/**
683
	 * Render Give Updates Completed page
684
	 *
685
	 * @since  1.8.12
686
	 * @access public
687
	 */
688
	public function render_complete_page() {
689
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades-complete.php';
690
	}
691
692
	/**
693
	 * Render Give Updates page
694
	 *
695
	 * @since  1.8.12
696
	 * @access public
697
	 */
698
	public function render_page() {
699
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades.php';
700
	}
701
702
	/**
703
	 * Run database upgrades
704
	 *
705
	 * @since  2.0
706
	 * @access private
707
	 */
708
	private function run_db_update() {
709
		// Bailout.
710
		if ( $this->is_doing_updates() || ! $this->get_total_new_db_update_count() ) {
711
			return;
712
		}
713
714
		$updates = $this->get_updates( 'database', 'new' );
715
716
		foreach ( $updates as $update ) {
717
			self::$background_updater->push_to_queue( $update );
718
		}
719
720
		add_option( 'give_db_update_count', count( $updates ), '', false );
721
722
		add_option( 'give_doing_upgrade', array(
723
			'update_info'      => $updates[0],
724
			'step'             => 1,
725
			'update'           => 1,
726
			'heading'          => sprintf( 'Update %s of %s', 1, count( $updates ) ),
727
			'percentage'       => 0,
728
			'total_percentage' => 0,
729
		), '', false );
730
731
		self::$background_updater->save()->dispatch();
732
	}
733
734
735
	/**
736
	 * Delete resume updates
737
	 *
738
	 * @since  1.8.12
739
	 * @access public
740
	 */
741
	public function __flush_resume_updates() {
742
		$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...
743
744
		$this->update = ( $this->get_total_db_update_count() > $this->update ) ?
745
			( $this->update + 1 ) :
746
			$this->update;
747
	}
748
749
750
	/**
751
	 * Initialize updates
752
	 *
753
	 * @since  2.0
754
	 * @access public
755
	 *
756
	 * @return void
757
	 */
758
	public function __give_start_updating() {
759
		// Check permission.
760
		if (
761
			! current_user_can( 'manage_give_settings' ) ||
762
			$this->is_doing_updates()
763
		) {
764
			// Run update via ajax
765
			self::$background_updater->dispatch();
766
767
			wp_send_json_error();
768
		}
769
770
		// @todo: validate nonce
771
		// @todo: set http method to post
772
		if ( empty( $_POST['run_db_update'] ) ) {
773
			wp_send_json_error();
774
		}
775
776
		$this->run_db_update();
777
778
		wp_send_json_success();
779
	}
780
781
782
	/**
783
	 * This function handle ajax query for dn update status.
784
	 *
785
	 * @since  2.0
786
	 * @access public
787
	 *
788
	 * @return string
789
	 */
790
	public function __give_db_updates_info() {
791
		// Check permission.
792
		if ( ! current_user_can( 'manage_give_settings' ) ) {
793
			give_die();
794
		}
795
796
		$update_info   = get_option( 'give_doing_upgrade' );
797
		$response_type = '';
798
799
		if ( self::$background_updater->is_paused_process() ) {
800
			$update_info = array(
801
				'message'    => __( 'The updates have been paused.', 'give' ),
802
				'heading'    => '',
803
				'percentage' => 0,
804
			);
805
806
			if ( get_option( 'give_upgrade_error' ) ) {
807
				$update_info['message'] = __( 'An unexpected issue occurred during the database update which caused it to stop automatically. Please contact support for assistance.', 'give' );
808
			}
809
810
			$response_type = 'error';
811
812
		} elseif ( empty( $update_info ) || ! $this->get_total_new_db_update_count( true ) ) {
813
			$update_info   = array(
814
				'message'    => __( 'Give database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
815
				'heading'    => __( 'Updates Completed.', 'give' ),
816
				'percentage' => 0,
817
			);
818
			$response_type = 'success';
819
820
			delete_option( 'give_show_db_upgrade_complete_notice' );
821
		}
822
823
		$this->send_ajax_response( $update_info, $response_type );
824
	}
825
826
	/**
827
	 * Send ajax response
828
	 *
829
	 * @since  1.8.12
830
	 * @access public
831
	 *
832
	 * @param        $data
833
	 * @param string $type
834
	 */
835
	public function send_ajax_response( $data, $type = '' ) {
836
		$default = array(
837
			'message'    => '',
838
			'heading'    => '',
839
			'percentage' => 0,
840
			'step'       => 0,
841
			'update'     => 0,
842
		);
843
844
		// Set data.
845
		$data = wp_parse_args( $data, $default );
846
847
		// Enable cache.
848
		Give_Cache::enable();
849
850
		switch ( $type ) {
851
			case 'success':
852
				wp_send_json_success( $data );
853
				break;
854
855
			case 'error':
856
				wp_send_json_error( $data );
857
				break;
858
859
			default:
860
				wp_send_json( array(
861
					'data' => $data,
862
				) );
863
				break;
864
		}
865
	}
866
867
	/**
868
	 * Set current update percentage.
869
	 *
870
	 * @since  1.8.12
871
	 * @access public
872
	 *
873
	 * @param $total
874
	 * @param $current_total
875
	 */
876
	public function set_percentage( $total, $current_total ) {
877
		// Set percentage.
878
		$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...
879
880
		// Verify percentage.
881
		$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...
882
	}
883
884
	/**
885
	 * Check if parent update completed or not.
886
	 *
887
	 * @since  2.0
888
	 * @access private
889
	 *
890
	 * @param array $update
891
	 *
892
	 * @return bool|null
893
	 */
894
	public function is_parent_updates_completed( $update ) {
895
		// Bailout.
896
		if ( empty( $update['depend'] ) ) {
897
			return true;
898
		}
899
900
		// Check if dependency is valid or not.
901
		if ( ! $this->has_valid_dependency( $update ) ) {
902
			return null;
903
		}
904
905
		$is_dependency_completed = true;
906
907
		foreach ( $update['depend'] as $depend ) {
908
909
			if ( ! give_has_upgrade_completed( $depend ) ) {
910
				$is_dependency_completed = false;
911
				break;
912
			}
913
		}
914
915
		return $is_dependency_completed;
916
	}
917
918
	/**
919
	 * Flag to check if DB updates running or not.
920
	 *
921
	 * @since  2.0
922
	 * @access public
923
	 * @return bool
924
	 */
925
	public function is_doing_updates() {
926
		return (bool) Give_Cache_Setting::get_option( 'give_doing_upgrade' );
927
	}
928
929
930
	/**
931
	 * Check if update has valid dependency or not.
932
	 *
933
	 * @since  2.0
934
	 * @access public
935
	 *
936
	 * @param $update
937
	 *
938
	 * @return bool
939
	 */
940
	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...
941
		$is_valid_dependency = true;
942
		// $update_ids          = wp_list_pluck( $this->get_updates( 'database', 'all' ), 'id' );
943
		//
944
		// foreach ( $update['depend'] as $depend ) {
945
		// 	// Check if dependency is valid or not.
946
		// 	if ( ! in_array( $depend, $update_ids ) ) {
947
		// 		$is_valid_dependency = false;
948
		// 		break;
949
		// 	}
950
		// }
951
952
		return $is_valid_dependency;
953
	}
954
955
	/**
956
	 * Get updates.
957
	 *
958
	 * @since  1.8.12
959
	 * @access public
960
	 *
961
	 * @param string $update_type Tye of update.
962
	 * @param string $status      Tye of update.
963
	 *
964
	 * @return array
965
	 */
966
	public function get_updates( $update_type = '', $status = 'all' ) {
967
		// return all updates.
968
		if ( empty( $update_type ) ) {
969
			return $this->updates;
970
		}
971
972
		// Get specific update.
973
		$updates = ! empty( $this->updates[ $update_type ] ) ? $this->updates[ $update_type ] : array();
974
975
		// Bailout.
976
		if ( empty( $updates ) ) {
977
			return $updates;
978
		}
979
980
		switch ( $status ) {
981
			case 'new':
982
				// Remove already completed updates.
983
				wp_cache_delete( 'give_completed_upgrades', 'options' );
984
				$completed_updates = give_get_completed_upgrades();
985
986
				if ( ! empty( $completed_updates ) ) {
987
					foreach ( $updates as $index => $update ) {
988
						if ( in_array( $update['id'], $completed_updates ) ) {
989
							unset( $updates[ $index ] );
990
						}
991
					}
992
					$updates = array_values( $updates );
993
				}
994
995
				break;
996
		}
997
998
		return $updates;
999
	}
1000
1001
	/**
1002
	 * Get addon update count.
1003
	 *
1004
	 * @since  1.8.12
1005
	 * @access public
1006
	 * @return int
1007
	 */
1008
	public function get_total_plugin_update_count() {
1009
		return count( $this->get_updates( 'plugin' ) );
1010
	}
1011
1012
	/**
1013
	 * Get total update count
1014
	 *
1015
	 * @since  1.8.12
1016
	 * @access public
1017
	 *
1018
	 * @return int
1019
	 */
1020
	public function get_total_update_count() {
1021
		$db_update_count     = $this->get_pending_db_update_count();
1022
		$plugin_update_count = $this->get_total_plugin_update_count();
1023
1024
		return ( $db_update_count + $plugin_update_count );
1025
	}
1026
1027
	/**
1028
	 * Get total pending updates count
1029
	 *
1030
	 * @since  1.8.12
1031
	 * @access public
1032
	 *
1033
	 * @return int
1034
	 */
1035
	public function get_pending_db_update_count() {
1036
		return count( $this->get_updates( 'database', 'new' ) );
1037
	}
1038
1039
	/**
1040
	 * Get total updates count
1041
	 *
1042
	 * @since  1.8.18
1043
	 * @access public
1044
	 *
1045
	 * @return int
1046
	 */
1047
	public function get_total_db_update_count() {
1048
		return count( $this->get_updates( 'database', 'all' ) );
1049
	}
1050
1051
	/**
1052
	 * Get total new updates count
1053
	 *
1054
	 * @since  2.0
1055
	 * @access public
1056
	 *
1057
	 * @param bool $refresh
1058
	 *
1059
	 * @return int
1060
	 */
1061
	public function get_total_new_db_update_count( $refresh = false ) {
1062
		$update_count = $this->is_doing_updates() && ! $refresh ?
1063
			get_option( 'give_db_update_count' ) :
1064
			$this->get_pending_db_update_count();
1065
1066
		return $update_count;
1067
	}
1068
1069
	/**
1070
	 * Get total new updates count
1071
	 *
1072
	 * @since  2.0
1073
	 * @access public
1074
	 *
1075
	 * @param bool $refresh
1076
	 *
1077
	 * @return int
1078
	 */
1079
	public function get_running_db_update( $refresh = false ) {
1080
		$current_update = 1;
1081
1082
		if ( $this->is_doing_updates() && ! $refresh ) {
1083
			$current_update = get_option( 'give_doing_upgrade' );
1084
			$current_update = $current_update['update'];
1085
		}
1086
1087
		return $current_update;
1088
	}
1089
1090
	/**
1091
	 * Get database update processing percentage.
1092
	 *
1093
	 * @since  2.0
1094
	 * @access public
1095
	 *
1096
	 * @param bool $refresh
1097
	 *
1098
	 * @return float|int
1099
	 */
1100
	public function get_db_update_processing_percentage( $refresh = false ) {
1101
		// Bailout.
1102
		if ( ! $this->get_total_new_db_update_count( $refresh ) ) {
1103
			return 0;
1104
		}
1105
1106
		$resume_update            = get_option( 'give_doing_upgrade' );
1107
		$update_count_percentages = ( ( $this->get_running_db_update( $refresh ) - 1 ) / $this->get_total_new_db_update_count( $refresh ) ) * 100;
1108
		$update_percentage_share  = ( 1 / $this->get_total_new_db_update_count() ) * 100;
1109
		$upgrade_percentage       = ( ( $resume_update['percentage'] * $update_percentage_share ) / 100 );
1110
1111
		$final_percentage = $update_count_percentages + $upgrade_percentage;
1112
1113
		return $this->is_doing_updates() ?
1114
			( absint( $final_percentage ) ?
1115
				absint( $final_percentage ) :
1116
				round( $final_percentage, 2 )
1117
			) :
1118
			0;
1119
	}
1120
1121
1122
	/**
1123
	 * Get all update ids.
1124
	 *
1125
	 * @since 2.0.3
1126
	 *
1127
	 * @return array
1128
	 */
1129
	public function get_update_ids() {
1130
		$all_updates    = $this->get_updates( 'database', 'all' );
1131
		$all_update_ids = wp_list_pluck( $all_updates, 'id' );
1132
1133
		return $all_update_ids;
1134
	}
1135
1136
	/**
1137
	 * Get offset count
1138
	 *
1139
	 * @since  2.0.5
1140
	 * @access public
1141
	 *
1142
	 * @param int $process_item_count
1143
	 *
1144
	 * @return float|int
1145
	 */
1146
	public function get_offset( $process_item_count ) {
1147
		return ( 1 === $this->step ) ?
1148
			0 :
1149
			( $this->step - 1 ) * $process_item_count;
1150
	}
1151
}
1152
1153
Give_Updates::get_instance()->setup();
1154