Test Failed
Push — issues/2531 ( 1109ed...e1606f )
by Ravinder
04:22
created

Give_Updates::get_running_db_update()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 0
dl 0
loc 7
rs 9.4285
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 static
24
	 * @var Give_Background_Updater
25
	 */
26
	static private $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_notices', array( $this, '__show_notice' ) );
153
154
		if ( is_admin() ) {
155
			add_action( 'admin_init', array( $this, '__change_donations_label' ), 9999 );
156
			add_action( 'admin_menu', array( $this, '__register_menu' ), 9999 );
157
		}
158
	}
159
160
	/**
161
	 * Register plugin add-on updates.
162
	 *
163
	 * @since  1.8.12
164
	 * @access public
165
	 */
166
	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...
167
		$addons         = give_get_plugins();
168
		$plugin_updates = get_plugin_updates();
169
170
		foreach ( $addons as $key => $info ) {
171
			if ( 'active' != $info['Status'] || 'add-on' != $info['Type'] || empty( $plugin_updates[ $key ] ) ) {
172
				continue;
173
			}
174
175
			$this->updates['plugin'][] = array_merge( $info, (array) $plugin_updates[ $key ] );
176
		}
177
	}
178
179
180
	/**
181
	 * Fire custom action hook to register updates
182
	 *
183
	 * @since  1.8.12
184
	 * @access public
185
	 */
186
	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...
187
		if ( ! is_admin() ) {
188
			return;
189
		}
190
191
		/**
192
		 * Fire the hook
193
		 *
194
		 * @since 1.8.12
195
		 */
196
		do_action( 'give_register_updates', $this );
197
	}
198
199
	/**
200
	 * Rename `Donations` menu title if updates exists
201
	 *
202
	 * @since  1.8.12
203
	 * @access public
204
	 */
205
	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...
206
		global $menu;
207
208
		// Bailout.
209
		if ( empty( $menu ) || ! $this->get_total_update_count() ) {
210
			return;
211
		}
212
213
		foreach ( $menu as $index => $menu_item ) {
214
			if ( 'edit.php?post_type=give_forms' !== $menu_item[2] ) {
215
				continue;
216
			}
217
218
			$menu[ $index ][0] = sprintf(
219
				'%1$s <span class="update-plugins count-%2$s"><span class="plugin-count">%2$s%3$s</span></span>',
220
				__( 'Donations', 'give' ),
221
				$this->is_doing_updates() ?
222
					$this->get_db_update_processing_percentage() :
223
					$this->get_total_new_db_update_count(),
224
				$this->is_doing_updates() ? '%' : ''
225
			);
226
227
			break;
228
		}
229
	}
230
231
	/**
232
	 * Register updates menu
233
	 *
234
	 * @since  1.8.12
235
	 * @access public
236
	 */
237
	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...
238
239
		// Load plugin updates.
240
		$this->__register_plugin_addon_updates();
241
242
		// Bailout.
243
		if ( ! $this->get_total_update_count() ) {
244
			// Show complete update message if still on update setting page.
245
			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...
246
				// Upgrades
247
				add_submenu_page(
248
					'edit.php?post_type=give_forms',
249
					esc_html__( 'Give Updates Complete', 'give' ),
250
					__( 'Updates', 'give' ),
251
					'manage_give_settings',
252
					'give-updates',
253
					array( $this, 'render_complete_page' )
254
				);
255
			}
256
257
			return;
258
		}
259
260
		// Upgrades
261
		add_submenu_page(
262
			'edit.php?post_type=give_forms',
263
			esc_html__( 'Give Updates', 'give' ),
264
			sprintf(
265
				'%1$s <span class="update-plugins count-%2$s"><span class="plugin-count">%2$s%3$s</span></span>',
266
				__( 'Updates', 'give' ),
267
				$this->is_doing_updates() ?
268
					$this->get_db_update_processing_percentage() :
269
					$this->get_total_new_db_update_count(),
270
				$this->is_doing_updates() ? '%' : ''
271
			),
272
			'manage_give_settings',
273
			'give-updates',
274
			array( $this, 'render_page' )
275
		);
