Test Failed
Push — feature/upgrdae-auto-pause ( 76a297 )
by Ravinder
06:26
created

Give_Updates::get_update_ids()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 6
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 public
24
	 * @var Give_Background_Updater
25
	 */
26
	static public $background_updater;
27
28
	/**
29
	 * Updates
30
	 *
31
	 * @since  1.8.12
32
	 * @access private
33
	 * @var array
34
	 */
35
	private $updates = array();
36
37
	/**
38
	 * Current update percentage number
39
	 *
40
	 * @since  1.8.12
41
	 * @access private
42
	 * @var array
43
	 */
44
	public $percentage = 0;
45
46
	/**
47
	 * Current update step number
48
	 *
49
	 * @since  1.8.12
50
	 * @access private
51
	 * @var array
52
	 */
53
	public $step = 1;
54
55
	/**
56
	 * Current update number
57
	 *
58
	 * @since  1.8.12
59
	 * @access private
60
	 * @var array
61
	 */
62
	public $update = 1;
63
64
	/**
65
	 * Singleton pattern.
66
	 *
67
	 * @since  1.8.12
68
	 * @access private
69
	 *
70
	 * @param Give_Updates .
71
	 */
72
	private function __construct() {
73
	}
74
75
	/**
76
	 * Register updates
77
	 *
78
	 * @since  1.8.12
79
	 * @access public
80
	 *
81
	 * @param array $args
82
	 */
83
	public function register( $args ) {
84
		$args_default = array(
85
			'id'       => '',
86
			'version'  => '',
87
			'callback' => '',
88
		);
89
90
		$args = wp_parse_args( $args, $args_default );
91
92
		// You can only register database upgrade.
93
		$args['type'] = 'database';
94
95
		// Bailout.
96
		if (
97
			empty( $args['id'] ) ||
98
			empty( $args['version'] ) ||
99
			empty( $args['callback'] ) ||
100
			! is_callable( $args['callback'] )
101
		) {
102
			return;
103
		}
104
105
		// Change depend param to array.
106
		if ( isset( $args['depend'] ) && is_string( $args['depend'] ) ) {
107
			$args['depend'] = array( $args['depend'] );
108
		}
109
110
		$this->updates[ $args['type'] ][] = $args;
111
	}
112
113
	/**
114
	 * Get instance.
115
	 *
116
	 * @since
117
	 * @access static
118
	 * @return static
119
	 */
120
	static function get_instance() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

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

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

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

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

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

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

Loading history...
326
			! $force &&
327
			(
328
				wp_doing_ajax() ||
329
				! isset( $_GET['page'] ) ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
330
				'give-updates' !== $_GET['page'] ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
331
				! isset( $_GET['give-pause-db-upgrades'] ) ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
332
				self::$background_updater->is_paused_process()
333
			)
334
335
		) {
336
			return false;
337
		}
338
339
		$batch = self::$background_updater->get_all_batch();
340
341
		if ( ! empty( $batch ) ) {
342
			delete_option('give_upgrade_error');
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
343
			update_option( 'give_paused_batches', $batch,  'no' );
344
			delete_option( $batch->key );
345
			delete_site_transient( self::$background_updater->get_identifier() . '_process_lock' );
346
			wp_clear_scheduled_hook( self::$background_updater->get_cron_identifier() );
347
348
			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...
349
350
			/**
351
			 * Fire action when pause db updates
352
			 *
353
			 * @since 2.0.1
354
			 */
355
			do_action( 'give_pause_db_upgrade', $this );
356
		}
357
358
		return true;
359
	}
360
361
	/**
362
	 * Restart db upgrade
363
	 *
364
	 * @since  2.0.1
365
	 * @access public
366
	 *
367
	 * @return bool
368
	 */
369
	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...
370
		// Bailout.
371 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...
372
			wp_doing_ajax() ||
373
			! isset( $_GET['page'] ) ||
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
374
			'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...
375
			! 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...
376
			! self::$background_updater->is_paused_process()
377
		) {
378
			return false;
379
		}
