PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.15.2
GiveWP – Donation Plugin and Fundraising Platform v4.15.2
4.18.0 4.17.0 4.16.9 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 All 257 releases
give / includes / admin / admin-actions.php

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

1,720 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 // Bailout.
973 if ( ! current_user_can( 'manage_give_settings' ) ) {
974 give_die();
975 }
976
977 $fields = isset( $_POST['fields'] ) ? $_POST['fields'] : null;
978 parse_str( $fields, $fields );
979
980 $json_data['success'] = false;
981
982 /**
983 * Filter to Modify fields that are being pass by the ajax before importing of the core setting start.
984 *
985 * @access public
986 *
987 * @since 1.8.17
988 *
989 * @param array $fields
990 *
991 * @return array $fields
992 */
993 $fields = (array) apply_filters( 'give_import_core_settings_fields', $fields );
994
995 $file_name = ( ! empty( $fields['file_name'] ) ? give_clean( $fields['file_name'] ) : false );
996
997 if ( ! empty( $file_name ) ) {
998 $type = ( ! empty( $fields['type'] ) ? give_clean( $fields['type'] ) : 'merge' );
999
1000 // Get the json data from the file and then alter it in array format
1001 $json_string = give_get_core_settings_json( $file_name );
1002 $json_to_array = json_decode( $json_string, true );
1003
1004 // get the current setting from the options table.
1005 $host_give_options = Give_Cache_Setting::get_settings();
1006
1007 // Save old settins for backup.
1008 update_option( 'give_settings_old', $host_give_options, false );
1009
1010 /**
1011 * Filter to Modify Core Settings that are being going to get import in options table as give settings.
1012 *
1013 * @access public
1014 *
1015 * @since 1.8.17
1016 *
1017 * @param array $type Type of Import
1018 * @param array $host_give_options Setting old setting that used to be in the options table.
1019 * @param array $fields Data that is being send from the ajax
1020 *
1021 * @param array $json_to_array Setting that are being going to get imported
1022 *
1023 * @return array $json_to_array Setting that are being going to get imported
1024 */
1025 $json_to_array = (array) apply_filters( 'give_import_core_settings_data', $json_to_array, $type, $host_give_options, $fields );
1026
1027 update_option( 'give_settings', $json_to_array, false );
1028
1029 $json_data['success'] = true;
1030 }
1031
1032 $json_data['percentage'] = 100;
1033
1034 /**
1035 * Filter to Modify core import setting page url
1036 *
1037 * @access public
1038 *
1039 * @since 1.8.17
1040 * @return array $url
1041 */
1042 $json_data['url'] = give_import_page_url(
1043 (array) apply_filters(
1044 'give_import_core_settings_success_url',
1045 [
1046 'step' => ( empty( $json_data['success'] ) ? '1' : '3' ),
1047 'importer-type' => 'import_core_setting',
1048 'success' => ( empty( $json_data['success'] ) ? '0' : '1' ),
1049 ]
1050 )
1051 );
1052
1053 wp_send_json( $json_data );
1054 }
1055
1056 add_action( 'wp_ajax_give_core_settings_import', 'give_core_settings_import_callback' );
1057
1058 /**
1059 * Initializes blank slate content if a list table is empty.
1060 *
1061 * @since 1.8.13
1062 */
1063 function give_blank_slate() {
1064 $blank_slate = new Give_Blank_Slate();
1065 $blank_slate->init();
1066 }
1067
1068 add_action( 'current_screen', 'give_blank_slate' );
1069
1070 /**
1071 * Validate Fields of User Profile
1072 *
1073 * @since 2.0
1074 *
1075 * @param int|bool $update True or False.
1076 * @param object $user WP User Data.
1077 *
1078 * @param object $errors Object of WP Errors.
1079 *
1080 * @return mixed
1081 */
1082 function give_validate_user_profile( $errors, $update, $user ) {
1083
1084 if ( ! empty( $_POST['action'] ) && ( 'adduser' === $_POST['action'] || 'createuser' === $_POST['action'] ) ) {
1085 return;
1086 }
1087
1088 if ( ! empty( $user->ID ) ) {
1089 $donor = Give()->donors->get_donor_by( 'user_id', $user->ID );
1090
1091 if ( $donor ) {
1092 // If Donor is attached with User, then validate first name.
1093 if ( empty( $_POST['first_name'] ) ) {
1094 $errors->add(
1095 'empty_first_name',
1096 sprintf(
1097 '<strong>%1$s:</strong> %2$s',
1098 __( 'ERROR', 'give' ),
1099 __( 'Please enter your first name.', 'give' )
1100 )
1101 );
1102 }
1103 }
1104 }
1105
1106 }
1107
1108 add_action( 'user_profile_update_errors', 'give_validate_user_profile', 10, 3 );
1109
1110 /**
1111 * Show Donor Information on User Profile Page.
1112 *
1113 * @since 2.0
1114 *
1115 * @param object $user User Object.
1116 *
1117 */
1118 function give_donor_information_profile_fields( $user ) {
1119 $donor = Give()->donors->get_donor_by( 'user_id', $user->ID );
1120
1121 // Display Donor Information, only if donor is attached with User.
1122 if ( ! empty( $donor->user_id ) ) :
1123 ?>
1124 <tr>
1125 <th scope="row"><?php _e( 'Donor', 'give' ); ?></th>
1126 <td>
1127 <a href="<?php echo admin_url( 'edit.php?post_type=give_forms&page=give-donors&view=overview&id=' . $donor->id ); ?>">
1128 <?php _e( 'View Donor Information', 'give' ); ?>
1129 </a>
1130 </td>
1131 </tr>
1132 <?php
1133 endif;
1134 }
1135
1136 add_action( 'personal_options', 'give_donor_information_profile_fields' );
1137 /**
1138 * Get Array of WP User Roles.
1139 *
1140 * @since 1.8.13
1141 * @return array
1142 */
1143 function give_get_user_roles() {
1144 $user_roles = [];
1145
1146 // Loop through User Roles.
1147 foreach ( get_editable_roles() as $role_name => $role_info ) :
1148 $user_roles[ $role_name ] = $role_info['name'];
1149 endforeach;
1150
1151 return $user_roles;
1152 }
1153
1154
1155 /**
1156 * Get user roles that are safe for donor registration.
1157 *
1158 * This excludes privileged roles like administrator, editor, give_accountant, etc.
1159 * to prevent security issues if the default donor role setting is misconfigured.
1160 * Only basic subscriber-level roles should be available for donor registration.
1161 *
1162 * @since 4.14.0
1163 * @return array
1164 */
1165 function give_get_donor_safe_user_roles() {
1166 $user_roles = [];
1167
1168 // Capabilities that indicate a privileged role - exclude these
1169 $privileged_caps = [
1170 // WordPress privileged caps
1171 'manage_options',
1172 'edit_users',
1173 'delete_users',
1174 'create_users',
1175 'edit_others_posts',
1176 'delete_others_posts',
1177 'edit_pages',
1178 'edit_others_pages',
1179 'publish_pages',
1180 'delete_pages',
1181 'edit_posts',
1182 // GiveWP privileged caps - access to sensitive donor/payment data
1183 'view_give_reports',
1184 'export_give_reports',
1185 'manage_give_settings',
1186 'view_give_sensitive_data',
1187 'edit_give_payments',
1188 'edit_give_forms',
1189 ];
1190
1191 foreach ( get_editable_roles() as $role_name => $role_info ) {
1192 $is_privileged = false;
1193
1194 // Check if role has any privileged capabilities
1195 foreach ( $privileged_caps as $cap ) {
1196 if ( ! empty( $role_info['capabilities'][ $cap ] ) ) {
1197 $is_privileged = true;
1198 break;
1199 }
1200 }
1201
1202 // Only include non-privileged roles
1203 if ( ! $is_privileged ) {
1204 $user_roles[ $role_name ] = $role_info['name'];
1205 }
1206 }
1207
1208 return $user_roles;
1209 }
1210
1211 /**
1212 * Ajax handle for donor address.
1213 *
1214 * @since 2.0
1215 * @since 2.11.0 decode url before parsing and sanitizing url when set $post.
1216 * @since 4.9.0 rename function - PHP 8 compatibility
1217 * @return void
1218 */
1219 function give_ajax_donor_manage_addresses() {
1220 // Bailout.
1221 if (
1222 empty( $_POST['form'] ) ||
1223 empty( $_POST['donorID'] )
1224 ) {
1225 wp_send_json_error(
1226 [
1227 'error' => 1,
1228 ]
1229 );
1230 }
1231
1232 $post = give_clean( wp_parse_args( urldecode_deep( $_POST ) ) );
1233 $donorID = absint( $post['donorID'] );
1234 $form_data = give_clean( wp_parse_args( $post['form'] ) );
1235 $is_multi_address_type = ( 'billing' === $form_data['address-id'] || false !== strpos( $form_data['address-id'], '_' ) );
1236 $exploded_address_id = explode( '_', $form_data['address-id'] );
1237 $address_type = false !== strpos( $form_data['address-id'], '_' ) ?
1238 array_shift( $exploded_address_id ) :
1239 $form_data['address-id'];
1240 $address_id = false !== strpos( $form_data['address-id'], '_' ) ?
1241 array_pop( $exploded_address_id ) :
1242 null;
1243 $response_data = [
1244 'action' => $form_data['address-action'],
1245 'id' => $form_data['address-id'],
1246 ];
1247
1248 // Security check.
1249 if ( ! wp_verify_nonce( $form_data['_wpnonce'], 'give-manage-donor-addresses' ) ) {
1250 wp_send_json_error(
1251 [
1252 'error' => 1,
1253 'error_msg' => wp_sprintf(
1254 '<div class="notice notice-error"><p>%s</p></div>',
1255 __( 'Error: Security issue.', 'give' )
1256 ),
1257 ]
1258 );
1259 }
1260
1261 $donor = new Give_Donor( $donorID );
1262
1263 // Verify donor.
1264 if ( ! $donor->id ) {
1265 wp_send_json_error(
1266 [
1267 'error' => 3,
1268 ]
1269 );
1270 }
1271
1272 // Unset all data except address.
1273 unset(
1274 $form_data['_wpnonce'],
1275 $form_data['address-action'],
1276 $form_data['address-id']
1277 );
1278
1279 // Process action.
1280 switch ( $response_data['action'] ) {
1281
1282 case 'add':
1283 if ( ! $donor->add_address( "{$address_type}[]", $form_data ) ) {
1284 wp_send_json_error(
1285 [
1286 'error' => 1,
1287 'error_msg' => wp_sprintf(
1288 '<div class="notice notice-error"><p>%s</p></div>',
1289 __( 'Error: Unable to save the address. Please check if address already exist.', 'give' )
1290 ),
1291 ]
1292 );
1293 }
1294
1295 $total_addresses = count( $donor->address[ $address_type ] );
1296
1297 $address_index = $is_multi_address_type ?
1298 $total_addresses - 1 :
1299 $address_type;
1300
1301 $array_keys = array_keys( $donor->address[ $address_type ] );
1302
1303 $address_id = $is_multi_address_type ?
1304 end( $array_keys ) :
1305 $address_type;
1306
1307 $response_data['address_html'] = give_get_format_address(
1308 end( $donor->address['billing'] ),
1309 [
1310 // We can add only billing address from donor screen.
1311 'type' => 'billing',
1312 'id' => $address_id,
1313 'index' => ++ $address_index,
1314 ]
1315 );
1316 $response_data['success_msg'] = wp_sprintf(
1317 '<div class="notice updated"><p>%s</p></div>',
1318 __( 'Successfully added a new address to the donor.', 'give' )
1319 );
1320
1321 if ( $is_multi_address_type ) {
1322 $response_data['id'] = "{$response_data['id']}_{$address_index}";
1323 }
1324
1325 break;
1326
1327 case 'remove':
1328 if ( ! $donor->remove_address( $response_data['id'] ) ) {
1329 wp_send_json_error(
1330 [
1331 'error' => 2,
1332 'error_msg' => wp_sprintf(
1333 '<div class="notice notice-error"><p>%s</p></div>',
1334 __( 'Error: Unable to delete address.', 'give' )
1335 ),
1336 ]
1337 );
1338 }
1339
1340 $response_data['success_msg'] = wp_sprintf(
1341 '<div class="notice updated"><p>%s</p></div>',
1342 __( 'Successfully removed a address of donor.', 'give' )
1343 );
1344
1345 break;
1346
1347 case 'update':
1348 if ( ! $donor->update_address( $response_data['id'], $form_data ) ) {
1349 wp_send_json_error(
1350 [
1351 'error' => 3,
1352 'error_msg' => wp_sprintf(
1353 '<div class="notice notice-error"><p>%s</p></div>',
1354 __( 'Error: Unable to update address. Please check if address already exist.', 'give' )
1355 ),
1356 ]
1357 );
1358 }
1359
1360 $response_data['address_html'] = give_get_format_address(
1361 $is_multi_address_type ?
1362 $donor->address[ $address_type ][ $address_id ] :
1363 $donor->address[ $address_type ],
1364 [
1365 'type' => $address_type,
1366 'id' => $address_id,
1367 'index' => $address_id,
1368 ]
1369 );
1370 $response_data['success_msg'] = wp_sprintf(
1371 '<div class="notice updated"><p>%s</p></div>',
1372 __( 'Successfully updated a address of donor', 'give' )
1373 );
1374
1375 break;
1376 }// End switch().
1377
1378 wp_send_json_success( $response_data );
1379 }
1380
1381 add_action( 'wp_ajax_donor_manage_addresses', 'give_ajax_donor_manage_addresses');
1382
1383 /**
1384 * Admin donor billing address label
1385 *
1386 * @since 4.9.0 rename function - PHP 8 compatibility
1387 * @since 2.0
1388 *
1389 * @param string $address_label
1390 *
1391 * @return string
1392 */
1393 function give_donor_billing_address_label( $address_label ) {
1394 $address_label = __( 'Billing Address', 'give' );
1395
1396 return $address_label;
1397 }
1398
1399 add_action( 'give_donor_billing_address_label', 'give_donor_billing_address_label');
1400
1401 /**
1402 * Admin donor personal address label
1403 *
1404 * @since 4.9.0 rename function - PHP 8 compatibility
1405 * @since 2.0
1406 *
1407 * @param string $address_label
1408 *
1409 * @return string
1410 */
1411 function give_donor_personal_address_label( $address_label ) {
1412 $address_label = __( 'Personal Address', 'give' );
1413
1414 return $address_label;
1415 }
1416
1417 add_action( 'give_donor_personal_address_label', 'give_donor_personal_address_label');
1418
1419 /**
1420 * Update Donor Information when User Profile is updated from admin.
1421 * Note: for internal use only.
1422 *
1423 * @since 2.0
1424 *
1425 * @param int $user_id
1426 *
1427 * @access public
1428 * @return bool
1429 */
1430 function give_update_donor_name_on_user_update( $user_id = 0 ) {
1431
1432 if ( current_user_can( 'edit_user', $user_id ) ) {
1433
1434 $donor = new Give_Donor( $user_id, true );
1435
1436 // Bailout, if donor doesn't exists.
1437 if ( ! $donor ) {
1438 return false;
1439 }
1440
1441 // Get User First name and Last name.
1442 $first_name = ( $_POST['first_name'] ) ? give_clean( $_POST['first_name'] ) : get_user_meta( $user_id, 'first_name', true );
1443 $last_name = ( $_POST['last_name'] ) ? give_clean( $_POST['last_name'] ) : get_user_meta( $user_id, 'last_name', true );
1444 $full_name = strip_tags( wp_unslash( trim( "{$first_name} {$last_name}" ) ) );
1445
1446 // Assign User First name and Last name to Donor.
1447 Give()->donors->update(
1448 $donor->id,
1449 [
1450 'name' => $full_name,
1451 ]
1452 );
1453 Give()->donor_meta->update_meta( $donor->id, '_give_donor_first_name', $first_name );
1454 Give()->donor_meta->update_meta( $donor->id, '_give_donor_last_name', $last_name );
1455
1456 }
1457 }
1458
1459 add_action( 'edit_user_profile_update', 'give_update_donor_name_on_user_update', 10 );
1460 add_action( 'personal_options_update', 'give_update_donor_name_on_user_update', 10 );
1461
1462
1463 /**
1464 * Updates the email address of a donor record when the email on a user is updated
1465 * Note: for internal use only.
1466 *
1467 * @since 1.4.3
1468 * @access public
1469 *
1470 * @param WP_User|bool $old_user_data User data.
1471 *
1472 * @param int $user_id User ID.
1473 *
1474 * @return bool
1475 */
1476 function give_update_donor_email_on_user_update( $user_id = 0, $old_user_data = false ) {
1477
1478 $donor = new Give_Donor( $user_id, true );
1479
1480 if ( ! $donor ) {
1481 return false;
1482 }
1483
1484 $user = get_userdata( $user_id );
1485
1486 if ( ! empty( $user ) && $user->user_email !== $donor->email ) {
1487
1488 $success = Give()->donors->update(
1489 $donor->id,
1490 [
1491 'email' => $user->user_email,
1492 ]
1493 );
1494
1495 if ( $success ) {
1496 // Update some payment meta if we need to
1497 $payments_array = explode( ',', $donor->payment_ids );
1498
1499 if ( ! empty( $payments_array ) ) {
1500
1501 foreach ( $payments_array as $payment_id ) {
1502
1503 give_update_payment_meta( $payment_id, 'email', $user->user_email );
1504
1505 }
1506 }
1507
1508 /**
1509 * Fires after updating donor email on user update.
1510 *
1511 * @since 1.4.3
1512 *
1513 * @param Give_Donor $donor Give donor object.
1514 *
1515 * @param WP_User $user WordPress User object.
1516 */
1517 do_action( 'give_update_donor_email_on_user_update', $user, $donor );
1518
1519 }
1520 }
1521
1522 }
1523
1524 add_action( 'profile_update', 'give_update_donor_email_on_user_update', 10, 2 );
1525
1526
1527 /**
1528 * Flushes Give's cache.
1529 */
1530 function give_cache_flush() {
1531 if (!is_user_logged_in() || !current_user_can('manage_give_settings')) {
1532 wp_die();
1533 }
1534
1535 /**
1536 * @since 2.25.2 add nonce check
1537 */
1538 check_ajax_referer('give_cache_flush');
1539
1540 $result = Give_Cache::flush_cache();
1541
1542 if ($result) {
1543 wp_send_json_success(
1544 [
1545 'message' => __('Cache flushed successfully.', 'give'),
1546 ]
1547 );
1548 } else {
1549 wp_send_json_error(
1550 [
1551 'message' => __('An error occurred while flushing the cache.', 'give'),
1552 ]
1553 );
1554 }
1555 }
1556
1557 add_action( 'wp_ajax_give_cache_flush', 'give_cache_flush', 10, 0 );
1558
1559
1560 /**
1561 * Log give addon activation time
1562 *
1563 * @since 2.5.0
1564 *
1565 * @param $network_wide
1566 *
1567 * @param $plugin
1568 */
1569 function give_log_addon_activation_time( $plugin, $network_wide ) {
1570 if ( $network_wide ) {
1571 return;
1572 }
1573
1574 $plugin_data = give_get_plugins( [ 'only_premium_add_ons' => true ] );
1575 $plugin_data = ! empty( $plugin_data[ $plugin ] ) ? $plugin_data[ $plugin ] : [];
1576
1577 if ( $plugin_data ) {
1578 update_option( 'give_addon_last_activated', current_time( 'timestamp' ), 'no' );
1579 }
1580 }
1581
1582 add_action( 'activate_plugin', 'give_log_addon_activation_time', 10, 2 );
1583
1584
1585 /**
1586 * Hide all admin notice from add-ons page
1587 *
1588 * Note: only for internal use
1589 *
1590 * @since 2.5.0
1591 */
1592 function give_hide_notices_on_add_ons_page() {
1593 $page = ! empty( $_GET['page'] ) ? give_clean( $_GET['page'] ) : '';
1594
1595 // Bailout.
1596 if ( 'give-addons' !== $page ) {
1597 return;
1598 }
1599
1600 remove_all_actions( 'admin_notices' );
1601 }
1602
1603 add_action( 'in_admin_header', 'give_hide_notices_on_add_ons_page', 999 );
1604
1605
1606 /**
1607 * Admin JS
1608 *
1609 * @since 2.5.0
1610 */
1611 function give_admin_quick_js() {
1612 if ( is_multisite() && is_blog_admin() ) {
1613 ?>
1614 <script>
1615 jQuery(document).ready(function ($) {
1616 var $updateNotices = $('[id$="-update"] ', '.wp-list-table');
1617
1618 if ($updateNotices.length) {
1619 $.each($updateNotices, function (index, $updateNotice) {
1620 $updateNotice = $($updateNotice);
1621 $updateNotice.prev().addClass('update');
1622 });
1623 }
1624 });
1625 </script>
1626 <?php
1627 }
1628 }
1629
1630 add_action( 'admin_head', 'give_admin_quick_js' );
1631
1632 /**
1633 * Add Admin addon menu related scripts
1634 *
1635 * @since 2.6.0
1636 */
1637 function give_admin_addon_menu_inline_scripts() {
1638 ?>
1639 <script>
1640 (function ($) {
1641 const $addonLink = $('#menu-posts-give_forms a[href^="edit.php?post_type=give_forms&page=give-add-ons"]');
1642 <?php if ( empty( give_get_plugins( [ 'only_premium_add_ons' => true ] ) ) ) : ?>
1643 $addonLink.addClass('give-highlight');
1644 $addonLink.prepend('<span class="dashicons dashicons-star-filled"></span>');
1645 <?php endif; ?>
1646 })(jQuery)
1647 </script>
1648 <style>
1649 #menu-posts-give_forms a[href^="edit.php?post_type=give_forms&page=give-add-ons"].give-highlight {
1650 color: rgb(43, 194, 83);
1651 font-weight: 700;
1652 vertical-align: top;
1653 text-shadow: 0 1px 2px #00000080;
1654 }
1655
1656 #menu-posts-give_forms a[href^="edit.php?post_type=give_forms&page=give-add-ons"].give-highlight span.dashicons {
1657 font-size: 14px !important;
1658 width: auto;
1659 height: 18px;
1660 padding-right: 3px;
1661 vertical-align: middle;
1662 }
1663 </style>
1664 <?php
1665 }
1666
1667 add_action( 'admin_footer', 'give_admin_addon_menu_inline_scripts' );
1668
1669 /**
1670 * Handle akismet_deblacklist_spammed_email_handler give-action
1671 *
1672 * @since 2.5.14
1673 *
1674 * @param array $get
1675 *
1676 */
1677 function give_akismet_deblacklist_spammed_email_handler( $get ) {
1678 $email = ! empty( $get['email'] ) && is_email( $get['email'] ) ? give_clean( $get['email'] ) : '';
1679 $log = ! empty( $get['log'] ) ? absint( $get['log'] ) : '';
1680 $action = "give_akismet_deblacklist_spammed_email_{$email}";
1681
1682 check_admin_referer( $action );
1683 $emails = give_akismet_get_whitelisted_emails();
1684
1685 if ( ! in_array( $email, $emails, true ) ) {
1686 array_unshift( $emails, $email );
1687
1688 give_update_option( 'akismet_whitelisted_email_addresses', $emails );
1689
1690 // Redirect to Akismet setting page.
1691 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' );
1692 }
1693 }
1694
1695 add_action( 'give_akismet_deblacklist_spammed_email', 'give_akismet_deblacklist_spammed_email_handler' );
1696
1697 /**
1698 * Add Custom setting view for form them setting panel
1699 *
1700 * @since 2.7.0
1701 */
1702 function give_render_form_theme_setting_panel() {
1703 require_once GIVE_PLUGIN_DIR . 'src/Views/Admin/Form/Metabox-Settings.php';
1704 }
1705
1706 add_action( 'give_post_form_template_options_settings', 'give_render_form_theme_setting_panel' );
1707
1708 /**
1709 * Add Custom setting view for form grid setting panel
1710 *
1711 * @since 2.20.0
1712 */
1713 function give_render_form_grid_setting_panel()
1714 {
1715 require_once GIVE_PLUGIN_DIR . 'src/Views/Admin/Form/FormGrid-Settings.php';
1716 }
1717
1718 add_action('give_post_form_grid_options_settings', 'give_render_form_grid_setting_panel');
1719
1720