276
	}
277
278
279
	/**
280
	 * Show update related notices
281
	 *
282
	 * @since  2.0
283
	 * @access public
284
	 */
285
	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...
286
		// Show db upgrade completed notice.
287
		if (
288
			! wp_doing_ajax() &&
289
			current_user_can( 'manage_give_settings' ) &&
290
			get_option( 'give_show_db_upgrade_complete_notice' ) &&
291
			! isset( $_GET['give-update-message'] )
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
292
		) {
293
			delete_option('give_show_db_upgrade_complete_notice' );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
294
295
			wp_redirect( add_query_arg( array( 'give-update-message' => 'give_db_upgrade_completed' ) ) );
296
			exit();
297
		}
298
	}
299
300
301
	/**
302
	 * Show update related notices
303
	 *
304
	 * @since  2.0
305
	 * @access public
306
	 */
307
	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...
308
		// Show db upgrade completed notice.
309
		if (
310
			current_user_can( 'manage_give_settings' ) &&
311
			! empty( $_GET['give-update-message'] ) &&
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
312
			( ! 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...
313
		) {
314
			Give()->notices->register_notice( array(
315
				'id'          => 'give_db_upgrade_completed',
316
				'type'        => 'updated',
317
				'description' => __( 'Database updated successfully.', 'give' ),
318
				'show'        => true,
319
			) );
320
		}
321
	}
322
323
	/**
324
	 * Render Give Updates Completed page
325
	 *
326
	 * @since  1.8.12
327
	 * @access public
328
	 */
329
	public function render_complete_page() {
330
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades-complete.php';
331
	}
332
333
	/**
334
	 * Render Give Updates page
335
	 *
336
	 * @since  1.8.12
337
	 * @access public
338
	 */
339
	public function render_page() {
340
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades.php';
341
	}
342
343
344
	/**
345
	 * Delete resume updates
346
	 *
347
	 * @since  1.8.12
348
	 * @access public
349
	 */
350
	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...
351
		//delete_option( 'give_doing_upgrade' );
352
		update_option( 'give_version', preg_replace( '/[^0-9.].*/', '', GIVE_VERSION ) );
353
354
		// Reset counter.
355
		$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...
356
		++ $this->update;
357
	}
358
359
360
	/**
361
	 * Initialize updates
362
	 *
363
	 * @since  2.0
364
	 * @access public
365
	 *
366
	 * @return void
367
	 */
368
	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...
369
		// Check permission.
370
		if (
371
			! current_user_can( 'manage_give_settings' ) ||
372
			$this->is_doing_updates()
373
		) {
374
			wp_send_json_error();
375
		}
376
377
		// @todo: validate nonce
378
		// @todo: set http method to post
379
		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...
380
			wp_send_json_error();
381
		}
382
383
		$updates = $this->get_updates( 'database', 'new' );
384
385
		foreach ( $updates as $update ) {
386
			self::$background_updater->push_to_queue( $update );
387
		}
388
389
		add_option( 'give_db_update_count', count( $updates ), '', 'no' );
390
391
		add_option( 'give_doing_upgrade', array(
392
			'update_info' => $updates[0],
393
			'step'        => 1,
394
			'update'      => 1,
395
			'heading'     => sprintf( 'Update %s of %s', 1, count( $updates ) ),
396
			'percentage'  => 0,
397
		), '', 'no' );
398
399
		self::$background_updater->save()->dispatch();
400
401
		wp_send_json_success();
402
	}
403
404
405
	/**
406
	 * This function handle ajax query for dn update status.
407
	 *
408
	 * @since  2.0
409
	 * @access public
410
	 *
411
	 * @return string
412
	 */
413
	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...
414
		$update_info   = get_option( 'give_doing_upgrade' );
415
		$response_type = '';