380
381
		$batch = get_option( 'give_paused_batches' );
382
383
		if ( ! empty( $batch ) ) {
384
			update_option( $batch->key, $batch->data );
385
			delete_option( 'give_paused_batches' );
386
387
			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...
388
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
389
390
			/** Fire action when restart db updates
391
			 *
392
			 * @since 2.0.1
393
			 */
394
			do_action( 'give_restart_db_upgrade', $this );
395
396
			self::$background_updater->dispatch();
397
		}
398
399
		return true;
400
	}
401
402
	/**
403
	 * Health check for updates.
404
	 *
405
	 * @since  2.0
406
	 * @access public
407
	 *
408
	 * @param Give_Updates $give_updates
409
	 */
410
	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...
411
		if ( ! $this->is_doing_updates() ) {
412
			return;
413
		}
414
415
		$batch                = Give_Updates::$background_updater->get_all_batch();
416
		$batch_data_count     = count( $batch->data );
417
		$all_updates          = $give_updates->get_updates( 'database', 'all' );
418
		$all_update_ids       = wp_list_pluck( $all_updates, 'id' );
419
		$all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : array();
420
		$log_data             = '';
421
		$doing_upgrade_args   = get_option( 'give_doing_upgrade' );
422
423
		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...
424
			$log_data .= 'Doing update:' . "\n";
425
			$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...
426
		}
427
428
		if ( ! empty( $batch->data ) ) {
429
430
			foreach ( $batch->data as $index => $update ) {
431
				$log_data = print_r( $update, true ) . "\n";
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
432
433
				if ( ! is_callable( $update['callback'] ) ) {
434
					$log_data .= 'Removing missing callback update: ' . "{$update['id']}\n";
435
					unset( $batch->data[ $index ] );
436
				}
437
438
				if ( ! empty( $update['depend'] ) ) {
439
440
					foreach ( $update['depend'] as $depend ) {
441
						if ( give_has_upgrade_completed( $depend ) ) {
442
							$log_data .= 'Completed update: ' . "{$depend}\n";
443
							continue;
444
						}
445
446
						if ( in_array( $depend, $all_update_ids ) && ! in_array( $depend, $all_batch_update_ids ) ) {
447
							$log_data .= 'Adding missing update: ' . "{$depend}\n";
448
							array_unshift( $batch->data, $all_updates[ array_search( $depend, $all_update_ids ) ] );
449
						}
450
					}
451
				}
452
			}
453
		}
454
455
		if ( $new_updates = $this->get_updates( 'database', 'new' ) ) {
456
			$all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : array();
457
458
			foreach ( $new_updates as $index => $new_update ) {
459
				if ( give_has_upgrade_completed( $new_update['id'] ) || in_array( $new_update['id'], $all_batch_update_ids ) ) {
460
					unset( $new_updates[ $index ] );
461
				}
462
			}
463
464
			if ( ! empty( $new_updates ) ) {
465
				$log_data .= 'Adding new update: ' . "\n";
466
				$log_data .= print_r( $new_updates, true ) . "\n";
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
467
468
				$batch->data = array_merge( (array) $batch->data, $new_updates );
469
				update_option( 'give_db_update_count', ( absint( get_option( 'give_db_update_count' ) ) + count( $new_updates ) ) );
470
			}
471
		}
472
473
		if ( $batch_data_count !== count( $batch->data ) ) {
474
			$log_data .= 'Updating batch' . "\n";
475
			$log_data .= print_r( $batch, true );
0 ignored issues
show
introduced by
The use of function print_r() is discouraged
Loading history...
476
477
			$doing_upgrade_args['heading']          = sprintf( 'Update %s of %s', $doing_upgrade_args['update'], get_option( 'give_db_update_count' ) );
478
			$doing_upgrade_args['total_percentage'] = $this->get_db_update_processing_percentage();
479
			update_option( 'give_doing_upgrade', $doing_upgrade_args );
480
481
			if ( ! empty( $batch->key ) ) {
482
				update_option( $batch->key, $batch->data );
483
			} else {
484
485
				update_option( 'give_db_update_count', count( $batch->data ) );
486
487
				$doing_upgrade_args['update']  = $give_updates->update;
488
				$doing_upgrade_args['heading'] = sprintf( 'Update %s of %s', 1, count( $batch->data ) );
489
490
				update_option( 'give_doing_upgrade', $doing_upgrade_args );
491
492
				foreach ( $batch->data as $data ) {
493
					Give_Updates::$background_updater->push_to_queue( $data );
494
				}
495
496
				Give_Updates::$background_updater->save();
497
			}
498
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
499
500
			Give()->logs->add( 'Update Health Check', $log_data, 0, 'update' );
501
		}
