PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.16.8.1
GiveWP – Donation Plugin and Fundraising Platform v4.16.8.1
4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 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 All 254 releases
give / includes / admin / admin-actions.php

admin-actions.php in GiveWP – Donation Plugin and Fundraising Platform 4.16.8.1, at includes/admin/admin-actions.php

1,722 lines 46.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use Give\Framework\Database\DB;
4 use Give\Helpers\Utils;
5 use Give\Log\ValueObjects\LogType;
6
7 /**
8 * Admin Actions
9 *
10 * @package Give
11 * @since 1.0
12 * @copyright Copyright (c) 2016, GiveWP
13 * @license https://opensource.org/licenses/gpl-license GNU Public License
14 * @subpackage Admin/Actions
15 */
16
17 // Exit if accessed directly.
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit;
20 }
21
22 /**
23 * Load wp editor by ajax.
24 *
25 * @since 1.8
26 */
27 function give_load_wp_editor() {
28 if ( ! isset( $_POST['wp_editor'] ) || ! current_user_can( 'edit_give_forms' ) ) {
29 die();
30 }
31
32 $wp_editor = json_decode( base64_decode( $_POST['wp_editor'] ), true );
33 $wp_editor[2]['textarea_name'] = give_clean( $_POST['textarea_name'] );
34
35 wp_editor( wp_kses_post( $wp_editor[0] ), give_clean( $_POST['wp_editor_id'] ), $wp_editor[2] );
36
37 die();
38 }
39
40 add_action( 'wp_ajax_give_load_wp_editor', 'give_load_wp_editor' );
41
42
43 /**
44 * Redirect admin to clean url give admin pages.
45 *
46 * @since 2.25.2 Removed _wpnonce from list of removed args.
47 * @since 1.8
48 *
49 * @return bool
50 */
51 function give_redirect_to_clean_url_admin_pages() {
52 // Give admin pages.
53 $give_pages = [
54 'give-payment-history',
55 'give-donors',
56 'give-reports',
57 'give-tools',
58 ];
59
60 // Get current page.
61 $current_page = isset( $_GET['page'] ) ? esc_attr( $_GET['page'] ) : '';
62
63 // Bailout.
64 if (
65 empty( $current_page )
66 || empty( $_GET['_wp_http_referer'] )
67 || ! in_array( $current_page, $give_pages )
68 ) {
69 return false;
70 }
71
72 /**
73 * Verify current page request.
74 *
75 * @since 1.8
76 */
77 $redirect = apply_filters( "give_validate_{$current_page}", true );
78
79 if ( $redirect ) {
80 // Redirect.
81 wp_redirect(
82 esc_url_raw(
83 remove_query_arg(
84 ['_wp_http_referer'],
85 wp_unslash($_SERVER['REQUEST_URI'])
86 )
87 )
88 );
89 exit;
90 }
91 }
92
93 add_action( 'admin_init', 'give_redirect_to_clean_url_admin_pages' );
94
95
96 /**
97 * Hide Outdated PHP Notice Shortly.
98 *
99 * This code is used with AJAX call to hide outdated PHP notice for a short period of time
100 *
101 * @since 1.8.9
102 * @return void
103 */
104 function give_hide_outdated_php_notice() {
105
106 if ( ! isset( $_POST['_give_hide_outdated_php_notices_shortly'] ) || ! current_user_can( 'manage_give_settings' ) ) {
107 give_die();
108 }
109
110 // Transient key name.
111 $transient_key = '_give_hide_outdated_php_notices_shortly';
112
113 if ( Give_Cache::get( $transient_key, true ) ) {
114 return;
115 }
116
117 // Hide notice for 24 hours.
118 Give_Cache::set( $transient_key, true, DAY_IN_SECONDS, true );
119
120 give_die();
121
122 }
123
124 add_action( 'wp_ajax_give_hide_outdated_php_notice', 'give_hide_outdated_php_notice' );
125
126 /**
127 * Register admin notices.
128 *
129 * @since 2.25.2 Add nonce check for bulk action.
130 * @since 1.8.9
131 */
132 function _give_register_admin_notices() {
133 // Bailout.
134 if ( ! is_admin() ) {
135 return;
136 }
137
138 // Bulk action notices.
139 if (
140 isset( $_GET['action'] ) &&
141 ! empty( $_GET['action'] )
142 ) {
143
144 // Add payment bulk notice.
145 if (
146 current_user_can('edit_give_payments') &&
147 isset($_GET['_wpnonce']) &&
148 wp_verify_nonce($_GET['_wpnonce'], 'bulk-forms') &&
149 isset($_GET['payment']) &&
150 ! empty( $_GET['payment'] )
151 ) {
152 $payment_count = isset( $_GET['payment'] ) ? count( $_GET['payment'] ) : 0;
153
154 switch ( $_GET['action'] ) {
155 case 'delete':
156 Give()->notices->register_notice(
157 [
158 'id' => 'bulk_action_delete',
159 'type' => 'updated',
160 'description' => sprintf(
161 _n(
162 'Successfully deleted one donation.',
163 'Successfully deleted %d donations.',
164 $payment_count,
165 'give'
166 ),
167 $payment_count
168 ),
169 'show' => true,
170 ]
171 );
172
173 break;
174
175 case 'resend-receipt':
176 Give()->notices->register_notice(
177 [
178 'id' => 'bulk_action_resend_receipt',
179 'type' => 'updated',
180 'description' => sprintf(
181 _n(
182 'Successfully sent email receipt to one recipient.',
183 'Successfully sent email receipts to %d recipients.',
184 $payment_count,
185 'give'
186 ),
187 $payment_count
188 ),
189 'show' => true,
190 ]
191 );
192 break;
193
194 case 'set-status-publish':
195 case 'set-status-pending':
196 case 'set-status-processing':
197 case 'set-status-refunded':
198 case 'set-status-revoked':
199 case 'set-status-failed':
200 case 'set-status-cancelled':
201 case 'set-status-abandoned':
202 case 'set-status-preapproval':
203 Give()->notices->register_notice(
204 [
205 'id' => 'bulk_action_status_change',
206 'type' => 'updated',
207 'description' => _n(
208 'Donation status updated successfully.',
209 'Donation statuses updated successfully.',
210 $payment_count,
211 'give'
212 ),
213 'show' => true,
214 ]
215 );
216 break;
217 }// End switch().
218 }// End if().
219 }// End if().
220
221 // Add give message notices.
222 $message_notices = give_get_admin_messages_key();
223 if ( ! empty( $message_notices ) ) {
224 foreach ( $message_notices as $message_notice ) {
225 // Donation reports errors.
226 if ( current_user_can( 'view_give_reports' ) ) {
227 switch ( $message_notice ) {
228 case 'donation-deleted':
229 Give()->notices->register_notice(
230 [
231 'id' => 'give-donation-deleted',
232 'type' => 'updated',
233 'description' => __( 'The donation has been deleted.', 'give' ),
234 'show' => true,
235 ]
236 );
237 break;
238 case 'email-sent':
239 Give()->notices->register_notice(
240 [
241 'id' => 'give-email-sent',
242 'type' => 'updated',
243 'description' => __( 'The donation receipt has been resent.', 'give' ),
244 'show' => true,
245 ]
246 );
247 break;
248 case 'refreshed-reports':
249 Give()->notices->register_notice(
250 [
251 'id' => 'give-refreshed-reports',
252 'type' => 'updated',
253 'description' => __( 'The reports cache has been cleared.', 'give' ),
254 'show' => true,
255 ]
256 );
257 break;
258 case 'donation-note-deleted':
259 Give()->notices->register_notice(
260 [
261 'id' => 'give-donation-note-deleted',
262 'type' => 'updated',
263 'description' => __( 'The donation note has been deleted.', 'give' ),
264 'show' => true,
265 ]
266 );
267 break;
268 }// End switch().
269 }// End if().
270
271 // Give settings notices and errors.
272 if ( current_user_can( 'manage_give_settings' ) ) {
273 switch ( $message_notice ) {
274 case 'settings-imported':
275 Give()->notices->register_notice(
276 [
277 'id' => 'give-settings-imported',
278 'type' => 'updated',
279 'description' => __( 'The settings have been imported.', 'give' ),
280 'show' => true,
281 ]
282 );
283 break;
284 case 'api-key-generated':
285 Give()->notices->register_notice(
286 [
287 'id' => 'give-api-key-generated',
288 'type' => 'updated',
289 'description' => __( 'API keys have been generated.', 'give' ),
290 'show' => true,
291 ]
292 );
293 break;
294 case 'api-key-exists':
295 Give()->notices->register_notice(
296 [
297 'id' => 'give-api-key-exists',
298 'type' => 'updated',
299 'description' => __( 'The specified user already has API keys.', 'give' ),
300 'show' => true,
301 ]
302 );
303 break;
304 case 'api-key-regenerated':
305 Give()->notices->register_notice(
306 [
307 'id' => 'give-api-key-regenerated',
308 'type' => 'updated',
309 'description' => __( 'API keys have been regenerated.', 'give' ),
310 'show' => true,
311 ]
312 );
313 break;
314 case 'api-key-revoked':
315 Give()->notices->register_notice(
316 [
317 'id' => 'give-api-key-revoked',
318 'type' => 'updated',
319 'description' => __( 'API keys have been revoked.', 'give' ),
320 'show' => true,
321 ]
322 );
323 break;
324 case 'sent-test-email':
325 Give()->notices->register_notice(
326 [
327 'id' => 'give-sent-test-email',
328 'type' => 'updated',
329 'description' => sprintf( __( 'The test email has been sent to %s.', 'give' ), wp_get_current_user()->user_email ),
330 'show' => true,
331 ]
332 );
333 break;
334 case 'matched-success-failure-page':
335 Give()->notices->register_notice(
336 [
337 'id' => 'give-matched-success-failure-page',
338 'type' => 'updated',
339 'description' => __( 'You cannot set the success and failed pages to the same page', 'give' ),
340 'show' => true,
341 ]
342 );
343 break;
344 case 'akismet-deblacklisted-email':
345 Give()->notices->register_notice(
346 [
347 'id' => 'give-akismet-deblacklisted-email',
348 'type' => 'updated',
349 'description' => __( 'Email de-blacklisted successfully. Now Donor will able to process donation with email flagged as spam', 'give' ),
350 'show' => true,
351 'dismissible' => 'auto',
352 ]
353 );
354 break;
355 }// End switch().
356 }// End if().
357
358 // Payments errors.
359 if ( current_user_can( 'edit_give_payments' ) ) {
360 switch ( $message_notice ) {
361 case 'note-added':
362 Give()->notices->register_notice(
363 [
364 'id' => 'give-note-added',
365 'type' => 'updated',
366 'description' => __( 'The donation note has been added.', 'give' ),
367 'show' => true,
368 ]
369 );
370 break;
371 case 'payment-updated':
372 Give()->notices->register_notice(
373 [
374 'id' => 'give-payment-updated',
375 'type' => 'updated',
376 'description' => __( 'The donation has been updated.', 'give' ),
377 'show' => true,
378 ]
379 );
380 break;
381 }// End switch().
382 }// End if().
383
384 // Donor Notices.
385 if ( current_user_can( 'edit_give_payments' ) ) {
386 switch ( $message_notice ) {
387 case 'donor-deleted':
388 Give()->notices->register_notice(
389 [
390 'id' => 'give-donor-deleted',
391 'type' => 'updated',
392 'description' => __( 'The selected donor(s) has been deleted.', 'give' ),
393 'show' => true,
394 ]
395 );
396 break;
397
398 case 'donor-donations-deleted':
399 Give()->notices->register_notice(
400 [
401 'id' => 'give-donor-donations-deleted',
402 'type' => 'updated',
403 'description' => __( 'The selected donor(s) and the associated donation(s) has been deleted.', 'give' ),
404 'show' => true,
405 ]
406 );
407 break;
408
409 case 'confirm-delete-donor':
410 Give()->notices->register_notice(
411 [
412 'id' => 'give-confirm-delete-donor',
413 'type' => 'updated',
414 'description' => __( 'You must confirm to delete the selected donor(s).', 'give' ),
415 'show' => true,
416 ]
417 );
418 break;
419
420 case 'invalid-donor-id':
421 Give()->notices->register_notice(
422 [
423 'id' => 'give-invalid-donor-id',
424 'type' => 'updated',
425 'description' => __( 'Invalid Donor ID.', 'give' ),
426 'show' => true,
427 ]
428 );
429 break;
430
431 case 'donor-delete-failed':
432 Give()->notices->register_notice(
433 [
434 'id' => 'give-donor-delete-failed',
435 'type' => 'error',
436 'description' => __( 'Unable to delete selected donor(s).', 'give' ),
437 'show' => true,
438 ]
439 );
440 break;
441
442 case 'email-added':
443 Give()->notices->register_notice(
444 [
445 'id' => 'give-email-added',
446 'type' => 'updated',
447 'description' => __( 'Donor email added.', 'give' ),
448 'show' => true,
449 ]
450 );
451 break;
452
453 case 'email-removed':
454 Give()->notices->register_notice(
455 [
456 'id' => 'give-email-removed',
457 'type' => 'updated',
458 'description' => __( 'Donor email removed.', 'give' ),
459 'show' => true,
460 ]
461 );
462 break;
463
464 case 'email-remove-failed':
465 Give()->notices->register_notice(
466 [
467 'id' => 'give-email-remove-failed',
468 'type' => 'updated',
469 'description' => __( 'Failed to remove donor email.', 'give' ),
470 'show' => true,
471 ]
472 );
473 break;
474
475 case 'primary-email-updated':
476 Give()->notices->register_notice(
477 [
478 'id' => 'give-primary-email-updated',
479 'type' => 'updated',
480 'description' => __( 'Primary email updated for donor.', 'give' ),
481 'show' => true,
482 ]
483 );
484 break;
485
486 case 'primary-email-failed':
487 Give()->notices->register_notice(
488 [
489 'id' => 'give-primary-email-failed',
490 'type' => 'updated',
491 'description' => __( 'Failed to set primary email.', 'give' ),
492 'show' => true,
493 ]
494 );
495 break;
496
497 case 'reconnect-user':
498 Give()->notices->register_notice(
499 [
500 'id' => 'give-reconnect-user',
501 'type' => 'updated',
502 'description' => __( 'User has been successfully connected with Donor.', 'give' ),
503 'show' => true,
504 ]
505 );
506 break;
507
508 case 'disconnect-user':
509 Give()->notices->register_notice(
510 [
511 'id' => 'give-disconnect-user',
512 'type' => 'updated',
513 'description' => __( 'User has been successfully disconnected from donor.', 'give' ),
514 'show' => true,
515 ]
516 );
517 break;
518
519 case 'profile-updated':
520 Give()->notices->register_notice(
521 [
522 'id' => 'give-profile-updated',
523 'type' => 'updated',
524 'description' => __( 'Donor information updated successfully.', 'give' ),
525 'show' => true,
526 ]
527 );
528 break;
529 }// End switch().
530 }// End if().
531 }
532 }
533
534 /**
535 * Spam log admin notice
536 */
537 if (
538 current_user_can( 'manage_give_settings' ) &&
539 give_is_setting_enabled( give_get_option( 'akismet_spam_protection' ) )
540 ) {
541 global $wpdb;
542
543 $current_time = current_time( 'timestamp' );
544 $end_of_current_time_in_gmt = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( 'tomorrow', $current_time ) ), 'U' );
545 $current_time_gmt = get_gmt_from_date( date( 'Y-m-d H:i:s', $current_time ), 'U' );
546
547 $spam_count = DB::get_var(
548 DB::prepare( "SELECT COUNT(id) FROM {$wpdb->give_log} WHERE log_type = %s AND date >= CURDATE();", LogType::SPAM )
549 );
550
551 if ( $spam_count && ! Give_Admin_Settings::is_setting_page( 'logs', 'spam' ) ) {
552 Give()->notices->register_notice(
553 [
554 'id' => 'give-new-akismet-spam-found',
555 'type' => 'warning',
556 'description' => sprintf(
557 __( 'Akismet flagged %1$s %2$s as spam. If you believe %7$s %5$s actual %6$s, you can whitelist %7$s to allow the %6$s to process donations. <a href="%3$s" title="%4$s">Click here</a> to review spam logs.', 'give' ),
558 $spam_count,
559 _n( 'donor email', 'donor emails', $spam_count, 'give' ),
560 esc_url( admin_url( 'edit.php?post_type=give_forms&page=give-tools&tab=logs&section=spam' ) ),
561 __( 'Go to spam log list page', 'give' ),
562 _n( 'was', 'were', $spam_count, 'give' ),
563 _n( 'donor', 'donors', $spam_count, 'give' ),
564 _n( 'this', 'these', $spam_count, 'give' )
565 ),
566 'dismissible_type' => 'user',
567 'dismiss_interval' => 'custom',
568 'dismiss_interval_time' => $end_of_current_time_in_gmt - $current_time_gmt,
569 ]
570 );
571 }
572 }
573 }
574
575 add_action( 'admin_notices', '_give_register_admin_notices', - 1 );
576
577
578 /**
579 * Display admin bar when active.
580 *
581 * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance, passed by reference.
582 *
583 * @return bool
584 */
585 function _give_show_test_mode_notice_in_admin_bar( $wp_admin_bar ) {
586 $is_test_mode = ! empty( $_POST['test_mode'] ) ?
587 give_is_setting_enabled( $_POST['test_mode'] ) :
588 give_is_test_mode();
589
590 if (
591 ! current_user_can( 'view_give_reports' ) ||
592 ! $is_test_mode
593 ) {
594 return false;
595 }
596
597 // Add the main site admin menu item.
598 $wp_admin_bar->add_menu(
599 [
600 'id' => 'give-test-notice',
601 'href' => admin_url( 'edit.php?post_type=give_forms&page=give-settings&tab=gateways' ),
602 'parent' => 'top-secondary',
603 'title' => __( 'GiveWP Test Mode Active', 'give' ),
604 'meta' => [
605 'class' => 'give-test-mode-active',
606 ],
607 ]
608 );
609
610 return true;
611 }
612
613 add_action( 'admin_bar_menu', '_give_show_test_mode_notice_in_admin_bar', 1000, 1 );
614
615 /**
616 * Outputs the Give admin bar CSS.
617 */
618 function _give_test_mode_notice_admin_bar_css() {
619 if ( ! give_is_test_mode() ) {
620 return;
621 }
622 ?>
623 <style>
624 #wpadminbar .give-test-mode-active > .ab-item {
625 color: #fff;
626 background-color: #ffba00;
627 }
628
629 #wpadminbar .give-test-mode-active:hover > .ab-item, #wpadminbar .give-test-mode-active:hover > .ab-item {
630 background-color: rgba(203, 144, 0, 1) !important;
631 color: #fff !important;
632 }
633 </style>
634 <?php
635 }
636
637 add_action( 'admin_head', '_give_test_mode_notice_admin_bar_css' );
638
639
640 /**
641 * Add Link to Import page in from donation archive and donation single page
642 *
643 * @since 1.8.13
644 */
645 function give_import_page_link_callback() {
646 ?>
647 <a href="<?php echo esc_url( give_import_page_url() ); ?>"
648 class="page-import-action page-title-action"><?php _e( 'Import Donations', 'give' ); ?></a>
649 <script>
650 function showReactTable () {
651 fetch( '<?php echo esc_url_raw(rest_url('give-api/v2/admin/donations/view?isLegacy=0')) ?>', {
652 method: 'GET',
653 headers: {
654 ['X-WP-Nonce']: '<?php echo wp_create_nonce('wp_rest') ?>'
655 }
656 })
657 .then((res) => {
658 window.location.reload();
659 });
660 }
661 </script>
662 <button onclick="showReactTable()" class="page-title-action">
663 <?php _e('Switch to New View', 'give') ?>
664 </button>
665
666 <?php
667 // Check if view donation single page only.
668 if ( ! empty( $_REQUEST['view'] ) && 'view-payment-details' === (string) give_clean( $_REQUEST['view'] ) && 'give-payment-history' === give_clean( $_REQUEST['page'] ) ) {
669 ?>
670 <style type="text/css">
671 .wrap #transaction-details-heading {
672 display: inline-block;
673 }
674 </style>
675 <?php
676 }
677 }
678
679 add_action( 'give_payments_page_top', 'give_import_page_link_callback', 11 );
680
681 /**
682 * Avoid insecure usage of `unserialize` when the data could be submitted by the user.
683 *
684 * @since 3.16.1 Use Utils::giveMaybeSafeUnserialize() method
685 * @since 3.5.0
686 *
687 * @param string $data Data that might be unserialized.
688 *
689 * @return mixed Unserialized data can be any type.
690 */
691 function give_maybe_safe_unserialize($data)
692 {
693 return Utils::maybeSafeUnserialize($data);
694 }
695
696 /**
697 * Load donation import ajax callback
698 * Fire when importing from CSV start
699 *
700 * @since 4.11.0 Updated error handling to display errors in the import page.
701 * @since 3.5.0 Extract safe unserialize logic to a function and use it in other places.
702 * @since 2.25.3 Append nonce to response url.
703 * @since 1.8.13
704 */
705 function give_donation_import_callback() {
706
707 check_ajax_referer('give_donation_import');
708
709 // Bailout.
710 if ( ! current_user_can( 'manage_give_settings' ) ) {
711 give_die();
712 }
713
714 // Disable Give cache
715 Give_Cache::get_instance()->disable();
716
717 $import_setting = [];
718 $fields = isset( $_POST['fields'] ) ? $_POST['fields'] : null;
719
720 parse_str( $fields, $output );
721
722 $import_setting['create_user'] = $output['create_user'];
723 $import_setting['mode'] = $output['mode'];
724 $import_setting['delimiter'] = $output['delimiter'];
725 $import_setting['csv'] = $output['csv'];
726 $import_setting['delete_csv'] = $output['delete_csv'];
727 $import_setting['dry_run'] = $output['dry_run'];
728
729 // Parent key id.
730 $main_key = give_maybe_safe_unserialize($output['main_key']);
731
732 $current = absint( $_REQUEST['current'] );
733 $total_ajax = absint( $_REQUEST['total_ajax'] );
734 $start = absint( $_REQUEST['start'] );
735 $end = absint( $_REQUEST['end'] );
736 $next = absint( $_REQUEST['next'] );
737 $total = absint( $_REQUEST['total'] );
738 $per_page = absint( $_REQUEST['per_page'] );
739 if ( empty( $output['delimiter'] ) ) {
740 $delimiter = ',';
741 } else {
742 $delimiter = $output['delimiter'];
743 }
744
745 // Processing done here.
746 $raw_data = give_get_donation_data_from_csv( $output['csv'], $start, $end, $delimiter);
747 $raw_key = give_maybe_safe_unserialize($output['mapto']);
748 $import_setting['raw_key'] = $raw_key;
749
750 if ( ! empty( $output['dry_run'] ) ) {
751 $import_setting['csv_raw_data'] = give_get_donation_data_from_csv( $output['csv'], 1, $end, $delimiter );
752
753 $import_setting['donors_list'] = Give()->donors->get_donors(
754 [
755 'number' => - 1,
756 'fields' => [ 'id', 'user_id', 'email' ],
757 ]
758 );
759 }
760
761 // Prevent normal emails.
762 remove_action( 'give_complete_donation', 'give_trigger_donation_receipt', 999 );
763 remove_action( 'give_insert_user', 'give_new_user_notification', 10 );
764 remove_action( 'give_insert_payment', 'give_payment_save_page_data' );
765
766 $current_key = $start;
767 foreach ( $raw_data as $row_data ) {
768 $import_setting['donation_key'] = $current_key;
769 $result = give_save_import_donation_to_db( $raw_key, $row_data, $main_key, $import_setting );
770 if ( is_string( $result ) && ! empty( $result ) ) {
771 if ( empty( $json_data['errors'] ) ) {
772 $json_data['errors'] = [];
773 }
774 $json_data['errors'][] = sprintf( __( 'Row %1$d: %2$s', 'give' ), $current_key, $result );
775 }
776 $current_key ++;
777 }
778
779 // Check if function exists or not.
780 if ( function_exists( 'give_payment_save_page_data' ) ) {
781 add_action( 'give_insert_payment', 'give_payment_save_page_data' );
782 }
783 add_action( 'give_insert_user', 'give_new_user_notification', 10, 2 );
784 add_action( 'give_complete_donation', 'give_trigger_donation_receipt', 999 );
785
786 if ( $next == false ) {
787 $json_data = [
788 'success' => true,
789 'message' => __( 'All donation uploaded successfully!', 'give' ),
790 ];
791 } else {
792 $index_start = $start;
793 $index_end = $end;
794 $last = false;
795 $next = true;
796 if ( $next ) {
797 $index_start = $index_start + $per_page;
798 $index_end = $per_page + ( $index_start - 1 );
799 }
800 if ( $index_end >= $total ) {
801 $index_end = $total;
802 $last = true;
803 }
804 $json_data = [
805 'raw_data' => $raw_data,
806 'raw_key' => $raw_key,
807 'next' => $next,
808 'start' => $index_start,
809 'end' => $index_end,
810 'last' => $last,
811 ];
812 }
813
814 $url = give_import_page_url(
815 [
816 'step' => '4',
817 'importer-type' => 'import_donations',
818 'csv' => $output['csv'],
819 'total' => $total,
820 'delete_csv' => $import_setting['delete_csv'],
821 'success' => ( isset( $json_data['success'] ) ? $json_data['success'] : '' ),
822 'dry_run' => $output['dry_run'],
823 '_wpnonce' => wp_create_nonce( 'give_donation_import_success' ),
824 ]
825 );
826 $json_data['url'] = $url;
827
828 $current ++;
829 $json_data['current'] = $current;
830
831 $percentage = ( 100 / ( $total_ajax + 1 ) ) * $current;
832 $json_data['percentage'] = $percentage;
833
834 // Enable Give cache
835 Give_Cache::get_instance()->enable();
836
837 $json_data = apply_filters( 'give_import_ajax_responces', $json_data, $fields );
838 wp_die( json_encode( $json_data ) );
839 }
840
841 add_action( 'wp_ajax_give_donation_import', 'give_donation_import_callback' );
842
843 /**
844 * Load subscription import ajax callback
845 *
846 * @since 4.11.0
847 */
848 function give_subscription_import_callback() {
849
850 check_ajax_referer('give_subscription_import');
851
852 if ( ! current_user_can( 'manage_give_settings' ) ) {
853 give_die();
854 }
855
856 // Disable Give cache
857 Give_Cache::get_instance()->disable();
858
859 $import_setting = [];
860 $fields = isset( $_POST['fields'] ) ? $_POST['fields'] : null;
861
862 parse_str( $fields, $output );
863
864 $import_setting['mode'] = $output['mode'];
865 $import_setting['create_user'] = isset($output['create_user']) ? $output['create_user'] : '0';
866 $import_setting['delimiter'] = $output['delimiter'];
867 $import_setting['csv'] = $output['csv'];
868 $import_setting['delete_csv'] = $output['delete_csv'];
869 $import_setting['dry_run'] = $output['dry_run'];
870
871 $main_key = give_maybe_safe_unserialize($output['main_key']);
872
873 $current = absint( $_REQUEST['current'] );
874 $total_ajax = absint( $_REQUEST['total_ajax'] );
875 $start = absint( $_REQUEST['start'] );
876 $end = absint( $_REQUEST['end'] );
877 $next = absint( $_REQUEST['next'] );
878 $total = absint( $_REQUEST['total'] );
879 $per_page = absint( $_REQUEST['per_page'] );
880 $delimiter = empty( $output['delimiter'] ) ? ',' : $output['delimiter'];
881
882 // Ensure importer class is loaded for admin-ajax context
883 if ( ! class_exists( 'Give_Import_Subscriptions' ) ) {
884 require_once GIVE_PLUGIN_DIR . 'includes/admin/tools/import/class-give-import-subscriptions.php';
885 }
886
887 $importer = \Give_Import_Subscriptions::get_instance();
888
889 // Processing
890 $raw_data = $importer->get_subscription_data_from_csv( $output['csv'], $start, $end, $delimiter );
891 $raw_key = give_maybe_safe_unserialize($output['mapto']);
892 $import_setting['raw_key'] = $raw_key;
893
894 $current_key = $start;
895 foreach ( $raw_data as $row_data ) {
896 $import_setting['row_key'] = $current_key;
897 $result = $importer->import_row( $raw_key, $row_data, $main_key, $import_setting );
898 if ( is_string( $result ) && ! empty( $result ) ) {
899 if ( empty( $json_data['errors'] ) ) {
900 $json_data['errors'] = [];
901 }
902 $json_data['errors'][] = sprintf( __( 'Row %1$d: %2$s', 'give' ), $current_key, $result );
903 }
904 $current_key ++;
905 }
906
907 if ( $next == false ) {
908 $json_data = [
909 'success' => true,
910 'message' => __( 'All subscriptions uploaded successfully!', 'give' ),
911 ];
912 } else {
913 $index_start = $start;
914 $index_end = $end;
915 $last = false;
916 $next = true;
917 if ( $next ) {
918 $index_start = $index_start + $per_page;
919 $index_end = $per_page + ( $index_start - 1 );
920 }
921 if ( $index_end >= $total ) {
922 $index_end = $total;
923 $last = true;
924 }
925 $json_data = [
926 'raw_data' => $raw_data,
927 'raw_key' => $raw_key,
928 'next' => $next,
929 'start' => $index_start,
930 'end' => $index_end,
931 'last' => $last,
932 ];
933 }
934
935 $url = give_import_page_url(
936 [
937 'step' => '4',
938 'importer-type' => 'import_subscriptions',
939 'csv' => $output['csv'],
940 'total' => $total,
941 'delete_csv' => $import_setting['delete_csv'],
942 'success' => ( isset( $json_data['success'] ) ? $json_data['success'] : '' ),
943 'dry_run' => $output['dry_run'],
944 '_wpnonce' => wp_create_nonce( 'give_subscription_import_success' ),
945 ]
946 );
947 $json_data['url'] = $url;
948
949 $current ++;
950 $json_data['current'] = $current;
951
952 $percentage = ( 100 / ( $total_ajax + 1 ) ) * $current;
953 $json_data['percentage'] = $percentage;
954
955 // Enable Give cache
956 Give_Cache::get_instance()->enable();
957
958 $json_data = apply_filters( 'give_import_ajax_responces', $json_data, $fields );
959 wp_die( json_encode( $json_data ) );
960 }
961
962 add_action( 'wp_ajax_give_subscription_import', 'give_subscription_import_callback' );
963
964 /**
965 * Load core settings import ajax callback
966 * Fire when importing from JSON start
967 *
968 * @since 1.8.17
969 */
970
971 function give_core_settings_import_callback() {
972 check_ajax_referer( 'give_core_settings_import' );
973
974 // Bailout.
975 if ( ! current_user_can( 'manage_give_settings' ) ) {
976 give_die();
977 }
978
979 $fields = isset( $_POST['fields'] ) ? $_POST['fields'] : null;
980 parse_str( $fields, $fields );
981
982 $json_data['success'] = false;
983
984 /**
985 * Filter to Modify fields that are being pass by the ajax before importing of the core setting start.
986 *
987 * @access public
988 *
989 * @since 1.8.17
990 *
991 * @param array $fields
992 *
993 * @return array $fields
994 */
995 $fields = (array) apply_filters( 'give_import_core_settings_fields', $fields );
996
997 $file_name = ( ! empty( $fields['file_name'] ) ? give_clean( $fields['file_name'] ) : false );
998
999 if ( ! empty( $file_name ) ) {
1000 $type = ( ! empty( $fields['type'] ) ? give_clean( $fields['type'] ) : 'merge' );
1001
1002 // Get the json data from the file and then alter it in array format
1003 $json_string = give_get_core_settings_json( $file_name );
1004 $json_to_array = json_decode( $json_string, true );
1005
1006 // get the current setting from the options table.
1007 $host_give_options = Give_Cache_Setting::get_settings();
1008
1009 // Save old settins for backup.
1010 update_option( 'give_settings_old', $host_give_options, false );
1011
1012 /**
1013 * Filter to Modify Core Settings that are being going to get import in options table as give settings.
1014 *
1015 * @access public
1016 *
1017 * @since 1.8.17
1018 *
1019 * @param array $type Type of Import
1020 * @param array $host_give_options Setting old setting that used to be in the options table.
1021 * @param array $fields Data that is being send from the ajax
1022 *
1023 * @param array $json_to_array Setting that are being going to get imported
1024 *
1025 * @return array $json_to_array Setting that are being going to get imported
1026 */
1027 $json_to_array = (array) apply_filters( 'give_import_core_settings_data', $json_to_array, $type, $host_give_options, $fields );
1028
1029 update_option( 'give_settings', $json_to_array, false );
1030
1031 $json_data['success'] = true;
1032 }
1033
1034 $json_data['percentage'] = 100;
1035
1036 /**
1037 * Filter to Modify core import setting page url
1038 *
1039 * @access public
1040 *
1041 * @since 1.8.17
1042 * @return array $url
1043 */
1044 $json_data['url'] = give_import_page_url(
1045 (array) apply_filters(
1046 'give_import_core_settings_success_url',
1047 [
1048 'step' => ( empty( $json_data['success'] ) ? '1' : '3' ),
1049 'importer-type' => 'import_core_setting',
1050 'success' => ( empty( $json_data['success'] ) ? '0' : '1' ),
1051 ]
1052 )
1053 );
1054
1055 wp_send_json( $json_data );
1056 }
1057
1058 add_action( 'wp_ajax_give_core_settings_import', 'give_core_settings_import_callback' );
1059
1060 /**
1061 * Initializes blank slate content if a list table is empty.
1062 *
1063 * @since 1.8.13
1064 */
1065 function give_blank_slate() {
1066 $blank_slate = new Give_Blank_Slate();
1067 $blank_slate->init();
1068 }
1069
1070 add_action( 'current_screen', 'give_blank_slate' );
1071
1072 /**
1073 * Validate Fields of User Profile
1074 *
1075 * @since 2.0
1076 *
1077 * @param int|bool $update True or False.
1078 * @param object $user WP User Data.
1079 *
1080 * @param object $errors Object of WP Errors.
1081 *
1082 * @return mixed
1083 */
1084 function give_validate_user_profile( $errors, $update, $user ) {
1085
1086 if ( ! empty( $_POST['action'] ) && ( 'adduser' === $_POST['action'] || 'createuser' === $_POST['action'] ) ) {
1087 return;
1088 }
1089
1090 if ( ! empty( $user->ID ) ) {
1091 $donor = Give()->donors->get_donor_by( 'user_id', $user->ID );
1092
1093 if ( $donor ) {
1094 // If Donor is attached with User, then validate first name.
1095 if ( empty( $_POST['first_name'] ) ) {
1096 $errors->add(
1097 'empty_first_name',
1098 sprintf(
1099 '<strong>%1$s:</strong> %2$s',
1100 __( 'ERROR', 'give' ),
1101 __( 'Please enter your first name.', 'give' )
1102 )
1103 );
1104 }
1105 }
1106 }
1107
1108 }
1109
1110 add_action( 'user_profile_update_errors', 'give_validate_user_profile', 10, 3 );
1111
1112 /**
1113 * Show Donor Information on User Profile Page.
1114 *
1115 * @since 2.0
1116 *
1117 * @param object $user User Object.
1118 *
1119 */
1120 function give_donor_information_profile_fields( $user ) {
1121 $donor = Give()->donors->get_donor_by( 'user_id', $user->ID );
1122
1123 // Display Donor Information, only if donor is attached with User.
1124 if ( ! empty( $donor->user_id ) ) :
1125 ?>
1126 <tr>
1127 <th scope="row"><?php _e( 'Donor', 'give' ); ?></th>
1128 <td>
1129 <a href="<?php echo admin_url( 'edit.php?post_type=give_forms&page=give-donors&view=overview&id=' . $donor->id ); ?>">
1130 <?php _e( 'View Donor Information', 'give' ); ?>
1131 </a>
1132 </td>
1133 </tr>
1134 <?php
1135 endif;
1136 }
1137
1138 add_action( 'personal_options', 'give_donor_information_profile_fields' );
1139 /**
1140 * Get Array of WP User Roles.
1141 *
1142 * @since 1.8.13
1143 * @return array
1144 */
1145 function give_get_user_roles() {
1146 $user_roles = [];
1147
1148 // Loop through User Roles.
1149 foreach ( get_editable_roles() as $role_name => $role_info ) :
1150 $user_roles[ $role_name ] = $role_info['name'];
1151 endforeach;
1152
1153 return $user_roles;
1154 }
1155
1156
1157 /**
1158 * Get user roles that are safe for donor registration.
1159 *
1160 * This excludes privileged roles like administrator, editor, give_accountant, etc.
1161 * to prevent security issues if the default donor role setting is misconfigured.
1162 * Only basic subscriber-level roles should be available for donor registration.
1163 *
1164 * @since 4.14.0
1165 * @return array
1166 */
1167 function give_get_donor_safe_user_roles() {
1168 $user_roles = [];
1169
1170 // Capabilities that indicate a privileged role - exclude these
1171 $privileged_caps = [
1172 // WordPress privileged caps
1173 'manage_options',
1174 'edit_users',
1175 'delete_users',
1176 'create_users',
1177 'edit_others_posts',
1178 'delete_others_posts',
1179 'edit_pages',
1180 'edit_others_pages',
1181 'publish_pages',
1182 'delete_pages',
1183 'edit_posts',
1184 // GiveWP privileged caps - access to sensitive donor/payment data
1185 'view_give_reports',
1186 'export_give_reports',
1187 'manage_give_settings',
1188 'view_give_sensitive_data',
1189 'edit_give_payments',
1190 'edit_give_forms',
1191 ];
1192
1193 foreach ( get_editable_roles() as $role_name => $role_info ) {
1194 $is_privileged = false;
1195
1196 // Check if role has any privileged capabilities
1197 foreach ( $privileged_caps as $cap ) {
1198 if ( ! empty( $role_info['capabilities'][ $cap ] ) ) {
1199 $is_privileged = true;
1200 break;
1201 }
1202 }
1203
1204 // Only include non-privileged roles
1205 if ( ! $is_privileged ) {
1206 $user_roles[ $role_name ] = $role_info['name'];
1207 }
1208 }
1209
1210 return $user_roles;
1211 }
1212
1213 /**
1214 * Ajax handle for donor address.
1215 *
1216 * @since 2.0
1217 * @since 2.11.0 decode url before parsing and sanitizing url when set $post.
1218 * @since 4.9.0 rename function - PHP 8 compatibility
1219 * @return void
1220 */
1221 function give_ajax_donor_manage_addresses() {
1222 // Bailout.
1223 if (
1224 empty( $_POST['form'] ) ||
1225 empty( $_POST['donorID'] )
1226 ) {
1227 wp_send_json_error(
1228 [
1229 'error' => 1,
1230 ]
1231 );
1232 }
1233
1234 $post = give_clean( wp_parse_args( urldecode_deep( $_POST ) ) );
1235 $donorID = absint( $post['donorID'] );
1236 $form_data = give_clean( wp_parse_args( $post['form'] ) );
1237 $is_multi_address_type = ( 'billing' === $form_data['address-id'] || false !== strpos( $form_data['address-id'], '_' ) );
1238 $exploded_address_id = explode( '_', $form_data['address-id'] );
1239 $address_type = false !== strpos( $form_data['address-id'], '_' ) ?
1240 array_shift( $exploded_address_id ) :
1241 $form_data['address-id'];
1242 $address_id = false !== strpos( $form_data['address-id'], '_' ) ?
1243 array_pop( $exploded_address_id ) :
1244 null;
1245 $response_data = [
1246 'action' => $form_data['address-action'],
1247 'id' => $form_data['address-id'],
1248 ];
1249
1250 // Security check.
1251 if ( ! wp_verify_nonce( $form_data['_wpnonce'], 'give-manage-donor-addresses' ) ) {
1252 wp_send_json_error(
1253 [
1254 'error' => 1,
1255 'error_msg' => wp_sprintf(
1256 '<div class="notice notice-error"><p>%s</p></div>',
1257 __( 'Error: Security issue.', 'give' )
1258 ),
1259 ]
1260 );
1261 }
1262
1263 $donor = new Give_Donor( $donorID );
1264
1265 // Verify donor.
1266 if ( ! $donor->id ) {
1267 wp_send_json_error(
1268 [
1269 'error' => 3,
1270 ]
1271 );
1272 }
1273
1274 // Unset all data except address.
1275 unset(
1276 $form_data['_wpnonce'],
1277 $form_data['address-action'],
1278 $form_data['address-id']
1279 );
1280
1281 // Process action.
1282 switch ( $response_data['action'] ) {
1283
1284 case 'add':
1285 if ( ! $donor->add_address( "{$address_type}[]", $form_data ) ) {
1286 wp_send_json_error(
1287 [
1288 'error' => 1,
1289 'error_msg' => wp_sprintf(
1290 '<div class="notice notice-error"><p>%s</p></div>',
1291 __( 'Error: Unable to save the address. Please check if address already exist.', 'give' )
1292 ),
1293 ]
1294 );
1295 }
1296
1297 $total_addresses = count( $donor->address[ $address_type ] );
1298
1299 $address_index = $is_multi_address_type ?
1300 $total_addresses - 1 :
1301 $address_type;
1302
1303 $array_keys = array_keys( $donor->address[ $address_type ] );
1304
1305 $address_id = $is_multi_address_type ?
1306 end( $array_keys ) :
1307 $address_type;
1308
1309 $response_data['address_html'] = give_get_format_address(
1310 end( $donor->address['billing'] ),
1311 [
1312 // We can add only billing address from donor screen.
1313 'type' => 'billing',
1314 'id' => $address_id,
1315 'index' => ++ $address_index,
1316 ]
1317 );
1318 $response_data['success_msg'] = wp_sprintf(
1319 '<div class="notice updated"><p>%s</p></div>',
1320 __( 'Successfully added a new address to the donor.', 'give' )
1321 );
1322
1323 if ( $is_multi_address_type ) {
1324 $response_data['id'] = "{$response_data['id']}_{$address_index}";
1325 }
1326
1327 break;
1328
1329 case 'remove':
1330 if ( ! $donor->remove_address( $response_data['id'] ) ) {
1331 wp_send_json_error(
1332 [
1333 'error' => 2,
1334 'error_msg' => wp_sprintf(
1335 '<div class="notice notice-error"><p>%s</p></div>',
1336 __( 'Error: Unable to delete address.', 'give' )
1337 ),
1338 ]
1339 );
1340 }
1341
1342 $response_data['success_msg'] = wp_sprintf(
1343 '<div class="notice updated"><p>%s</p></div>',
1344 __( 'Successfully removed a address of donor.', 'give' )
1345 );
1346
1347 break;
1348
1349 case 'update':
1350 if ( ! $donor->update_address( $response_data['id'], $form_data ) ) {
1351 wp_send_json_error(
1352 [
1353 'error' => 3,
1354 'error_msg' => wp_sprintf(
1355 '<div class="notice notice-error"><p>%s</p></div>',
1356 __( 'Error: Unable to update address. Please check if address already exist.', 'give' )
1357 ),
1358 ]
1359 );
1360 }
1361
1362 $response_data['address_html'] = give_get_format_address(
1363 $is_multi_address_type ?
1364 $donor->address[ $address_type ][ $address_id ] :
1365 $donor->address[ $address_type ],
1366 [
1367 'type' => $address_type,
1368 'id' => $address_id,
1369 'index' => $address_id,
1370 ]
1371 );
1372 $response_data['success_msg'] = wp_sprintf(
1373 '<div class="notice updated"><p>%s</p></div>',
1374 __( 'Successfully updated a address of donor', 'give' )
1375 );
1376
1377 break;
1378 }// End switch().
1379
1380 wp_send_json_success( $response_data );
1381 }
1382
1383 add_action( 'wp_ajax_donor_manage_addresses', 'give_ajax_donor_manage_addresses');
1384
1385 /**
1386 * Admin donor billing address label
1387 *
1388 * @since 4.9.0 rename function - PHP 8 compatibility
1389 * @since 2.0
1390 *
1391 * @param string $address_label
1392 *
1393 * @return string
1394 */
1395 function give_donor_billing_address_label( $address_label ) {
1396 $address_label = __( 'Billing Address', 'give' );
1397
1398 return $address_label;
1399 }
1400
1401 add_action( 'give_donor_billing_address_label', 'give_donor_billing_address_label');
1402
1403 /**
1404 * Admin donor personal address label
1405 *
1406 * @since 4.9.0 rename function - PHP 8 compatibility
1407 * @since 2.0
1408 *
1409 * @param string $address_label
1410 *
1411 * @return string
1412 */
1413 function give_donor_personal_address_label( $address_label ) {
1414 $address_label = __( 'Personal Address', 'give' );
1415
1416 return $address_label;
1417 }
1418
1419 add_action( 'give_donor_personal_address_label', 'give_donor_personal_address_label');
1420
1421 /**
1422 * Update Donor Information when User Profile is updated from admin.
1423 * Note: for internal use only.
1424 *
1425 * @since 2.0
1426 *
1427 * @param int $user_id
1428 *
1429 * @access public
1430 * @return bool
1431 */
1432 function give_update_donor_name_on_user_update( $user_id = 0 ) {
1433
1434 if ( current_user_can( 'edit_user', $user_id ) ) {
1435
1436 $donor = new Give_Donor( $user_id, true );
1437
1438 // Bailout, if donor doesn't exists.
1439 if ( ! $donor ) {
1440 return false;
1441 }
1442
1443 // Get User First name and Last name.
1444 $first_name = ( $_POST['first_name'] ) ? give_clean( $_POST['first_name'] ) : get_user_meta( $user_id, 'first_name', true );
1445 $last_name = ( $_POST['last_name'] ) ? give_clean( $_POST['last_name'] ) : get_user_meta( $user_id, 'last_name', true );
1446 $full_name = strip_tags( wp_unslash( trim( "{$first_name} {$last_name}" ) ) );
1447
1448 // Assign User First name and Last name to Donor.
1449 Give()->donors->update(
1450 $donor->id,
1451 [
1452 'name' => $full_name,
1453 ]
1454 );
1455 Give()->donor_meta->update_meta( $donor->id, '_give_donor_first_name', $first_name );
1456 Give()->donor_meta->update_meta( $donor->id, '_give_donor_last_name', $last_name );
1457
1458 }
1459 }
1460
1461 add_action( 'edit_user_profile_update', 'give_update_donor_name_on_user_update', 10 );
1462 add_action( 'personal_options_update', 'give_update_donor_name_on_user_update', 10 );
1463
1464
1465 /**
1466 * Updates the email address of a donor record when the email on a user is updated
1467 * Note: for internal use only.
1468 *
1469 * @since 1.4.3
1470 * @access public
1471 *
1472 * @param WP_User|bool $old_user_data User data.
1473 *
1474 * @param int $user_id User ID.
1475 *
1476 * @return bool
1477 */
1478 function give_update_donor_email_on_user_update( $user_id = 0, $old_user_data = false ) {
1479
1480 $donor = new Give_Donor( $user_id, true );
1481
1482 if ( ! $donor ) {
1483 return false;
1484 }
1485
1486 $user = get_userdata( $user_id );
1487
1488 if ( ! empty( $user ) && $user->user_email !== $donor->email ) {
1489
1490 $success = Give()->donors->update(
1491 $donor->id,
1492 [
1493 'email' => $user->user_email,
1494 ]
1495 );
1496
1497 if ( $success ) {
1498 // Update some payment meta if we need to
1499 $payments_array = explode( ',', $donor->payment_ids );
1500
1501 if ( ! empty( $payments_array ) ) {
1502
1503 foreach ( $payments_array as $payment_id ) {
1504
1505 give_update_payment_meta( $payment_id, 'email', $user->user_email );
1506
1507 }
1508 }
1509
1510 /**
1511 * Fires after updating donor email on user update.
1512 *
1513 * @since 1.4.3
1514 *
1515 * @param Give_Donor $donor Give donor object.
1516 *
1517 * @param WP_User $user WordPress User object.
1518 */
1519 do_action( 'give_update_donor_email_on_user_update', $user, $donor );
1520
1521 }
1522 }
1523
1524 }
1525
1526 add_action( 'profile_update', 'give_update_donor_email_on_user_update', 10, 2 );
1527
1528
1529 /**
1530 * Flushes Give's cache.
1531 */
1532 function give_cache_flush() {
1533 if (!is_user_logged_in() || !current_user_can('manage_give_settings')) {
1534 wp_die();
1535 }
1536
1537 /**
1538 * @since 2.25.2 add nonce check
1539 */
1540 check_ajax_referer('give_cache_flush');
1541
1542 $result = Give_Cache::flush_cache();
1543
1544 if ($result) {
1545 wp_send_json_success(
1546 [
1547 'message' => __('Cache flushed successfully.', 'give'),
1548 ]
1549 );
1550 } else {
1551 wp_send_json_error(
1552 [
1553 'message' => __('An error occurred while flushing the cache.', 'give'),
1554 ]
1555 );
1556 }
1557 }
1558
1559 add_action( 'wp_ajax_give_cache_flush', 'give_cache_flush', 10, 0 );
1560
1561
1562 /**
1563 * Log give addon activation time
1564 *
1565 * @since 2.5.0
1566 *
1567 * @param $network_wide
1568 *
1569 * @param $plugin
1570 */
1571 function give_log_addon_activation_time( $plugin, $network_wide ) {
1572 if ( $network_wide ) {
1573 return;
1574 }
1575
1576 $plugin_data = give_get_plugins( [ 'only_premium_add_ons' => true ] );
1577 $plugin_data = ! empty( $plugin_data[ $plugin ] ) ? $plugin_data[ $plugin ] : [];
1578
1579 if ( $plugin_data ) {
1580 update_option( 'give_addon_last_activated', current_time( 'timestamp' ), 'no' );
1581 }
1582 }
1583
1584 add_action( 'activate_plugin', 'give_log_addon_activation_time', 10, 2 );
1585
1586
1587 /**
1588 * Hide all admin notice from add-ons page
1589 *
1590 * Note: only for internal use
1591 *
1592 * @since 2.5.0
1593 */
1594 function give_hide_notices_on_add_ons_page() {
1595 $page = ! empty( $_GET['page'] ) ? give_clean( $_GET['page'] ) : '';
1596
1597 // Bailout.
1598 if ( 'give-addons' !== $page ) {
1599 return;
1600 }
1601
1602 remove_all_actions( 'admin_notices' );
1603 }
1604
1605 add_action( 'in_admin_header', 'give_hide_notices_on_add_ons_page', 999 );
1606
1607
1608 /**
1609 * Admin JS
1610 *
1611 * @since 2.5.0
1612 */
1613 function give_admin_quick_js() {
1614 if ( is_multisite() && is_blog_admin() ) {
1615 ?>
1616 <script>
1617 jQuery(document).ready(function ($) {
1618 var $updateNotices = $('[id$="-update"] ', '.wp-list-table');
1619
1620 if ($updateNotices.length) {
1621 $.each($updateNotices, function (index, $updateNotice) {
1622 $updateNotice = $($updateNotice);
1623 $updateNotice.prev().addClass('update');
1624 });
1625 }
1626 });
1627 </script>
1628 <?php
1629 }
1630 }
1631
1632 add_action( 'admin_head', 'give_admin_quick_js' );
1633
1634 /**
1635 * Add Admin addon menu related scripts
1636 *
1637 * @since 2.6.0
1638 */
1639 function give_admin_addon_menu_inline_scripts() {
1640 ?>
1641 <script>
1642 (function ($) {
1643 const $addonLink = $('#menu-posts-give_forms a[href^="edit.php?post_type=give_forms&page=give-add-ons"]');
1644 <?php if ( empty( give_get_plugins( [ 'only_premium_add_ons' => true ] ) ) ) : ?>
1645 $addonLink.addClass('give-highlight');
1646 $addonLink.prepend('<span class="dashicons dashicons-star-filled"></span>');
1647 <?php endif; ?>
1648 })(jQuery)
1649 </script>
1650 <style>
1651 #menu-posts-give_forms a[href^="edit.php?post_type=give_forms&page=give-add-ons"].give-highlight {
1652 color: rgb(43, 194, 83);
1653 font-weight: 700;
1654 vertical-align: top;
1655 text-shadow: 0 1px 2px #00000080;
1656 }
1657
1658 #menu-posts-give_forms a[href^="edit.php?post_type=give_forms&page=give-add-ons"].give-highlight span.dashicons {
1659 font-size: 14px !important;
1660 width: auto;
1661 height: 18px;
1662 padding-right: 3px;
1663 vertical-align: middle;
1664 }
1665 </style>
1666 <?php
1667 }
1668
1669 add_action( 'admin_footer', 'give_admin_addon_menu_inline_scripts' );
1670
1671 /**
1672 * Handle akismet_deblacklist_spammed_email_handler give-action
1673 *
1674 * @since 2.5.14
1675 *
1676 * @param array $get
1677 *
1678 */
1679 function give_akismet_deblacklist_spammed_email_handler( $get ) {
1680 $email = ! empty( $get['email'] ) && is_email( $get['email'] ) ? give_clean( $get['email'] ) : '';
1681 $log = ! empty( $get['log'] ) ? absint( $get['log'] ) : '';
1682 $action = "give_akismet_deblacklist_spammed_email_{$email}";
1683
1684 check_admin_referer( $action );
1685 $emails = give_akismet_get_whitelisted_emails();
1686
1687 if ( ! in_array( $email, $emails, true ) ) {
1688 array_unshift( $emails, $email );
1689
1690 give_update_option( 'akismet_whitelisted_email_addresses', $emails );
1691
1692 // Redirect to Akismet setting page.
1693 wp_safe_redirect( 'wp-admin/edit.php?post_type=give_forms&page=give-settings&tab=advanced&section=akismet-spam-protection&give-message=akismet-deblacklisted-email' );
1694 }
1695 }
1696
1697 add_action( 'give_akismet_deblacklist_spammed_email', 'give_akismet_deblacklist_spammed_email_handler' );
1698
1699 /**
1700 * Add Custom setting view for form them setting panel
1701 *
1702 * @since 2.7.0
1703 */
1704 function give_render_form_theme_setting_panel() {
1705 require_once GIVE_PLUGIN_DIR . 'src/Views/Admin/Form/Metabox-Settings.php';
1706 }
1707
1708 add_action( 'give_post_form_template_options_settings', 'give_render_form_theme_setting_panel' );
1709
1710 /**
1711 * Add Custom setting view for form grid setting panel
1712 *
1713 * @since 2.20.0
1714 */
1715 function give_render_form_grid_setting_panel()
1716 {
1717 require_once GIVE_PLUGIN_DIR . 'src/Views/Admin/Form/FormGrid-Settings.php';
1718 }
1719
1720 add_action('give_post_form_grid_options_settings', 'give_render_form_grid_setting_panel');
1721
1722