PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 4.13.0
GiveWP – Donation Plugin and Fundraising Platform v4.13.0
4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / includes / admin / upgrades / class-give-updates.php
give / includes / admin / upgrades Last commit date
views 4 years ago class-give-updates.php 9 months ago upgrade-functions.php 9 months ago
class-give-updates.php
1175 lines
1 <?php
2
3 /**
4 * Class Give_Updates
5 *
6 * @since 1.8.12
7 */
8 class Give_Updates {
9
10 /**
11 * Instance.
12 *
13 * @since
14 * @access static
15 * @var
16 */
17 private static $instance;
18
19 /**
20 * Instance.
21 *
22 * @since
23 * @access public
24 * @var Give_Background_Updater
25 */
26 public static $background_updater;
27
28 /**
29 * Updates
30 *
31 * @since 1.8.12
32 * @access private
33 * @var array
34 */
35 private $updates = [];
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 = [
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'] = [ $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() {
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', [ $this, '__register_upgrade' ], 9999 );
148 add_action( 'give_set_upgrade_completed', [$this, 'flush_resume_updates'], 9999 );
149 add_action( 'wp_ajax_give_db_updates_info', [$this, 'give_db_updates_info'] );
150 add_action( 'wp_ajax_give_run_db_updates', [$this, 'give_start_updating'] );
151 add_action( 'admin_init', [$this, 'redirect_admin'] );
152 add_action( 'admin_init', [$this, 'pause_db_update'], - 1 );
153 add_action( 'admin_init', [$this, 'restart_db_update'], - 1 );
154 add_action( 'admin_notices', [$this, 'show_notice'] );
155 add_action( 'give_restart_db_upgrade', [$this, 'health_background_update'] );
156
157 if ( is_admin() ) {
158 add_action( 'admin_init', [$this, 'change_donations_label'], 9999 );
159 add_action( 'admin_menu', [$this, 'register_menu'], 55 );
160 }
161 }
162
163 /**
164 * Register plugin add-on updates.
165 *
166 * @since 4.9.0 rename function - PHP 8 compatibility
167 * @since 1.8.12
168 * @access public
169 */
170 public function register_plugin_addon_updates() {
171 $addons = give_get_plugins( [ 'only_premium_add_ons' => true ] );
172 $plugin_updates = get_plugin_updates();
173
174 foreach ( $addons as $key => $info ) {
175 if ( empty( $plugin_updates[ $key ] ) ) {
176 continue;
177 }
178
179 $this->updates['plugin'][] = array_merge( $info, (array) $plugin_updates[ $key ] );
180 }
181 }
182
183
184 /**
185 * Fire custom action hook to register updates
186 *
187 * @since 1.8.12
188 * @access public
189 */
190 public function __register_upgrade() {
191 if ( ! is_admin() ) {
192 return;
193 }
194
195 /**
196 * Fire the hook
197 *
198 * @since 1.8.12
199 */
200 do_action( 'give_register_updates', $this );
201 }
202
203 /**
204 * Rename `Donations` menu title if updates exists
205 *
206 * @since 4.9.0 rename function - PHP 8 compatibility
207 * @since 1.8.12
208 * @access public
209 */
210 function change_donations_label() {
211 global $menu;
212
213 // Bailout.
214 if ( empty( $menu ) || ! $this->get_total_update_count() ) {
215 return;
216 }
217
218 $is_update = ( $this->is_doing_updates() && ! self::$background_updater->is_paused_process() );
219
220 foreach ( $menu as $index => $menu_item ) {
221 if ( 'edit.php?post_type=give_forms' !== $menu_item[2] ) {
222 continue;
223 }
224
225 $menu[ $index ][0] = sprintf(
226 '%1$s <span class="update-plugins"><span class="plugin-count give-update-progress-count">%2$s%3$s</span></span>',
227 __( 'GiveWP', 'give' ),
228 $is_update ?
229 $this->get_db_update_processing_percentage() :
230 $this->get_total_update_count(),
231 $is_update ? '%' : ''
232 );
233
234 break;
235 }
236 }
237
238 /**
239 * Register updates menu
240 *
241 * @since 4.9.0 rename function - PHP 8 compatibility
242 * @since 1.8.12
243 * @access public
244 */
245 public function register_menu() {
246 // Load plugin updates.
247 $this->register_plugin_addon_updates();
248
249 // Bailout.
250 if ( ! $this->get_total_update_count() ) {
251 // Show complete update message if still on update setting page.
252 if ( isset( $_GET['page'] ) && 'give-updates' === $_GET['page'] ) {
253 // Upgrades
254 add_submenu_page(
255 'edit.php?post_type=give_forms',
256 esc_html__( 'GiveWP Updates Complete', 'give' ),
257 __( 'Updates', 'give' ),
258 'manage_give_settings',
259 'give-updates',
260 [ $this, 'render_complete_page' ]
261 );
262 }
263
264 return;
265 }
266
267 $is_update = ( $this->is_doing_updates() && ! self::$background_updater->is_paused_process() );
268
269 // Upgrades
270 add_submenu_page(
271 'edit.php?post_type=give_forms',
272 esc_html__( 'GiveWP Updates', 'give' ),
273 sprintf(
274 '%1$s <span class="update-plugins"%2$s><span class="plugin-count give-update-progress-count">%3$s%4$s</span></span>',
275 __( 'Updates', 'give' ),
276 isset( $_GET['give-pause-db-upgrades'] ) ? ' style="display:none;"' : '',
277 $is_update ?
278 $this->get_db_update_processing_percentage() :
279 $this->get_total_update_count(),
280 $is_update ? '%' : ''
281 ),
282 'manage_give_settings',
283 'give-updates',
284 [ $this, 'render_page' ]
285 );
286 }
287
288
289 /**
290 * Show update related notices
291 *
292 * @since 4.9.0 rename function - PHP 8 compatibility
293 * @since 2.0
294 * @access public
295 */
296 public function redirect_admin() {
297 // Show db upgrade completed notice.
298 if (
299 ! wp_doing_ajax() &&
300 current_user_can( 'manage_give_settings' ) &&
301 get_option( 'give_show_db_upgrade_complete_notice' ) &&
302 ! isset( $_GET['give-db-update-completed'] )
303 ) {
304 delete_option( 'give_show_db_upgrade_complete_notice' );
305
306 wp_redirect( admin_url( 'edit.php?post_type=give_forms&page=give-updates&give-db-update-completed=give_db_upgrade_completed' ) );
307 exit();
308 }
309 }
310
311
312 /**
313 * Pause db upgrade
314 *
315 * @since 4.9.0 rename function - PHP 8 compatibility
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 ) {
324 // Bailout.
325 if (
326 ! $force &&
327 (
328 wp_doing_ajax() ||
329 ! isset( $_GET['page'] ) ||
330 'give-updates' !== $_GET['page'] ||
331 ! isset( $_GET['give-pause-db-upgrades'] ) ||
332 self::$background_updater->is_paused_process()
333 )
334
335 ) {
336 return false;
337 }
338
339 delete_option( 'give_upgrade_error' );
340
341 $this->health_background_update( $this );
342 $batch = self::$background_updater->get_all_batch();
343
344 // Bailout: if batch is empty
345 if ( empty( $batch->data ) ) {
346 return false;
347 }
348
349 // Remove cache.
350 Give_Background_Updater::flush_cache();
351
352 // Do not stop background process immediately if task running.
353 // @see Give_Background_Updater::lock_process
354 if ( ! $force && self::$background_updater->is_process_running() ) {
355 update_option( 'give_pause_upgrade', 1, false );
356
357 return true;
358 }
359
360 update_option( 'give_paused_batches', $batch, false );
361 delete_option( $batch->key );
362 delete_site_transient( self::$background_updater->get_identifier() . '_process_lock' );
363 wp_clear_scheduled_hook( self::$background_updater->get_cron_identifier() );
364
365 Give()->logs->add( 'Update Pause', print_r( $batch, true ), 0, 'update' );
366
367 /**
368 * Fire action when pause db updates
369 *
370 * @since 2.0.1
371 */
372 do_action( 'give_pause_db_upgrade', $this );
373
374 return true;
375 }
376
377 /**
378 * Restart db upgrade
379 *
380 * @since 4.9.0 rename function - PHP 8 compatibility
381 * @since 2.0.1
382 * @access public
383 *
384 * @return bool
385 */
386 public function restart_db_update() {
387 // Bailout.
388 if (
389 wp_doing_ajax() ||
390 ! isset( $_GET['page'] ) ||
391 'give-updates' !== $_GET['page'] ||
392 ! isset( $_GET['give-restart-db-upgrades'] ) ||
393 ! self::$background_updater->is_paused_process()
394 ) {
395 return false;
396 }
397
398 Give_Background_Updater::flush_cache();
399 $batch = get_option( 'give_paused_batches' );
400
401 if ( ! empty( $batch ) ) {
402 wp_cache_delete( $batch->key, 'options' );
403 update_option( $batch->key, $batch->data, false );
404
405 delete_option( 'give_paused_batches' );
406
407 Give()->logs->add( 'Update Restart', print_r( $batch, true ), 0, 'update' );
408
409 /** Fire action when restart db updates
410 *
411 * @since 2.0.1
412 */
413 do_action( 'give_restart_db_upgrade', $this );
414
415 self::$background_updater->dispatch();
416 }
417
418 return true;
419 }
420
421 /**
422 * Health check for updates.
423 *
424 * @since 4.9.0 rename function - PHP 8 compatibility
425 * @since 2.0
426 * @access public
427 *
428 * @param Give_Updates $give_updates
429 */
430 public function health_background_update( $give_updates ) {
431 if ( ! $this->is_doing_updates() ) {
432 return;
433 }
434
435 Give_Background_Updater::flush_cache();
436
437 /* @var stdClass $batch */
438 $batch = self::$background_updater->get_all_batch();
439 $old_batch_update_ids = is_array( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : [];
440 $all_updates = $give_updates->get_updates( 'database', 'all' );
441 $all_update_ids = wp_list_pluck( $all_updates, 'id' );
442 $all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : [];
443 $log_data = '';
444 $doing_upgrade_args = get_option( 'give_doing_upgrade' );
445
446 if ( ! empty( $doing_upgrade_args ) ) {
447 $log_data .= 'Doing update:' . "\n";
448 $log_data .= print_r( $doing_upgrade_args, true ) . "\n";
449 }
450
451 /**
452 * Add remove upgrade from batch
453 */
454 if ( ! empty( $batch->data ) ) {
455
456 foreach ( $batch->data as $index => $update ) {
457 $log_data = print_r( $update, true ) . "\n";
458
459 if ( ! is_callable( $update['callback'] ) ) {
460 $log_data .= 'Removing missing callback update: ' . "{$update['id']}\n";
461 unset( $batch->data[ $index ] );
462 } elseif ( give_has_upgrade_completed( $update['id'] ) ) {
463 $log_data .= 'Removing already completed update: ' . "{$update['id']}\n";
464 unset( $batch->data[ $index ] );
465 }
466
467 if ( ! empty( $update['depend'] ) ) {
468
469 foreach ( $update['depend'] as $depend ) {
470 if ( give_has_upgrade_completed( $depend ) ) {
471 $log_data .= 'Completed update: ' . "{$depend}\n";
472 continue;
473 }
474
475 if ( in_array( $depend, $all_update_ids ) && ! in_array( $depend, $all_batch_update_ids ) ) {
476 $log_data .= 'Adding missing update: ' . "{$depend}\n";
477 array_unshift( $batch->data, $all_updates[ array_search( $depend, $all_update_ids ) ] );
478 }
479 }
480 }
481 }
482 }
483
484 /**
485 * Add new upgrade to batch
486 */
487 if ( $new_updates = $this->get_updates( 'database', 'new' ) ) {
488 $all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : [];
489
490 foreach ( $new_updates as $index => $new_update ) {
491 if ( give_has_upgrade_completed( $new_update['id'] ) || in_array( $new_update['id'], $all_batch_update_ids ) ) {
492 unset( $new_updates[ $index ] );
493 }
494 }
495
496 if ( ! empty( $new_updates ) ) {
497 $log_data .= 'Adding new update: ' . "\n";
498 $log_data .= print_r( $new_updates, true ) . "\n";
499
500 $batch->data = array_merge( (array) $batch->data, $new_updates );
501 update_option( 'give_db_update_count', ( absint( get_option( 'give_db_update_count' ) ) + count( $new_updates ) ), false );
502 }
503 }
504
505 /**
506 * Fix batch
507 */
508 if ( empty( $batch->data ) ) {
509 // Complete batch if do not have any data to process.
510 self::$background_updater->delete( $batch->key );
511
512 if ( self::$background_updater->has_queue() ) {
513 $this->health_background_update( $this );
514 } else {
515 delete_site_transient( self::$background_updater->get_identifier() . '_process_lock' );
516 wp_clear_scheduled_hook( self::$background_updater->get_cron_identifier() );
517
518 self::$background_updater->complete();
519 }
520 } elseif ( array_diff( wp_list_pluck( $batch->data, 'id' ), $old_batch_update_ids ) ) {
521
522 $log_data .= 'Updating batch' . "\n";
523 $log_data .= print_r( $batch, true );
524
525 if ( ! empty( $batch->key ) ) {
526 wp_cache_delete( $batch->key, 'options' );
527 update_option( $batch->key, $batch->data, false );
528 } else {
529
530 foreach ( $batch->data as $data ) {
531 self::$background_updater->push_to_queue( $data );
532 }
533
534 self::$background_updater->save();
535 }
536 }
537
538 /**
539 * Fix give_doing_upgrade option
540 */
541 if ( $fresh_new_db_count = $this->get_total_new_db_update_count( true ) ) {
542 update_option( 'give_db_update_count', $fresh_new_db_count, false );
543 }
544
545 $doing_upgrade_args['update'] = 1;
546 $doing_upgrade_args['heading'] = sprintf( 'Update %s of %s', 1, $fresh_new_db_count );
547 $doing_upgrade_args['total_percentage'] = $this->get_db_update_processing_percentage( true );
548
549 // Remove already completed update from info.
550 if (
551 empty( $doing_upgrade_args['update_info'] )
552 || give_has_upgrade_completed( $doing_upgrade_args['update_info']['id'] )
553 ) {
554 $doing_upgrade_args['update_info'] = current( array_values( $batch->data ) );
555 $doing_upgrade_args['step'] = 1;
556 }
557
558 // Check if dependency completed or not.
559 if ( isset( $doing_upgrade_args['update_info']['depend'] ) ) {
560 foreach ( $doing_upgrade_args['update_info']['depend'] as $depend ) {
561 if ( give_has_upgrade_completed( $depend ) ) {
562 continue;
563 }
564
565 $doing_upgrade_args['update_info'] = $all_updates[ array_search( $depend, $all_update_ids ) ];
566 $doing_upgrade_args['step'] = 1;
567 $doing_upgrade_args['percentage'] = 0;
568 $doing_upgrade_args['total_percentage'] = 0;
569
570 break;
571 }
572 }
573
574 if ( ! empty( $doing_upgrade_args['update_info'] ) ) {
575 update_option( 'give_doing_upgrade', $doing_upgrade_args, false );
576
577 $log_data .= 'Updated doing update:' . "\n";
578 $log_data .= print_r( $doing_upgrade_args, true ) . "\n";
579 }
580
581 Give()->logs->add( 'Update Health Check', $log_data, 0, 'update' );
582 }
583
584
585 /**
586 * Show update related notices
587 *
588 * @since 4.9.0 rename function - PHP 8 compatibility
589 * @since 2.0
590 * @access public
591 */
592 public function show_notice() {
593 $current_screen = get_current_screen();
594 $hide_on_pages = [
595 'give_forms_page_give-updates',
596 'update-core',
597 'give_forms_page_give-addons',
598 ];
599
600 // Bailout.
601 if ( ! current_user_can( 'manage_give_settings' ) ) {
602 return;
603 }
604
605 // Run DB updates.
606 if ( ! empty( $_GET['give-run-db-update'] ) ) {
607 $this->run_db_update();
608 }
609
610 // Bailout.
611 if ( in_array( $current_screen->base, $hide_on_pages ) ) {
612 return;
613 }
614
615 // Show notice if upgrade paused.
616 if ( self::$background_updater->is_paused_process() ) {
617 ob_start();
618
619 $upgrade_error = get_option( 'give_upgrade_error' );
620 if ( ! $upgrade_error ) : ?>
621 <strong><?php _e( 'Database Update', 'give' ); ?></strong>
622 &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' ); ?>
623 <br>
624 <br>
625 <a href="<?php echo esc_url( add_query_arg( [ 'give-restart-db-upgrades' => 1 ], admin_url( 'edit.php?post_type=give_forms&page=give-updates' ) ) ); ?>" class="button button-primary give-restart-updater-btn">
626 <?php _e( 'Restart the updater', 'give' ); ?>
627 </a>
628 <?php else : ?>
629 <strong><?php _e( 'Database Update', 'give' ); ?></strong>
630 &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' ); ?>
631 <a href="<?php echo esc_url( 'http://docs.givewp.com/troubleshooting-db-updates' ); ?>" target="_blank"><?php _e( 'Read More', 'give' ); ?> &raquo;</a>
632 <?php
633 endif;
634 $desc_html = ob_get_clean();
635
636 Give()->notices->register_notice(
637 [
638 'id' => 'give_upgrade_db',
639 'type' => 'error',
640 'dismissible' => false,
641 'description' => $desc_html,
642 ]
643 );
644 }
645
646 // Bailout if doing upgrades.
647 if ( $this->is_doing_updates() ) {
648 return;
649 }
650
651 // Show db upgrade completed notice.
652 if ( ! empty( $_GET['give-db-update-completed'] ) ) {
653 Give()->notices->register_notice(
654 [
655 'id' => 'give_db_upgrade_completed',
656 'type' => 'updated',
657 'description' => __( 'GiveWP database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
658 'show' => true,
659 ]
660 );
661
662 // Start update.
663 } elseif ( ! empty( $_GET['give-run-db-update'] ) ) {
664 $this->run_db_update();
665
666 // Show run the update notice.
667 } elseif ( $this->get_total_new_db_update_count() ) {
668 ob_start();
669 ?>
670 <p>
671 <strong><?php _e( 'Database Update', 'give' ); ?></strong>
672 &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' ); ?>
673 </p>
674 <p class="submit">
675 <a href="<?php echo esc_url( add_query_arg( [ 'give-run-db-update' => 1 ], admin_url( 'edit.php?post_type=give_forms&page=give-updates' ) ) ); ?>" class="button button-primary give-run-update-now">
676 <?php _e( 'Run the updater', 'give' ); ?>
677 </a>
678 </p>
679 <?php
680 $desc_html = ob_get_clean();
681
682 Give()->notices->register_notice(
683 [
684 'id' => 'give_upgrade_db',
685 'type' => 'updated',
686 'dismissible' => false,
687 'description' => $desc_html,
688 ]
689 );
690 }
691 }
692
693 /**
694 * Render Give Updates Completed page
695 *
696 * @since 1.8.12
697 * @access public
698 */
699 public function render_complete_page() {
700 include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades-complete.php';
701 }
702
703 /**
704 * Render Give Updates page
705 *
706 * @since 1.8.12
707 * @access public
708 */
709 public function render_page() {
710 include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades.php';
711 }
712
713 /**
714 * Run database upgrades
715 *
716 * @since 2.0
717 * @access private
718 */
719 private function run_db_update() {
720 // Bailout.
721 if ( $this->is_doing_updates() || ! $this->get_total_new_db_update_count() ) {
722 return;
723 }
724
725 $updates = $this->get_updates( 'database', 'new' );
726
727 foreach ( $updates as $update ) {
728 self::$background_updater->push_to_queue( $update );
729 }
730
731 add_option( 'give_db_update_count', count( $updates ), '', false );
732
733 add_option(
734 'give_doing_upgrade',
735 [
736 'update_info' => $updates[0],
737 'step' => 1,
738 'update' => 1,
739 'heading' => sprintf( 'Update %s of %s', 1, count( $updates ) ),
740 'percentage' => 0,
741 'total_percentage' => 0,
742 ],
743 '',
744 false
745 );
746
747 self::$background_updater->save()->dispatch();
748 }
749
750
751 /**
752 * Delete resume updates
753 *
754 * @since 4.9.0 rename function - PHP 8 compatibility
755 * @since 1.8.12
756 * @access public
757 */
758 public function flush_resume_updates() {
759 $this->step = $this->percentage = 0;
760
761 $this->update = ( $this->get_total_db_update_count() > $this->update ) ?
762 ( $this->update + 1 ) :
763 $this->update;
764 }
765
766
767 /**
768 * Initialize updates
769 *
770 * @since 4.9.0 rename function - PHP 8 compatibility
771 * @since 2.0
772 * @access public
773 *
774 * @return void
775 */
776 public function give_start_updating() {
777 // Check permission.
778 if (
779 ! current_user_can( 'manage_give_settings' ) ||
780 $this->is_doing_updates()
781 ) {
782 // Run update via ajax
783 self::$background_updater->dispatch();
784
785 wp_send_json_error();
786 }
787
788 // @todo: validate nonce
789 // @todo: set http method to post
790 if ( empty( $_POST['run_db_update'] ) ) {
791 wp_send_json_error();
792 }
793
794 $this->run_db_update();
795
796 wp_send_json_success();
797 }
798
799
800 /**
801 * This function handle ajax query for dn update status.
802 *
803 * @since 4.9.0 rename function - PHP 8 compatibility
804 * @since 2.0
805 * @access public
806 *
807 * @return string
808 */
809 public function give_db_updates_info() {
810 // Check permission.
811 if ( ! current_user_can( 'manage_give_settings' ) ) {
812 give_die();
813 }
814
815 $update_info = get_option( 'give_doing_upgrade' );
816 $response_type = '';
817
818 if ( self::$background_updater->is_paused_process() ) {
819 $update_info = [
820 'message' => __( 'The updates have been paused.', 'give' ),
821 'heading' => '',
822 'percentage' => 0,
823 ];
824
825 if ( get_option( 'give_upgrade_error' ) ) {
826 $update_info['message'] = __( 'An unexpected issue occurred during the database update which caused it to stop automatically. Please contact support for assistance.', 'give' );
827 }
828
829 $response_type = 'error';
830
831 } elseif ( empty( $update_info ) || ! $this->get_total_new_db_update_count( true ) ) {
832 $update_info = [
833 'message' => __( 'GiveWP database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
834 'heading' => __( 'Updates Completed.', 'give' ),
835 'percentage' => 0,
836 ];
837 $response_type = 'success';
838
839 delete_option( 'give_show_db_upgrade_complete_notice' );
840 }
841
842 $this->send_ajax_response( $update_info, $response_type );
843 }
844
845 /**
846 * Send ajax response
847 *
848 * @since 1.8.12
849 * @access public
850 *
851 * @param $data
852 * @param string $type
853 */
854 public function send_ajax_response( $data, $type = '' ) {
855 $default = [
856 'message' => '',
857 'heading' => '',
858 'percentage' => 0,
859 'step' => 0,
860 'update' => 0,
861 ];
862
863 // Set data.
864 $data = wp_parse_args( $data, $default );
865
866 // Enable cache.
867 Give_Cache::enable();
868
869 switch ( $type ) {
870 case 'success':
871 wp_send_json_success( $data );
872 break;
873
874 case 'error':
875 wp_send_json_error( $data );
876 break;
877
878 default:
879 wp_send_json(
880 [
881 'data' => $data,
882 ]
883 );
884 break;
885 }
886 }
887
888 /**
889 * Set current update percentage.
890 *
891 * @since 1.8.12
892 * @access public
893 *
894 * @param $total
895 * @param $current_total
896 */
897 public function set_percentage( $total, $current_total ) {
898 // Set percentage.
899 $this->percentage = $total ? ( ( $current_total ) / $total ) * 100 : 0;
900
901 // Verify percentage.
902 $this->percentage = ( 100 < $this->percentage ) ? 100 : $this->percentage;
903 }
904
905 /**
906 * Check if parent update completed or not.
907 *
908 * @since 2.0
909 * @access private
910 *
911 * @param array $update
912 *
913 * @return bool|null
914 */
915 public function is_parent_updates_completed( $update ) {
916 // Bailout.
917 if ( empty( $update['depend'] ) ) {
918 return true;
919 }
920
921 // Check if dependency is valid or not.
922 if ( ! $this->has_valid_dependency( $update ) ) {
923 return null;
924 }
925
926 $is_dependency_completed = true;
927
928 foreach ( $update['depend'] as $depend ) {
929
930 if ( ! give_has_upgrade_completed( $depend ) ) {
931 $is_dependency_completed = false;
932 break;
933 }
934 }
935
936 return $is_dependency_completed;
937 }
938
939 /**
940 * Flag to check if DB updates running or not.
941 *
942 * @since 2.0
943 * @access public
944 * @return bool
945 */
946 public function is_doing_updates() {
947 return (bool) Give_Cache_Setting::get_option( 'give_doing_upgrade' );
948 }
949
950
951 /**
952 * Check if update has valid dependency or not.
953 *
954 * @since 2.0
955 * @access public
956 *
957 * @param $update
958 *
959 * @return bool
960 */
961 public function has_valid_dependency( $update ) {
962 $is_valid_dependency = true;
963 // $update_ids = wp_list_pluck( $this->get_updates( 'database', 'all' ), 'id' );
964 //
965 // foreach ( $update['depend'] as $depend ) {
966 // Check if dependency is valid or not.
967 // if ( ! in_array( $depend, $update_ids ) ) {
968 // $is_valid_dependency = false;
969 // break;
970 // }
971 // }
972
973 return $is_valid_dependency;
974 }
975
976 /**
977 * Get updates.
978 *
979 * @since 1.8.12
980 * @access public
981 *
982 * @param string $update_type Tye of update.
983 * @param string $status Tye of update.
984 *
985 * @return array
986 */
987 public function get_updates( $update_type = '', $status = 'all' ) {
988 // return all updates.
989 if ( empty( $update_type ) ) {
990 return $this->updates;
991 }
992
993 // Get specific update.
994 $updates = ! empty( $this->updates[ $update_type ] ) ? $this->updates[ $update_type ] : [];
995
996 // Bailout.
997 if ( empty( $updates ) ) {
998 return $updates;
999 }
1000
1001 switch ( $status ) {
1002 case 'new':
1003 // Remove already completed updates.
1004 wp_cache_delete( 'give_completed_upgrades', 'options' );
1005 $completed_updates = give_get_completed_upgrades();
1006
1007 if ( ! empty( $completed_updates ) ) {
1008 foreach ( $updates as $index => $update ) {
1009 if ( in_array( $update['id'], $completed_updates ) ) {
1010 unset( $updates[ $index ] );
1011 }
1012 }
1013 $updates = array_values( $updates );
1014 }
1015
1016 break;
1017 }
1018
1019 return $updates;
1020 }
1021
1022 /**
1023 * Get addon update count.
1024 *
1025 * @since 1.8.12
1026 * @access public
1027 * @return int
1028 */
1029 public function get_total_plugin_update_count() {
1030 return count( $this->get_updates( 'plugin' ) );
1031 }
1032
1033 /**
1034 * Get total update count
1035 *
1036 * @since 1.8.12
1037 * @access public
1038 *
1039 * @return int
1040 */
1041 public function get_total_update_count() {
1042 $db_update_count = $this->get_pending_db_update_count();
1043 $plugin_update_count = $this->get_total_plugin_update_count();
1044
1045 return ( $db_update_count + $plugin_update_count );
1046 }
1047
1048 /**
1049 * Get total pending updates count
1050 *
1051 * @since 1.8.12
1052 * @access public
1053 *
1054 * @return int
1055 */
1056 public function get_pending_db_update_count() {
1057 return count( $this->get_updates( 'database', 'new' ) );
1058 }
1059
1060 /**
1061 * Get total updates count
1062 *
1063 * @since 1.8.18
1064 * @access public
1065 *
1066 * @return int
1067 */
1068 public function get_total_db_update_count() {
1069 return count( $this->get_updates( 'database', 'all' ) );
1070 }
1071
1072 /**
1073 * Get total new updates count
1074 *
1075 * @since 2.0
1076 * @access public
1077 *
1078 * @param bool $refresh
1079 *
1080 * @return int
1081 */
1082 public function get_total_new_db_update_count( $refresh = false ) {
1083 $update_count = $this->is_doing_updates() && ! $refresh ?
1084 get_option( 'give_db_update_count' ) :
1085 $this->get_pending_db_update_count();
1086
1087 return $update_count;
1088 }
1089
1090 /**
1091 * Get total new updates count
1092 *
1093 * @since 2.0
1094 * @access public
1095 *
1096 * @param bool $refresh
1097 *
1098 * @return int
1099 */
1100 public function get_running_db_update( $refresh = false ) {
1101 $current_update = 1;
1102
1103 if ( $this->is_doing_updates() && ! $refresh ) {
1104 $current_update = get_option( 'give_doing_upgrade' );
1105 $current_update = $current_update['update'];
1106 }
1107
1108 return $current_update;
1109 }
1110
1111 /**
1112 * Get database update processing percentage.
1113 *
1114 * @since 2.0
1115 * @access public
1116 *
1117 * @param bool $refresh
1118 *
1119 * @return float|int
1120 */
1121 public function get_db_update_processing_percentage( $refresh = false ) {
1122 // Bailout.
1123 if ( ! $this->get_total_new_db_update_count( $refresh ) ) {
1124 return 0;
1125 }
1126
1127 $resume_update = get_option( 'give_doing_upgrade' );
1128 $update_count_percentages = ( ( $this->get_running_db_update( $refresh ) - 1 ) / $this->get_total_new_db_update_count( $refresh ) ) * 100;
1129 $update_percentage_share = ( 1 / $this->get_total_new_db_update_count() ) * 100;
1130 $upgrade_percentage = ( ( $resume_update['percentage'] * $update_percentage_share ) / 100 );
1131
1132 $final_percentage = $update_count_percentages + $upgrade_percentage;
1133
1134 return $this->is_doing_updates() ?
1135 ( absint( $final_percentage ) ?
1136 absint( $final_percentage ) :
1137 round( $final_percentage, 2 )
1138 ) :
1139 0;
1140 }
1141
1142
1143 /**
1144 * Get all update ids.
1145 *
1146 * @since 2.0.3
1147 *
1148 * @return array
1149 */
1150 public function get_update_ids() {
1151 $all_updates = $this->get_updates( 'database', 'all' );
1152 $all_update_ids = wp_list_pluck( $all_updates, 'id' );
1153
1154 return $all_update_ids;
1155 }
1156
1157 /**
1158 * Get offset count
1159 *
1160 * @since 2.0.5
1161 * @access public
1162 *
1163 * @param int $process_item_count
1164 *
1165 * @return float|int
1166 */
1167 public function get_offset( $process_item_count ) {
1168 return ( 1 === $this->step ) ?
1169 0 :
1170 ( $this->step - 1 ) * $process_item_count;
1171 }
1172 }
1173
1174 Give_Updates::get_instance()->setup();
1175