502
	}
503
504
505
	/**
506
	 * Show update related notices
507
	 *
508
	 * @since  2.0
509
	 * @access public
510
	 */
511
	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...
512
		// Bailout.
513
		if ( ! current_user_can( 'manage_give_settings' ) ) {
514
			return;
515
		}
516
517
		// Run DB updates.
518
		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...
519
			$this->run_db_update();
520
		}
521
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
522
523
		// Bailout.
524
		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...
525
			return;
526
		}
527
528
		// Show notice if upgrade paused.
529
		if ( self::$background_updater->is_paused_process() ) {
530
			ob_start();
531
532
			if ( ! get_option( 'give_upgrade_error' ) ):
533
				?>
534
				<strong><?php _e( 'Database Update', 'give' ); ?></strong>
535
				&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' ); ?>
536
				<br>
537
				<br>
538
				<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">
539
					<?php _e( 'Restart the updater', 'give' ); ?>
540
				</a>
541
				<script type="text/javascript">
542
					jQuery('.give-restart-updater-btn').click('click', function () {
543
						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
544
					});
545
				</script>
546 View Code Duplication
			<?php else: ?>
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
547
				<strong><?php _e( 'Database Update', 'give' ); ?></strong>
548
				&nbsp;&#8211;&nbsp;<?php echo sprintf(
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'sprintf'
Loading history...
549
					'%s <a href="%s" target="_blank">%s</a>.',
550
					__( 'Database updates stop automatically because some unexpected issue occur during upgrade. Please contact', 'give' ),
551
					esc_url( 'https://givewp.com/support/' ),
552
					__( 'GiveWP support', 'give' )
553
				); ?>
554
			<?php
555
			endif;
556
			$desc_html = ob_get_clean();
557
558
			Give()->notices->register_notice( array(
559
				'id'          => 'give_upgrade_db',
560
				'type'        => 'error',
561
				'dismissible' => false,
562
				'description' => $desc_html,
563
			) );
564
		}
565
566
		// Bailout if doing upgrades.
567
		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...
568
			return;
569
		}
570
571
		// Show notice if ajax is not working.
572
		if ( ! give_test_ajax_works() ) {
573
			Give()->notices->register_notice(
574
				array(
575
					'id'          => 'give_db_upgrade_ajax_inaccessible',
576
					'type'        => 'error',
577
					'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;' ),
578
					'show'        => true,
579
				)
580
			);
581
582
			return;
583
		}
584
585
		// Show db upgrade completed notice.
586
		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...
587
			Give()->notices->register_notice( array(
588
				'id'          => 'give_db_upgrade_completed',
589
				'type'        => 'updated',
590
				'description' => __( 'Give database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
591
				'show'        => true,
592
			) );
593
594
			// Start update.
595
		} 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...
596
			$this->run_db_update();
597
598
			// Show run the update notice.
599
		} elseif ( $this->get_total_new_db_update_count() ) {
600
			ob_start();
601
			?>
602
			<p>
603
				<strong><?php _e( 'Database Update', 'give' ); ?></strong>
604
				&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' ); ?>
605
			</p>
606
			<p class="submit">
607
				<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">
608
					<?php _e( 'Run the updater', 'give' ); ?>
609
				</a>
610
			</p>
611
			<script type="text/javascript">
612
				jQuery('.give-run-update-now').click('click', function () {
613
					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
614
				});
615
			</script>
616
			<?php
617
			$desc_html = ob_get_clean();
618
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
619
620
			Give()->notices->register_notice( array(
621
				'id'          => 'give_upgrade_db',
622
				'type'        => 'updated',
623
				'dismissible' => false,
624
				'description' => $desc_html,
625
			) );
626
		}