416
417
		if ( empty( $update_info ) && ! $this->get_pending_db_update_count() ) {
418
			$update_info   = array(
419
				'message'    => __( 'Database updated successfully.', 'give' ),
420
				'heading'    => __( 'Updates Completed.', 'give' ),
421
				'percentage' => 0,
422
			);
423
			$response_type = 'success';
424
425
			delete_option( 'give_show_db_upgrade_complete_notice' );
426
		}
427
428
		$this->send_ajax_response( $update_info, $response_type );
429
	}
430
431
	/**
432
	 * Send ajax response
433
	 *
434
	 * @since  1.8.12
435
	 * @access public
436
	 *
437
	 * @param        $data
438
	 * @param string $type
439
	 */
440
	public function send_ajax_response( $data, $type = '' ) {
441
		$default = array(
442
			'message'    => '',
443
			'heading'    => '',
444
			'percentage' => 0,
445
			'step'       => 0,
446
			'update'     => 0,
447
		);
448
449
		// Set data.
450
		$data = wp_parse_args( $data, $default );
451
452
		// Enable cache.
453
		Give_Cache::enable();
454
455
		switch ( $type ) {
456
			case 'success':
457
				wp_send_json_success( $data );
458
				break;
459
460
			case 'error':
461
				wp_send_json_error( $data );
462
				break;
463
464
			default:
465
				wp_send_json( array(
466
					'data' => $data,
467
				) );
468
				break;
469
		}
470
	}
471
472
	/**
473
	 * Set current update percentage.
474
	 *
475
	 * @since  1.8.12
476
	 * @access public
477
	 *
478
	 * @param $total
479
	 * @param $current_total
480
	 */
481
	public function set_percentage( $total, $current_total ) {
482
		// Set percentage.
483
		$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...
484
485
		// Verify percentage.
486
		$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...
487
	}
488
489
	/**
490
	 * Check if parent update completed or not.
491
	 *
492
	 * @since  2.0
493
	 * @access private
494
	 *
495
	 * @param array $update
496
	 *
497
	 * @return bool|null
498
	 */
499
	public function is_parent_updates_completed( $update ) {
500
		// Bailout.
501
		if ( empty( $update['depend'] ) ) {
502
			return true;
503
		}
504
505
		$is_dependency_completed = true;
506
507
		foreach ( $update['depend'] as $depend ) {
508
			// Check if dependency is valid or not.
509
			if ( ! $this->has_valid_dependency( $update ) ) {
510
				$is_dependency_completed = null;
511
				break;
512
			}
513
514
			if ( ! give_has_upgrade_completed( $depend ) ) {
515
				$is_dependency_completed = false;
516
				break;
517
			}
518
		}
519
520
		return $is_dependency_completed;
521
	}
522
523
	/**
524
	 * Flag to check if DB updates running or not.
525
	 *
526
	 * @since  2.0
527
	 * @access public
528
	 * @return bool
529
	 */
530
	public function is_doing_updates() {
531
		return (bool) get_option( 'give_doing_upgrade' );
532
	}
533
534
535
	/**
536
	 * Check if update has valid dependency or not.
537
	 *
538
	 * @since  2.0
539
	 * @access public
540
	 *
541
	 * @param $update
542
	 *
543
	 * @return bool
544
	 */
545
	public function has_valid_dependency( $update ) {
546
		$is_valid_dependency = true;
547
		$update_ids          = wp_list_pluck( $this->get_updates( 'database' ), 'id' );
548
549
		foreach ( $update['depend'] as $depend ) {
550
			// Check if dependency is valid or not.
551
			if ( ! in_array( $depend, $update_ids ) ) {
552
				$is_valid_dependency = false;
553
				break;
554
			}
555
		}
556
557
		return $is_valid_dependency;
558
	}
559
560
	/**
561
	 * Get updates.
562
	 *
563
	 * @since  1.8.12
564
	 * @access public
565
	 *
566
	 * @param string $update_type Tye of update.
567
	 * @param string $status      Tye of update.
568
	 *
569
	 * @return array
570
	 */
