PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / trunk
GiveWP – Donation Plugin and Fundraising Platform vtrunk
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 5 months ago upgrade-functions.php 5 months ago
class-give-updates.php
1178 lines
1 <?php
2
3 use Give\Framework\Permissions\Facades\UserPermissions;
4
5 /**
6 * Class Give_Updates
7 *
8 * @since 1.8.12
9 */
10 class Give_Updates {
11
12 /**
13 * Instance.
14 *
15 * @since
16 * @access static
17 * @var
18 */
19 private static $instance;
20
21 /**
22 * Instance.
23 *
24 * @since
25 * @access public
26 * @var Give_Background_Updater
27 */
28 public static $background_updater;
29
30 /**
31 * Updates
32 *
33 * @since 1.8.12
34 * @access private
35 * @var array
36 */
37 private $updates = [];
38
39 /**
40 * Current update percentage number
41 *
42 * @since 1.8.12
43 * @access private
44 * @var array
45 */
46 public $percentage = 0;
47
48 /**
49 * Current update step number
50 *
51 * @since 1.8.12
52 * @access private
53 * @var array
54 */
55 public $step = 1;
56
57 /**
58 * Current update number
59 *
60 * @since 1.8.12
61 * @access private
62 * @var array
63 */
64 public $update = 1;
65
66 /**
67 * Singleton pattern.
68 *
69 * @since 1.8.12
70 * @access private
71 *
72 * @param Give_Updates .
73 */
74 private function __construct() {
75 }
76
77 /**
78 * Register updates
79 *
80 * @since 1.8.12
81 * @access public
82 *
83 * @param array $args
84 */
85 public function register( $args ) {
86 $args_default = [
87 'id' => '',
88 'version' => '',
89 'callback' => '',
90 ];
91
92 $args = wp_parse_args( $args, $args_default );
93
94 // You can only register database upgrade.
95 $args['type'] = 'database';
96
97 // Bailout.
98 if (
99 empty( $args['id'] ) ||
100 empty( $args['version'] ) ||
101 empty( $args['callback'] ) ||
102 ! is_callable( $args['callback'] )
103 ) {
104 return;
105 }
106
107 // Change depend param to array.
108 if ( isset( $args['depend'] ) && is_string( $args['depend'] ) ) {
109 $args['depend'] = [ $args['depend'] ];
110 }
111
112 $this->updates[ $args['type'] ][] = $args;
113 }
114
115 /**
116 * Get instance.
117 *
118 * @since
119 * @access static
120 * @return static
121 */
122 static function get_instance() {
123 if ( is_null( self::$instance ) ) {
124 self::$instance = new self();
125 }
126
127 return self::$instance;
128 }
129
130 /**
131 *
132 * Setup hook
133 *
134 * @since 1.8.12
135 * @access public
136 */
137 public function setup() {
138 /**
139 * Load file
140 */
141 require_once GIVE_PLUGIN_DIR . 'includes/class-give-background-updater.php';
142 require_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/upgrade-functions.php';
143
144 self::$background_updater = new Give_Background_Updater();
145
146 /**
147 * Setup hooks.
148 */
149 add_action( 'init', [ $this, '__register_upgrade' ], 9999 );
150 add_action( 'give_set_upgrade_completed', [$this, 'flush_resume_updates'], 9999 );
151 add_action( 'wp_ajax_give_db_updates_info', [$this, 'give_db_updates_info'] );
152 add_action( 'wp_ajax_give_run_db_updates', [$this, 'give_start_updating'] );
153 add_action( 'admin_init', [$this, 'redirect_admin'] );
154 add_action( 'admin_init', [$this, 'pause_db_update'], - 1 );
155 add_action( 'admin_init', [$this, 'restart_db_update'], - 1 );
156 add_action( 'admin_notices', [$this, 'show_notice'] );
157 add_action( 'give_restart_db_upgrade', [$this, 'health_background_update'] );
158
159 if ( is_admin() ) {
160 add_action( 'admin_init', [$this, 'change_donations_label'], 9999 );
161 add_action( 'admin_menu', [$this, 'register_menu'], 55 );
162 }
163 }
164
165 /**
166 * Register plugin add-on updates.
167 *
168 * @since 4.9.0 rename function - PHP 8 compatibility
169 * @since 1.8.12
170 * @access public
171 */
172 public function register_plugin_addon_updates() {
173 $addons = give_get_plugins( [ 'only_premium_add_ons' => true ] );
174 $plugin_updates = get_plugin_updates();
175
176 foreach ( $addons as $key => $info ) {
177 if ( empty( $plugin_updates[ $key ] ) ) {
178 continue;
179 }
180
181 $this->updates['plugin'][] = array_merge( $info, (array) $plugin_updates[ $key ] );
182 }
183 }
184
185
186 /**
187 * Fire custom action hook to register updates
188 *
189 * @since 1.8.12
190 * @access public
191 */
192 public function __register_upgrade() {
193 if ( ! is_admin() ) {
194 return;
195 }
196
197 /**
198 * Fire the hook
199 *
200 * @since 1.8.12
201 */
202 do_action( 'give_register_updates', $this );
203 }
204
205 /**
206 * Rename `Donations` menu title if updates exists
207 *
208 * @since 4.9.0 rename function - PHP 8 compatibility
209 * @since 1.8.12
210 * @access public
211 */
212 function change_donations_label() {
213 global $menu;
214
215 // Bailout.
216 if ( empty( $menu ) || ! $this->get_total_update_count() ) {
217 return;
218 }
219
220 $is_update = ( $this->is_doing_updates() && ! self::$background_updater->is_paused_process() );
221
222 foreach ( $menu as $index => $menu_item ) {
223 if ( 'edit.php?post_type=give_forms' !== $menu_item[2] ) {
224 continue;
225 }
226
227 $menu[ $index ][0] = sprintf(
228 '%1$s <span class="update-plugins"><span class="plugin-count give-update-progress-count">%2$s%3$s</span></span>',
229 __( 'GiveWP', 'give' ),
230 $is_update ?
231 $this->get_db_update_processing_percentage() :
232 $this->get_total_update_count(),
233 $is_update ? '%' : ''
234 );
235
236 break;
237 }
238 }
239
240 /**
241 * Register updates menu
242 *
243 * @since 4.14.0 update permission capability to use facade
244 * @since 4.9.0 rename function - PHP 8 compatibility
245 * @since 1.8.12
246 * @access public
247 */
248 public function register_menu() {
249 // Load plugin updates.
250 $this->register_plugin_addon_updates();
251
252 // Bailout.
253 if ( ! $this->get_total_update_count() ) {
254 // Show complete update message if still on update setting page.
255 if ( isset( $_GET['page'] ) && 'give-updates' === $_GET['page'] ) {
256 // Upgrades
257 add_submenu_page(
258 'edit.php?post_type=give_forms',
259 esc_html__( 'GiveWP Updates Complete', 'give' ),
260 __( 'Updates', 'give' ),
261 'manage_give_settings',
262 'give-updates',
263 [ $this, 'render_complete_page' ]
264 );
265 }
266
267 return;
268 }
269
270 $is_update = ( $this->is_doing_updates() && ! self::$background_updater->is_paused_process() );
271
272 // Upgrades
273 add_submenu_page(
274 'edit.php?post_type=give_forms',
275 esc_html__( 'GiveWP Updates', 'give' ),
276 sprintf(
277 '%1$s <span class="update-plugins"%2$s><span class="plugin-count give-update-progress-count">%3$s%4$s</span></span>',
278 __( 'Updates', 'give' ),
279 isset( $_GET['give-pause-db-upgrades'] ) ? ' style="display:none;"' : '',
280 $is_update ?
281 $this->get_db_update_processing_percentage() :
282 $this->get_total_update_count(),
283 $is_update ? '%' : ''
284 ),
285 UserPermissions::settings()->manageCap(),
286 'give-updates',
287 [ $this, 'render_page' ]
288 );
289 }
290
291
292 /**
293 * Show update related notices
294 *
295 * @since 4.9.0 rename function - PHP 8 compatibility
296 * @since 2.0
297 * @access public
298 */
299 public function redirect_admin() {
300 // Show db upgrade completed notice.
301 if (
302 ! wp_doing_ajax() &&
303 current_user_can( 'manage_give_settings' ) &&
304 get_option( 'give_show_db_upgrade_complete_notice' ) &&
305 ! isset( $_GET['give-db-update-completed'] )
306 ) {
307 delete_option( 'give_show_db_upgrade_complete_notice' );
308
309 wp_redirect( admin_url( 'edit.php?post_type=give_forms&page=give-updates&give-db-update-completed=give_db_upgrade_completed' ) );
310 exit();
311 }
312 }
313
314
315 /**
316 * Pause db upgrade
317 *
318 * @since 4.9.0 rename function - PHP 8 compatibility
319 * @since 2.0.1
320 * @access public
321 *
322 * @param bool $force
323 *
324 * @return bool
325 */
326 public function pause_db_update( $force = false ) {
327 // Bailout.
328 if (
329 ! $force &&
330 (
331 wp_doing_ajax() ||
332 ! isset( $_GET['page'] ) ||
333 'give-updates' !== $_GET['page'] ||
334 ! isset( $_GET['give-pause-db-upgrades'] ) ||
335 self::$background_updater->is_paused_process()
336 )
337
338 ) {
339 return false;
340 }
341
342 delete_option( 'give_upgrade_error' );
343
344 $this->health_background_update( $this );
345 $batch = self::$background_updater->get_all_batch();
346
347 // Bailout: if batch is empty
348 if ( empty( $batch->data ) ) {
349 return false;
350 }
351
352 // Remove cache.
353 Give_Background_Updater::flush_cache();
354
355 // Do not stop background process immediately if task running.
356 // @see Give_Background_Updater::lock_process
357 if ( ! $force && self::$background_updater->is_process_running() ) {
358 update_option( 'give_pause_upgrade', 1, false );
359
360 return true;
361 }
362
363 update_option( 'give_paused_batches', $batch, false );
364 delete_option( $batch->key );
365 delete_site_transient( self::$background_updater->get_identifier() . '_process_lock' );
366 wp_clear_scheduled_hook( self::$background_updater->get_cron_identifier() );
367
368 Give()->logs->add( 'Update Pause', print_r( $batch, true ), 0, 'update' );
369
370 /**
371 * Fire action when pause db updates
372 *
373 * @since 2.0.1
374 */
375 do_action( 'give_pause_db_upgrade', $this );
376
377 return true;
378 }
379
380 /**
381 * Restart db upgrade
382 *
383 * @since 4.9.0 rename function - PHP 8 compatibility
384 * @since 2.0.1
385 * @access public
386 *
387 * @return bool
388 */
389 public function restart_db_update() {
390 // Bailout.
391 if (
392 wp_doing_ajax() ||
393 ! isset( $_GET['page'] ) ||
394 'give-updates' !== $_GET['page'] ||
395 ! isset( $_GET['give-restart-db-upgrades'] ) ||
396 ! self::$background_updater->is_paused_process()
397 ) {
398 return false;
399 }
400
401 Give_Background_Updater::flush_cache();
402 $batch = get_option( 'give_paused_batches' );
403
404 if ( ! empty( $batch ) ) {
405 wp_cache_delete( $batch->key, 'options' );
406 update_option( $batch->key, $batch->data, false );
407
408 delete_option( 'give_paused_batches' );
409
410 Give()->logs->add( 'Update Restart', print_r( $batch, true ), 0, 'update' );
411
412 /** Fire action when restart db updates
413 *
414 * @since 2.0.1
415 */
416 do_action( 'give_restart_db_upgrade', $this );
417
418 self::$background_updater->dispatch();
419 }
420
421 return true;
422 }
423
424 /**
425 * Health check for updates.
426 *
427 * @since 4.9.0 rename function - PHP 8 compatibility
428 * @since 2.0
429 * @access public
430 *
431 * @param Give_Updates $give_updates
432 */
433 public function health_background_update( $give_updates ) {
434 if ( ! $this->is_doing_updates() ) {
435 return;
436 }
437
438 Give_Background_Updater::flush_cache();
439
440 /* @var stdClass $batch */
441 $batch = self::$background_updater->get_all_batch();
442 $old_batch_update_ids = is_array( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : [];
443 $all_updates = $give_updates->get_updates( 'database', 'all' );
444 $all_update_ids = wp_list_pluck( $all_updates, 'id' );
445 $all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : [];
446 $log_data = '';
447 $doing_upgrade_args = get_option( 'give_doing_upgrade' );
448
449 if ( ! empty( $doing_upgrade_args ) ) {
450 $log_data .= 'Doing update:' . "\n";
451 $log_data .= print_r( $doing_upgrade_args, true ) . "\n";
452 }
453
454 /**
455 * Add remove upgrade from batch
456 */
457 if ( ! empty( $batch->data ) ) {
458
459 foreach ( $batch->data as $index => $update ) {
460 $log_data = print_r( $update, true ) . "\n";
461
462 if ( ! is_callable( $update['callback'] ) ) {
463 $log_data .= 'Removing missing callback update: ' . "{$update['id']}\n";
464 unset( $batch->data[ $index ] );
465 } elseif ( give_has_upgrade_completed( $update['id'] ) ) {
466 $log_data .= 'Removing already completed update: ' . "{$update['id']}\n";
467 unset( $batch->data[ $index ] );
468 }
469
470 if ( ! empty( $update['depend'] ) ) {
471
472 foreach ( $update['depend'] as $depend ) {
473 if ( give_has_upgrade_completed( $depend ) ) {
474 $log_data .= 'Completed update: ' . "{$depend}\n";
475 continue;
476 }
477
478 if ( in_array( $depend, $all_update_ids ) && ! in_array( $depend, $all_batch_update_ids ) ) {
479 $log_data .= 'Adding missing update: ' . "{$depend}\n";
480 array_unshift( $batch->data, $all_updates[ array_search( $depend, $all_update_ids ) ] );
481 }
482 }
483 }
484 }
485 }
486
487 /**
488 * Add new upgrade to batch
489 */
490 if ( $new_updates = $this->get_updates( 'database', 'new' ) ) {
491 $all_batch_update_ids = ! empty( $batch->data ) ? wp_list_pluck( $batch->data, 'id' ) : [];
492
493 foreach ( $new_updates as $index => $new_update ) {
494 if ( give_has_upgrade_completed( $new_update['id'] ) || in_array( $new_update['id'], $all_batch_update_ids ) ) {
495 unset( $new_updates[ $index ] );
496 }
497 }
498
499 if ( ! empty( $new_updates ) ) {
500 $log_data .= 'Adding new update: ' . "\n";
501 $log_data .= print_r( $new_updates, true ) . "\n";
502
503 $batch->data = array_merge( (array) $batch->data, $new_updates );
504 update_option( 'give_db_update_count', ( absint( get_option( 'give_db_update_count' ) ) + count( $new_updates ) ), false );
505 }
506 }
507
508 /**
509 * Fix batch
510 */
511 if ( empty( $batch->data ) ) {
512 // Complete batch if do not have any data to process.
513 self::$background_updater->delete( $batch->key );
514
515 if ( self::$background_updater->has_queue() ) {
516 $this->health_background_update( $this );
517 } else {
518 delete_site_transient( self::$background_updater->get_identifier() . '_process_lock' );
519 wp_clear_scheduled_hook( self::$background_updater->get_cron_identifier() );
520
521 self::$background_updater->complete();
522 }
523 } elseif ( array_diff( wp_list_pluck( $batch->data, 'id' ), $old_batch_update_ids ) ) {
524
525 $log_data .= 'Updating batch' . "\n";
526 $log_data .= print_r( $batch, true );
527
528 if ( ! empty( $batch->key ) ) {
529 wp_cache_delete( $batch->key, 'options' );
530 update_option( $batch->key, $batch->data, false );
531 } else {
532
533 foreach ( $batch->data as $data ) {
534 self::$background_updater->push_to_queue( $data );
535 }
536
537 self::$background_updater->save();
538 }
539 }
540
541 /**
542 * Fix give_doing_upgrade option
543 */
544 if ( $fresh_new_db_count = $this->get_total_new_db_update_count( true ) ) {
545 update_option( 'give_db_update_count', $fresh_new_db_count, false );
546 }
547
548 $doing_upgrade_args['update'] = 1;
549 $doing_upgrade_args['heading'] = sprintf( 'Update %s of %s', 1, $fresh_new_db_count );
550 $doing_upgrade_args['total_percentage'] = $this->get_db_update_processing_percentage( true );
551
552 // Remove already completed update from info.
553 if (
554 empty( $doing_upgrade_args['update_info'] )
555 || give_has_upgrade_completed( $doing_upgrade_args['update_info']['id'] )
556 ) {
557 $doing_upgrade_args['update_info'] = current( array_values( $batch->data ) );
558 $doing_upgrade_args['step'] = 1;
559 }
560
561 // Check if dependency completed or not.
562 if ( isset( $doing_upgrade_args['update_info']['depend'] ) ) {
563 foreach ( $doing_upgrade_args['update_info']['depend'] as $depend ) {
564 if ( give_has_upgrade_completed( $depend ) ) {
565 continue;
566 }
567
568 $doing_upgrade_args['update_info'] = $all_updates[ array_search( $depend, $all_update_ids ) ];
569 $doing_upgrade_args['step'] = 1;
570 $doing_upgrade_args['percentage'] = 0;
571 $doing_upgrade_args['total_percentage'] = 0;
572
573 break;
574 }
575 }
576
577 if ( ! empty( $doing_upgrade_args['update_info'] ) ) {
578 update_option( 'give_doing_upgrade', $doing_upgrade_args, false );
579
580 $log_data .= 'Updated doing update:' . "\n";
581 $log_data .= print_r( $doing_upgrade_args, true ) . "\n";
582 }
583
584 Give()->logs->add( 'Update Health Check', $log_data, 0, 'update' );
585 }
586
587
588 /**
589 * Show update related notices
590 *
591 * @since 4.9.0 rename function - PHP 8 compatibility
592 * @since 2.0
593 * @access public
594 */
595 public function show_notice() {
596 $current_screen = get_current_screen();
597 $hide_on_pages = [
598 'give_forms_page_give-updates',
599 'update-core',
600 'give_forms_page_give-addons',
601 ];
602
603 // Bailout.
604 if ( ! current_user_can( 'manage_give_settings' ) ) {
605 return;
606 }
607
608 // Run DB updates.
609 if ( ! empty( $_GET['give-run-db-update'] ) ) {
610 $this->run_db_update();
611 }
612
613 // Bailout.
614 if ( in_array( $current_screen->base, $hide_on_pages ) ) {
615 return;
616 }
617
618 // Show notice if upgrade paused.
619 if ( self::$background_updater->is_paused_process() ) {
620 ob_start();
621
622 $upgrade_error = get_option( 'give_upgrade_error' );
623 if ( ! $upgrade_error ) : ?>
624 <strong><?php _e( 'Database Update', 'give' ); ?></strong>
625 &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' ); ?>
626 <br>
627 <br>
628 <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">
629 <?php _e( 'Restart the updater', 'give' ); ?>
630 </a>
631 <?php else : ?>
632 <strong><?php _e( 'Database Update', 'give' ); ?></strong>
633 &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' ); ?>
634 <a href="<?php echo esc_url( 'http://docs.givewp.com/troubleshooting-db-updates' ); ?>" target="_blank"><?php _e( 'Read More', 'give' ); ?> &raquo;</a>
635 <?php
636 endif;
637 $desc_html = ob_get_clean();
638
639 Give()->notices->register_notice(
640 [
641 'id' => 'give_upgrade_db',
642 'type' => 'error',
643 'dismissible' => false,
644 'description' => $desc_html,
645 ]
646 );
647 }
648
649 // Bailout if doing upgrades.
650 if ( $this->is_doing_updates() ) {
651 return;
652 }
653
654 // Show db upgrade completed notice.
655 if ( ! empty( $_GET['give-db-update-completed'] ) ) {
656 Give()->notices->register_notice(
657 [
658 'id' => 'give_db_upgrade_completed',
659 'type' => 'updated',
660 'description' => __( 'GiveWP database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
661 'show' => true,
662 ]
663 );
664
665 // Start update.
666 } elseif ( ! empty( $_GET['give-run-db-update'] ) ) {
667 $this->run_db_update();
668
669 // Show run the update notice.
670 } elseif ( $this->get_total_new_db_update_count() ) {
671 ob_start();
672 ?>
673 <p>
674 <strong><?php _e( 'Database Update', 'give' ); ?></strong>
675 &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' ); ?>
676 </p>
677 <p class="submit">
678 <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">
679 <?php _e( 'Run the updater', 'give' ); ?>
680 </a>
681 </p>
682 <?php
683 $desc_html = ob_get_clean();
684
685 Give()->notices->register_notice(
686 [
687 'id' => 'give_upgrade_db',
688 'type' => 'updated',
689 'dismissible' => false,
690 'description' => $desc_html,
691 ]
692 );
693 }
694 }
695
696 /**
697 * Render Give Updates Completed page
698 *
699 * @since 1.8.12
700 * @access public
701 */
702 public function render_complete_page() {
703 include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades-complete.php';
704 }
705
706 /**
707 * Render Give Updates page
708 *
709 * @since 1.8.12
710 * @access public
711 */
712 public function render_page() {
713 include_once GIVE_PLUGIN_DIR . 'includes/admin/upgrades/views/upgrades.php';
714 }
715
716 /**
717 * Run database upgrades
718 *
719 * @since 2.0
720 * @access private
721 */
722 private function run_db_update() {
723 // Bailout.
724 if ( $this->is_doing_updates() || ! $this->get_total_new_db_update_count() ) {
725 return;
726 }
727
728 $updates = $this->get_updates( 'database', 'new' );
729
730 foreach ( $updates as $update ) {
731 self::$background_updater->push_to_queue( $update );
732 }
733
734 add_option( 'give_db_update_count', count( $updates ), '', false );
735
736 add_option(
737 'give_doing_upgrade',
738 [
739 'update_info' => $updates[0],
740 'step' => 1,
741 'update' => 1,
742 'heading' => sprintf( 'Update %s of %s', 1, count( $updates ) ),
743 'percentage' => 0,
744 'total_percentage' => 0,
745 ],
746 '',
747 false
748 );
749
750 self::$background_updater->save()->dispatch();
751 }
752
753
754 /**
755 * Delete resume updates
756 *
757 * @since 4.9.0 rename function - PHP 8 compatibility
758 * @since 1.8.12
759 * @access public
760 */
761 public function flush_resume_updates() {
762 $this->step = $this->percentage = 0;
763
764 $this->update = ( $this->get_total_db_update_count() > $this->update ) ?
765 ( $this->update + 1 ) :
766 $this->update;
767 }
768
769
770 /**
771 * Initialize updates
772 *
773 * @since 4.9.0 rename function - PHP 8 compatibility
774 * @since 2.0
775 * @access public
776 *
777 * @return void
778 */
779 public function give_start_updating() {
780 // Check permission.
781 if (
782 ! current_user_can( 'manage_give_settings' ) ||
783 $this->is_doing_updates()
784 ) {
785 // Run update via ajax
786 self::$background_updater->dispatch();
787
788 wp_send_json_error();
789 }
790
791 // @todo: validate nonce
792 // @todo: set http method to post
793 if ( empty( $_POST['run_db_update'] ) ) {
794 wp_send_json_error();
795 }
796
797 $this->run_db_update();
798
799 wp_send_json_success();
800 }
801
802
803 /**
804 * This function handle ajax query for dn update status.
805 *
806 * @since 4.9.0 rename function - PHP 8 compatibility
807 * @since 2.0
808 * @access public
809 *
810 * @return string
811 */
812 public function give_db_updates_info() {
813 // Check permission.
814 if ( ! current_user_can( 'manage_give_settings' ) ) {
815 give_die();
816 }
817
818 $update_info = get_option( 'give_doing_upgrade' );
819 $response_type = '';
820
821 if ( self::$background_updater->is_paused_process() ) {
822 $update_info = [
823 'message' => __( 'The updates have been paused.', 'give' ),
824 'heading' => '',
825 'percentage' => 0,
826 ];
827
828 if ( get_option( 'give_upgrade_error' ) ) {
829 $update_info['message'] = __( 'An unexpected issue occurred during the database update which caused it to stop automatically. Please contact support for assistance.', 'give' );
830 }
831
832 $response_type = 'error';
833
834 } elseif ( empty( $update_info ) || ! $this->get_total_new_db_update_count( true ) ) {
835 $update_info = [
836 'message' => __( 'GiveWP database updates completed successfully. Thank you for updating to the latest version!', 'give' ),
837 'heading' => __( 'Updates Completed.', 'give' ),
838 'percentage' => 0,
839 ];
840 $response_type = 'success';
841
842 delete_option( 'give_show_db_upgrade_complete_notice' );
843 }
844
845 $this->send_ajax_response( $update_info, $response_type );
846 }
847
848 /**
849 * Send ajax response
850 *
851 * @since 1.8.12
852 * @access public
853 *
854 * @param $data
855 * @param string $type
856 */
857 public function send_ajax_response( $data, $type = '' ) {
858 $default = [
859 'message' => '',
860 'heading' => '',
861 'percentage' => 0,
862 'step' => 0,
863 'update' => 0,
864 ];
865
866 // Set data.
867 $data = wp_parse_args( $data, $default );
868
869 // Enable cache.
870 Give_Cache::enable();
871
872 switch ( $type ) {
873 case 'success':
874 wp_send_json_success( $data );
875 break;
876
877 case 'error':
878 wp_send_json_error( $data );
879 break;
880
881 default:
882 wp_send_json(
883 [
884 'data' => $data,
885 ]
886 );
887 break;
888 }
889 }
890
891 /**
892 * Set current update percentage.
893 *
894 * @since 1.8.12
895 * @access public
896 *
897 * @param $total
898 * @param $current_total
899 */
900 public function set_percentage( $total, $current_total ) {
901 // Set percentage.
902 $this->percentage = $total ? ( ( $current_total ) / $total ) * 100 : 0;
903
904 // Verify percentage.
905 $this->percentage = ( 100 < $this->percentage ) ? 100 : $this->percentage;
906 }
907
908 /**
909 * Check if parent update completed or not.
910 *
911 * @since 2.0
912 * @access private
913 *
914 * @param array $update
915 *
916 * @return bool|null
917 */
918 public function is_parent_updates_completed( $update ) {
919 // Bailout.
920 if ( empty( $update['depend'] ) ) {
921 return true;
922 }
923
924 // Check if dependency is valid or not.
925 if ( ! $this->has_valid_dependency( $update ) ) {
926 return null;
927 }
928
929 $is_dependency_completed = true;
930
931 foreach ( $update['depend'] as $depend ) {
932
933 if ( ! give_has_upgrade_completed( $depend ) ) {
934 $is_dependency_completed = false;
935 break;
936 }
937 }
938
939 return $is_dependency_completed;
940 }
941
942 /**
943 * Flag to check if DB updates running or not.
944 *
945 * @since 2.0
946 * @access public
947 * @return bool
948 */
949 public function is_doing_updates() {
950 return (bool) Give_Cache_Setting::get_option( 'give_doing_upgrade' );
951 }
952
953
954 /**
955 * Check if update has valid dependency or not.
956 *
957 * @since 2.0
958 * @access public
959 *
960 * @param $update
961 *
962 * @return bool
963 */
964 public function has_valid_dependency( $update ) {
965 $is_valid_dependency = true;
966 // $update_ids = wp_list_pluck( $this->get_updates( 'database', 'all' ), 'id' );
967 //
968 // foreach ( $update['depend'] as $depend ) {
969 // Check if dependency is valid or not.
970 // if ( ! in_array( $depend, $update_ids ) ) {
971 // $is_valid_dependency = false;
972 // break;
973 // }
974 // }
975
976 return $is_valid_dependency;
977 }
978
979 /**
980 * Get updates.
981 *
982 * @since 1.8.12
983 * @access public
984 *
985 * @param string $update_type Tye of update.
986 * @param string $status Tye of update.
987 *
988 * @return array
989 */
990 public function get_updates( $update_type = '', $status = 'all' ) {
991 // return all updates.
992 if ( empty( $update_type ) ) {
993 return $this->updates;
994 }
995
996 // Get specific update.
997 $updates = ! empty( $this->updates[ $update_type ] ) ? $this->updates[ $update_type ] : [];
998
999 // Bailout.
1000 if ( empty( $updates ) ) {
1001 return $updates;
1002 }
1003
1004 switch ( $status ) {
1005 case 'new':
1006 // Remove already completed updates.
1007 wp_cache_delete( 'give_completed_upgrades', 'options' );
1008 $completed_updates = give_get_completed_upgrades();
1009
1010 if ( ! empty( $completed_updates ) ) {
1011 foreach ( $updates as $index => $update ) {
1012 if ( in_array( $update['id'], $completed_updates ) ) {
1013 unset( $updates[ $index ] );
1014 }
1015 }
1016 $updates = array_values( $updates );
1017 }
1018
1019 break;
1020 }
1021
1022 return $updates;
1023 }
1024
1025 /**
1026 * Get addon update count.
1027 *
1028 * @since 1.8.12
1029 * @access public
1030 * @return int
1031 */
1032 public function get_total_plugin_update_count() {
1033 return count( $this->get_updates( 'plugin' ) );
1034 }
1035
1036 /**
1037 * Get total update count
1038 *
1039 * @since 1.8.12
1040 * @access public
1041 *
1042 * @return int
1043 */
1044 public function get_total_update_count() {
1045 $db_update_count = $this->get_pending_db_update_count();
1046 $plugin_update_count = $this->get_total_plugin_update_count();
1047
1048 return ( $db_update_count + $plugin_update_count );
1049 }
1050
1051 /**
1052 * Get total pending updates count
1053 *
1054 * @since 1.8.12
1055 * @access public
1056 *
1057 * @return int
1058 */
1059 public function get_pending_db_update_count() {
1060 return count( $this->get_updates( 'database', 'new' ) );
1061 }
1062
1063 /**
1064 * Get total updates count
1065 *
1066 * @since 1.8.18
1067 * @access public
1068 *
1069 * @return int
1070 */
1071 public function get_total_db_update_count() {
1072 return count( $this->get_updates( 'database', 'all' ) );
1073 }
1074
1075 /**
1076 * Get total new updates count
1077 *
1078 * @since 2.0
1079 * @access public
1080 *
1081 * @param bool $refresh
1082 *
1083 * @return int
1084 */
1085 public function get_total_new_db_update_count( $refresh = false ) {
1086 $update_count = $this->is_doing_updates() && ! $refresh ?
1087 get_option( 'give_db_update_count' ) :
1088 $this->get_pending_db_update_count();
1089
1090 return $update_count;
1091 }
1092
1093 /**
1094 * Get total new updates count
1095 *
1096 * @since 2.0
1097 * @access public
1098 *
1099 * @param bool $refresh
1100 *
1101 * @return int
1102 */
1103 public function get_running_db_update( $refresh = false ) {
1104 $current_update = 1;
1105
1106 if ( $this->is_doing_updates() && ! $refresh ) {
1107 $current_update = get_option( 'give_doing_upgrade' );
1108 $current_update = $current_update['update'];
1109 }
1110
1111 return $current_update;
1112 }
1113
1114 /**
1115 * Get database update processing percentage.
1116 *
1117 * @since 2.0
1118 * @access public
1119 *
1120 * @param bool $refresh
1121 *
1122 * @return float|int
1123 */
1124 public function get_db_update_processing_percentage( $refresh = false ) {
1125 // Bailout.
1126 if ( ! $this->get_total_new_db_update_count( $refresh ) ) {
1127 return 0;
1128 }
1129
1130 $resume_update = get_option( 'give_doing_upgrade' );
1131 $update_count_percentages = ( ( $this->get_running_db_update( $refresh ) - 1 ) / $this->get_total_new_db_update_count( $refresh ) ) * 100;
1132 $update_percentage_share = ( 1 / $this->get_total_new_db_update_count() ) * 100;
1133 $upgrade_percentage = ( ( $resume_update['percentage'] * $update_percentage_share ) / 100 );
1134
1135 $final_percentage = $update_count_percentages + $upgrade_percentage;
1136
1137 return $this->is_doing_updates() ?
1138 ( absint( $final_percentage ) ?
1139 absint( $final_percentage ) :
1140 round( $final_percentage, 2 )
1141 ) :
1142 0;
1143 }
1144
1145
1146 /**
1147 * Get all update ids.
1148 *
1149 * @since 2.0.3
1150 *
1151 * @return array
1152 */
1153 public function get_update_ids() {
1154 $all_updates = $this->get_updates( 'database', 'all' );
1155 $all_update_ids = wp_list_pluck( $all_updates, 'id' );
1156
1157 return $all_update_ids;
1158 }
1159
1160 /**
1161 * Get offset count
1162 *
1163 * @since 2.0.5
1164 * @access public
1165 *
1166 * @param int $process_item_count
1167 *
1168 * @return float|int
1169 */
1170 public function get_offset( $process_item_count ) {
1171 return ( 1 === $this->step ) ?
1172 0 :
1173 ( $this->step - 1 ) * $process_item_count;
1174 }
1175 }
1176
1177 Give_Updates::get_instance()->setup();
1178