627
	}
628
629
	/**
630
	 * Render Give Updates Completed page
631
	 *
632
	 * @since  1.8.12
633
	 * @access public
634
	 */
635
	public function render_complete_page() {
636
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades-complete.php';
637
	}
638
639
	/**
640
	 * Render Give Updates page
641
	 *
642
	 * @since  1.8.12
643
	 * @access public
644
	 */
645
	public function render_page() {
646
		include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades.php';
647
	}
648
649
	/**
650
	 * Run database upgrades
651
	 *
652
	 * @since  2.0
653
	 * @access private
654
	 */
655
	private function run_db_update() {
656
		// Bailout.
657
		if ( $this->is_doing_updates() || ! $this->get_total_new_db_update_count() ) {
658
			return;
659
		}
660
661
		$updates = $this->get_updates( 'database', 'new' );
662
663
		foreach ( $updates as $update ) {
664
			self::$background_updater->push_to_queue( $update );
665
		}
666
667
		add_option( 'give_db_update_count', count( $updates ), '', 'no' );
668
669
		add_option( 'give_doing_upgrade', array(
670
			'update_info' => $updates[0],
671
			'step'        => 1,
672
			'update'      => 1,
673
			'heading'     => sprintf( 'Update %s of %s', 1, count( $updates ) ),
674
			'percentage'  => 0,
675
			'total_percentage'  => 0,
676
		), '', 'no' );
677
678
		self::$background_updater->save()->dispatch();
679
	}
680
681
682
	/**
683
	 * Delete resume updates
684
	 *
685
	 * @since  1.8.12
686
	 * @access public
687
	 */
688
	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...
689
		//delete_option( 'give_doing_upgrade' );
690
		update_option( 'give_version', preg_replace( '/[^0-9.].*/', '', GIVE_VERSION ) );
691
692
		// Reset counter.
693
		$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...
694
695
		$this->update = ( $this->get_total_db_update_count() > $this->update ) ?
696
			( $this->update + 1 ) :
697
			$this->update;
698
	}
699
700
701
	/**
702
	 * Initialize updates
703
	 *
704
	 * @since  2.0
705
	 * @access public
706
	 *
707
	 * @return void
708
	 */
709
	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...
710
		// Check permission.
711
		if (
712
			! current_user_can( 'manage_give_settings' ) ||
713
			$this->is_doing_updates()
714
		) {
715
			wp_send_json_error();
716
		}
717
718
		// @todo: validate nonce
719
		// @todo: set http method to post
720
		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...
721
			wp_send_json_error();
722
		}
723
724
		$this->run_db_update();
725
726
		wp_send_json_success();
727
	}
728
729
730
	/**
731
	 * This function handle ajax query for dn update status.
732
	 *
733
	 * @since  2.0
734
	 * @access public
735
	 *
736
	 * @return string
737
	 */
738
	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...
739
		$update_info   = get_option( 'give_doing_upgrade' );
740
		$response_type = '';
741
742
		if ( empty( $update_info ) ) {
743
			$update_info   = array(
744
				'message'    => __( 'Give database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
745
				'heading'    => __( 'Updates Completed.', 'give' ),
746
				'percentage' => 0,
747
			);
748
			$response_type = 'success';
749
750
			delete_option( 'give_show_db_upgrade_complete_notice' );
751
		}
752
753
		$this->send_ajax_response( $update_info, $response_type );
754
	}
755
756
	/**
757
	 * Send ajax response
758
	 *
759
	 * @since  1.8.12
760
	 * @access public
761
	 *
762
	 * @param        $data
763
	 * @param string $type
764
	 */