571
	public function get_updates( $update_type = '', $status = 'all' ) {
572
		// return all updates.
573
		if ( empty( $update_type ) ) {
574
			return $this->updates;
575
		}
576
577
		// Get specific update.
578
		$updates = ! empty( $this->updates[ $update_type ] ) ? $this->updates[ $update_type ] : array();
579
580
		// Bailout.
581
		if ( empty( $updates ) ) {
582
			return $updates;
583
		}
584
585
		switch ( $status ) {
586
			case 'new':
587
				// Remove already completed updates.
588
				$completed_updates = give_get_completed_upgrades();
589
590
				if ( ! empty( $completed_updates ) ) {
591
					foreach ( $updates as $index => $update ) {
592
						if ( in_array( $update['id'], $completed_updates ) ) {
593
							unset( $updates[ $index ] );
594
						}
595
					}
596
					$updates = array_values( $updates );
597
				}
598
599
				break;
600
		}
601
602
		return $updates;
603
	}
604
605
	/**
606
	 * Get addon update count.
607
	 *
608
	 * @since  1.8.12
609
	 * @access public
610
	 * @return int
611
	 */
612
	public function get_total_plugin_update_count() {
613
		return count( $this->get_updates( 'plugin' ) );
614
	}
615
616
	/**
617
	 * Get total update count
618
	 *
619
	 * @since  1.8.12
620
	 * @access public
621
	 *
622
	 * @return int
623
	 */
624
	public function get_total_update_count() {
625
		$db_update_count     = $this->get_pending_db_update_count();
626
		$plugin_update_count = $this->get_total_plugin_update_count();
627
628
		return ( $db_update_count + $plugin_update_count );
629
	}
630
631
	/**
632
	 * Get total pending updates count
633
	 *
634
	 * @since  1.8.12
635
	 * @access public
636
	 *
637
	 * @return int
638
	 */
639
	public function get_pending_db_update_count() {
640
		return count( $this->get_updates( 'database', 'new' ) );
641
	}
642
643
	/**
644
	 * Get total updates count
645
	 *
646
	 * @since  1.8.18
647
	 * @access public
648
	 *
649
	 * @return int
650
	 */
651
	public function get_total_db_update_count() {
652
		return count( $this->get_updates( 'database', 'all' ) );
653
	}
654
655
	/**
656
	 * Get total new updates count
657
	 *
658
	 * @since  2.0
659
	 * @access public
660
	 *
661
	 * @return int
662
	 */
663
	public function get_total_new_db_update_count() {
664
		return $this->is_doing_updates() ?
665
			get_option( 'give_db_update_count' ) :
666
			$this->get_pending_db_update_count();
667
	}
668
669
	/**
670
	 * Get total new updates count
671
	 *
672
	 * @since  2.0
673
	 * @access public
674
	 *
675
	 * @return int
676
	 */
677
	public function get_running_db_update() {
678
		$current_update = get_option( 'give_doing_upgrade' );
679
680
		return $this->is_doing_updates() ?
681
			$current_update['update'] :
682
			1;
683
	}
684
685
	/**
686
	 * Get database update processing percentage.
687
	 *
688
	 * @since  2.0
689
	 * @access public
690
	 * @return float|int
691
	 */
692
	public function get_db_update_processing_percentage() {
693
		// Bailout.
694
		if ( ! $this->get_total_new_db_update_count() ) {
695
			return 0;
696
		}
697
698
		$resume_update            = get_option( 'give_doing_upgrade' );
699
		$update_count_percentages = ( ( $this->get_running_db_update() - 1 ) / $this->get_total_new_db_update_count() ) * 100;
700
		$update_percentage_share  = ( 1 / $this->get_total_new_db_update_count() ) * 100;
701
		$upgrade_percentage       = ( ( $resume_update['percentage'] * $update_percentage_share ) / 100 );
702
703
		return $this->is_doing_updates() ?
704
			absint( $update_count_percentages + $upgrade_percentage ) :
705
			0;
706
	}
707
}
708
709
Give_Updates::get_instance()->setup();
710