765
	public function send_ajax_response( $data, $type = '' ) {
766
		$default = array(
767
			'message'    => '',
768
			'heading'    => '',
769
			'percentage' => 0,
770
			'step'       => 0,
771
			'update'     => 0,
772
		);
773
774
		// Set data.
775
		$data = wp_parse_args( $data, $default );
776
777
		// Enable cache.
778
		Give_Cache::enable();
779
780
		switch ( $type ) {
781
			case 'success':
782
				wp_send_json_success( $data );
783
				break;
784
785
			case 'error':
786
				wp_send_json_error( $data );
787
				break;
788
789
			default:
790
				wp_send_json( array(
791
					'data' => $data,
792
				) );
793
				break;
794
		}
795
	}
796
797
	/**
798
	 * Set current update percentage.
799
	 *
800
	 * @since  1.8.12
801
	 * @access public
802
	 *
803
	 * @param $total
804
	 * @param $current_total
805
	 */
806
	public function set_percentage( $total, $current_total ) {
807
		// Set percentage.
808
		$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...
809
810
		// Verify percentage.
811
		$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...
812
	}
813
814
	/**
815
	 * Check if parent update completed or not.
816
	 *
817
	 * @since  2.0
818
	 * @access private
819
	 *
820
	 * @param array $update
821
	 *
822
	 * @return bool|null
823
	 */
824
	public function is_parent_updates_completed( $update ) {
825
		// Bailout.
826
		if ( empty( $update['depend'] ) ) {
827
			return true;
828
		}
829
830
		// Check if dependency is valid or not.
831
		if ( ! $this->has_valid_dependency( $update ) ) {
832
			return null;
833
		}
834
835
		$is_dependency_completed = true;
836
837
		foreach ( $update['depend'] as $depend ) {
838
839
			if ( ! give_has_upgrade_completed( $depend ) ) {
840
				$is_dependency_completed = false;
841
				break;
842
			}
843
		}
844
845
		return $is_dependency_completed;
846
	}
847
848
	/**
849
	 * Flag to check if DB updates running or not.
850
	 *
851
	 * @since  2.0
852
	 * @access public
853
	 * @return bool
854
	 */
855
	public function is_doing_updates() {
856
		return (bool) get_option( 'give_doing_upgrade' );
857
	}
858
859
860
	/**
861
	 * Check if update has valid dependency or not.
862
	 *
863
	 * @since  2.0
864
	 * @access public
865
	 *
866
	 * @param $update
867
	 *
868
	 * @return bool
869
	 */
870
	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...
871
		$is_valid_dependency = true;
872
		// $update_ids          = wp_list_pluck( $this->get_updates( 'database', 'all' ), 'id' );
873
		//
874
		// foreach ( $update['depend'] as $depend ) {
875
		// 	// Check if dependency is valid or not.
876
		// 	if ( ! in_array( $depend, $update_ids ) ) {
877
		// 		$is_valid_dependency = false;
878
		// 		break;
879
		// 	}
880
		// }
881
882
		return $is_valid_dependency;
883
	}
884
885
	/**
886
	 * Get updates.
887
	 *
888
	 * @since  1.8.12
889
	 * @access public
890
	 *
891
	 * @param string $update_type Tye of update.
892
	 * @param string $status      Tye of update.
893
	 *
894
	 * @return array
895
	 */
896
	public function get_updates( $update_type = '', $status = 'all' ) {
897
		// return all updates.
898
		if ( empty( $update_type ) ) {
899
			return $this->updates;
900
		}
901
902
		// Get specific update.
903
		$updates = ! empty( $this->updates[ $update_type ] ) ? $this->updates[ $update_type ] : array();
904
905
		// Bailout.
906
		if ( empty( $updates ) ) {
907
			return $updates;
908
		}
909
910
		switch ( $status ) {
911
			case 'new':
912
				// Remove already completed updates.
913
				$completed_updates = give_get_completed_upgrades();
914
915
				if ( ! empty( $completed_updates ) ) {
916
					foreach ( $updates as $index => $update ) {
917
						if ( in_array( $update['id'], $completed_updates ) ) {
918
							unset( $updates[ $index ] );
919
						}
920
					}
921
					$updates = array_values( $updates );
922
				}
923
924
				break;
925
		}
926
927
		return $updates;
928
	}
929
930
	/**
931
	 * Get addon update count.
932
	 *
933
	 * @since  1.8.12
934
	 * @access public
935
	 * @return int
936
	 */
937
	public function get_total_plugin_update_count() {
938
		return count( $this->get_updates( 'plugin' ) );
939
	}
940
941
	/**
942
	 * Get total update count
943
	 *
944
	 * @since  1.8.12
945
	 * @access public
946
	 *
947
	 * @return int
948
	 */
949
	public function get_total_update_count() {
950
		$db_update_count     = $this->get_pending_db_update_count();
951
		$plugin_update_count = $this->get_total_plugin_update_count();
952
953
		return ( $db_update_count + $plugin_update_count );
954
	}
955
956
	/**
957
	 * Get total pending updates count
958
	 *
959
	 * @since  1.8.12
960
	 * @access public
961
	 *
962
	 * @return int
963
	 */
964
	public function get_pending_db_update_count() {
965
		return count( $this->get_updates( 'database', 'new' ) );
966
	}
967
968
	/**
969
	 * Get total updates count
970
	 *
971
	 * @since  1.8.18
972
	 * @access public
973
	 *
974
	 * @return int
975
	 */
976
	public function get_total_db_update_count() {
977
		return count( $this->get_updates( 'database', 'all' ) );
978
	}
979
980
	/**
981
	 * Get total new updates count
982
	 *
983
	 * @since  2.0
984
	 * @access public
985
	 *
986
	 * @return int
987
	 */
988
	public function get_total_new_db_update_count() {
989
		return $this->is_doing_updates() ?
990
			get_option( 'give_db_update_count' ) :
991
			$this->get_pending_db_update_count();
992
	}
993
994
	/**
995
	 * Get total new updates count
996
	 *
997
	 * @since  2.0
998
	 * @access public
999
	 *
1000
	 * @return int
1001
	 */
1002
	public function get_running_db_update() {
1003
		$current_update = get_option( 'give_doing_upgrade' );
1004
1005
		return $this->is_doing_updates() ?
1006
			$current_update['update'] :
1007
			1;
1008
	}
1009
1010
	/**
1011
	 * Get database update processing percentage.
1012
	 *
1013
	 * @since  2.0
1014
	 * @access public
1015
	 * @return float|int
1016
	 */
1017
	public function get_db_update_processing_percentage() {
1018
		// Bailout.
1019
		if ( ! $this->get_total_new_db_update_count() ) {
1020
			return 0;
1021
		}
1022
1023
		$resume_update            = get_option( 'give_doing_upgrade' );
1024
		$update_count_percentages = ( ( $this->get_running_db_update() - 1 ) / $this->get_total_new_db_update_count() ) * 100;
1025
		$update_percentage_share  = ( 1 / $this->get_total_new_db_update_count() ) * 100;
1026
		$upgrade_percentage       = ( ( $resume_update['percentage'] * $update_percentage_share ) / 100 );
1027
1028
		$final_percentage = $update_count_percentages + $upgrade_percentage;
1029
1030
		return $this->is_doing_updates() ?
1031
			( absint( $final_percentage ) ?
1032
				absint( $final_percentage ) :
1033
				round( $final_percentage, 2 )
1034
			) :
1035
			0;
1036
	}
1037
1038
1039
	/**
1040
	 * Get all update ids.
1041
	 *
1042
	 * @since 2.0.3
1043
	 *
1044
	 * @return array
1045
	 */
1046
	public function get_update_ids() {
1047
		$all_updates    = $this->get_updates( 'database', 'all' );
1048
		$all_update_ids = wp_list_pluck( $all_updates, 'id' );
1049
1050
		return $all_update_ids;
1051
	}
1052
}
1053
1054
Give_Updates::get_instance()->setup();
1055