PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.16.9
GiveWP – Donation Plugin and Fundraising Platform v4.16.9
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 2.3.2 2.30.0 All 255 releases
← All changes | includes/admin/admin-actions.php +924 -364 2.3.04.16.9 View file →
@@ -1,13 +1,18 @@
1 1 <?php
2 +
3 +use Give\Framework\Database\DB;
4 +use Give\Helpers\Utils;
5 +use Give\Log\ValueObjects\LogType;
6 +
2 7 /**
3 8 * Admin Actions
4 9 *
5 10 * @package Give
11 + * @since 1.0
12 + * @copyright Copyright (c) 2016, GiveWP
13 + * @license https://opensource.org/licenses/gpl-license GNU Public License
6 14 * @subpackage Admin/Actions
7 - * @copyright Copyright (c) 2016, WordImpress
8 - * @license https://opensource.org/licenses/gpl-license GNU Public License
9 - * @since 1.0
10 15 */
11 16
12 17 // Exit if accessed directly.
13 18 if ( ! defined( 'ABSPATH' ) ) {
@@ -19,16 +24,16 @@
19 24 *
20 25 * @since 1.8
21 26 */
22 27 function give_load_wp_editor() {
23 - if ( ! isset( $_POST['wp_editor'] ) ) {
28 + if ( ! isset( $_POST['wp_editor'] ) || ! current_user_can( 'edit_give_forms' ) ) {
24 29 die();
25 30 }
26 31
27 32 $wp_editor = json_decode( base64_decode( $_POST['wp_editor'] ), true );
28 - $wp_editor[2]['textarea_name'] = $_POST['textarea_name'];
33 + $wp_editor[2]['textarea_name'] = give_clean( $_POST['textarea_name'] );
29 34
30 - wp_editor( $wp_editor[0], $_POST['wp_editor_id'], $wp_editor[2] );
35 + wp_editor( wp_kses_post( $wp_editor[0] ), give_clean( $_POST['wp_editor_id'] ), $wp_editor[2] );
31 36
32 37 die();
33 38 }
34 39
@@ -37,20 +42,21 @@
37 42
38 43 /**
39 44 * Redirect admin to clean url give admin pages.
40 45 *
41 - * @since 1.8
46 + * @since 2.25.2 Removed _wpnonce from list of removed args.
47 + * @since 1.8
42 48 *
43 49 * @return bool
44 50 */
45 51 function give_redirect_to_clean_url_admin_pages() {
46 52 // Give admin pages.
47 - $give_pages = array(
53 + $give_pages = [
48 54 'give-payment-history',
49 55 'give-donors',
50 56 'give-reports',
51 57 'give-tools',
52 - );
58 + ];
53 59
54 60 // Get current page.
55 61 $current_page = isset( $_GET['page'] ) ? esc_attr( $_GET['page'] ) : '';
56 62
@@ -72,12 +78,14 @@
72 78
73 79 if ( $redirect ) {
74 80 // Redirect.
75 81 wp_redirect(
76 - remove_query_arg(
77 - array( '_wp_http_referer', '_wpnonce' ),
78 - wp_unslash( $_SERVER['REQUEST_URI'] )
79 - )
82 + esc_url_raw(
83 + remove_query_arg(
84 + ['_wp_http_referer'],
85 + wp_unslash($_SERVER['REQUEST_URI'])
86 + )
87 + )
80 88 );
81 89 exit;
82 90 }
83 91 }
@@ -90,14 +98,13 @@
90 98 *
91 99 * This code is used with AJAX call to hide outdated PHP notice for a short period of time
92 100 *
93 101 * @since 1.8.9
94 - *
95 102 * @return void
96 103 */
97 104 function give_hide_outdated_php_notice() {
98 105
99 - if ( ! isset( $_POST['_give_hide_outdated_php_notices_shortly'] ) ) {
106 + if ( ! isset( $_POST['_give_hide_outdated_php_notices_shortly'] ) || ! current_user_can( 'manage_give_settings' ) ) {
100 107 give_die();
101 108 }
102 109
103 110 // Transient key name.
@@ -118,9 +125,10 @@
118 125
119 126 /**
120 127 * Register admin notices.
121 128 *
122 - * @since 1.8.9
129 + * @since 2.25.2 Add nonce check for bulk action.
130 + * @since 1.8.9
123 131 */
124 132 function _give_register_admin_notices() {
125 133 // Bailout.
126 134 if ( ! is_admin() ) {
@@ -134,70 +142,79 @@
134 142 ) {
135 143
136 144 // Add payment bulk notice.
137 145 if (
138 - current_user_can( 'edit_give_payments' ) &&
139 - isset( $_GET['payment'] ) &&
140 - ! empty( $_GET['payment'] )
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'] )
141 151 ) {
142 152 $payment_count = isset( $_GET['payment'] ) ? count( $_GET['payment'] ) : 0;
143 153
144 154 switch ( $_GET['action'] ) {
145 155 case 'delete':
146 - Give()->notices->register_notice( array(
147 - 'id' => 'bulk_action_delete',
148 - 'type' => 'updated',
149 - 'description' => sprintf(
150 - _n(
151 - 'Successfully deleted one donation.',
152 - 'Successfully deleted %d donations.',
153 - $payment_count,
154 - 'give'
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
155 168 ),
156 - $payment_count ),
157 - 'show' => true,
158 - ) );
169 + 'show' => true,
170 + ]
171 + );
159 172
160 173 break;
161 174
162 175 case 'resend-receipt':
163 - Give()->notices->register_notice( array(
164 - 'id' => 'bulk_action_resend_receipt',
165 - 'type' => 'updated',
166 - 'description' => sprintf(
167 - _n(
168 - 'Successfully sent email receipt to one recipient.',
169 - 'Successfully sent email receipts to %d recipients.',
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.',
170 210 $payment_count,
171 211 'give'
172 212 ),
173 - $payment_count
174 - ),
175 - 'show' => true,
176 - ) );
213 + 'show' => true,
214 + ]
215 + );
177 216 break;
178 -
179 - case 'set-status-publish' :
180 - case 'set-status-pending' :
181 - case 'set-status-processing' :
182 - case 'set-status-refunded' :
183 - case 'set-status-revoked' :
184 - case 'set-status-failed' :
185 - case 'set-status-cancelled' :
186 - case 'set-status-abandoned' :
187 - case 'set-status-preapproval' :
188 - Give()->notices->register_notice( array(
189 - 'id' => 'bulk_action_status_change',
190 - 'type' => 'updated',
191 - 'description' => _n(
192 - 'Donation status updated successfully.',
193 - 'Donation statuses updated successfully.',
194 - $payment_count,
195 - 'give'
196 - ),
197 - 'show' => true,
198 - ) );
199 - break;
200 217 }// End switch().
201 218 }// End if().
202 219 }// End if().
203 220
@@ -207,39 +224,47 @@
207 224 foreach ( $message_notices as $message_notice ) {
208 225 // Donation reports errors.
209 226 if ( current_user_can( 'view_give_reports' ) ) {
210 227 switch ( $message_notice ) {
211 - case 'donation-deleted' :
212 - Give()->notices->register_notice( array(
213 - 'id' => 'give-donation-deleted',
214 - 'type' => 'updated',
215 - 'description' => __( 'The donation has been deleted.', 'give' ),
216 - 'show' => true,
217 - ) );
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 + );
218 237 break;
219 - case 'email-sent' :
220 - Give()->notices->register_notice( array(
221 - 'id' => 'give-email-sent',
222 - 'type' => 'updated',
223 - 'description' => __( 'The donation receipt has been resent.', 'give' ),
224 - 'show' => true,
225 - ) );
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 + );
226 247 break;
227 - case 'refreshed-reports' :
228 - Give()->notices->register_notice( array(
229 - 'id' => 'give-refreshed-reports',
230 - 'type' => 'updated',
231 - 'description' => __( 'The reports cache has been cleared.', 'give' ),
232 - 'show' => true,
233 - ) );
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 + );
234 257 break;
235 - case 'donation-note-deleted' :
236 - Give()->notices->register_notice( array(
237 - 'id' => 'give-donation-note-deleted',
238 - 'type' => 'updated',
239 - 'description' => __( 'The donation note has been deleted.', 'give' ),
240 - 'show' => true,
241 - ) );
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 + );
242 267 break;
243 268 }// End switch().
244 269 }// End if().
245 270
@@ -245,64 +270,89 @@
245 270
246 271 // Give settings notices and errors.
247 272 if ( current_user_can( 'manage_give_settings' ) ) {
248 273 switch ( $message_notice ) {
249 - case 'settings-imported' :
250 - Give()->notices->register_notice( array(
251 - 'id' => 'give-settings-imported',
252 - 'type' => 'updated',
253 - 'description' => __( 'The settings have been imported.', 'give' ),
254 - 'show' => true,
255 - ) );
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 + );
256 283 break;
257 - case 'api-key-generated' :
258 - Give()->notices->register_notice( array(
259 - 'id' => 'give-api-key-generated',
260 - 'type' => 'updated',
261 - 'description' => __( 'API keys have been generated.', 'give' ),
262 - 'show' => true,
263 - ) );
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 + );
264 293 break;
265 - case 'api-key-exists' :
266 - Give()->notices->register_notice( array(
267 - 'id' => 'give-api-key-exists',
268 - 'type' => 'updated',
269 - 'description' => __( 'The specified user already has API keys.', 'give' ),
270 - 'show' => true,
271 - ) );
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 + );
272 303 break;
273 - case 'api-key-regenerated' :
274 - Give()->notices->register_notice( array(
275 - 'id' => 'give-api-key-regenerated',
276 - 'type' => 'updated',
277 - 'description' => __( 'API keys have been regenerated.', 'give' ),
278 - 'show' => true,
279 - ) );
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 + );
280 313 break;
281 - case 'api-key-revoked' :
282 - Give()->notices->register_notice( array(
283 - 'id' => 'give-api-key-revoked',
284 - 'type' => 'updated',
285 - 'description' => __( 'API keys have been revoked.', 'give' ),
286 - 'show' => true,
287 - ) );
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 + );
288 323 break;
289 - case 'sent-test-email' :
290 - Give()->notices->register_notice( array(
291 - 'id' => 'give-sent-test-email',
292 - 'type' => 'updated',
293 - 'description' => __( 'The test email has been sent.', 'give' ),
294 - 'show' => true,
295 - ) );
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 + );
296 333 break;
297 334 case 'matched-success-failure-page':
298 - Give()->notices->register_notice( array(
299 - 'id' => 'give-matched-success-failure-page',
300 - 'type' => 'updated',
301 - 'description' => __( 'You cannot set the success and failed pages to the same page', 'give' ),
302 - 'show' => true,
303 - ) );
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 + );
304 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;
305 355 }// End switch().
306 356 }// End if().
307 357
308 358 // Payments errors.
@@ -307,23 +357,27 @@
307 357
308 358 // Payments errors.
309 359 if ( current_user_can( 'edit_give_payments' ) ) {
310 360 switch ( $message_notice ) {
311 - case 'note-added' :
312 - Give()->notices->register_notice( array(
313 - 'id' => 'give-note-added',
314 - 'type' => 'updated',
315 - 'description' => __( 'The donation note has been added.', 'give' ),
316 - 'show' => true,
317 - ) );
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 + );
318 370 break;
319 - case 'payment-updated' :
320 - Give()->notices->register_notice( array(
321 - 'id' => 'give-payment-updated',
322 - 'type' => 'updated',
323 - 'description' => __( 'The donation has been updated.', 'give' ),
324 - 'show' => true,
325 - ) );
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 + );
326 380 break;
327 381 }// End switch().
328 382 }// End if().
329 383
@@ -329,119 +383,194 @@
329 383
330 384 // Donor Notices.
331 385 if ( current_user_can( 'edit_give_payments' ) ) {
332 386 switch ( $message_notice ) {
333 - case 'donor-deleted' :
334 - Give()->notices->register_notice( array(
335 - 'id' => 'give-donor-deleted',
336 - 'type' => 'updated',
337 - 'description' => __( 'The selected donor(s) has been deleted.', 'give' ),
338 - 'show' => true,
339 - ) );
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 + );
340 396 break;
341 397
342 - case 'donor-donations-deleted' :
343 - Give()->notices->register_notice( array(
344 - 'id' => 'give-donor-donations-deleted',
345 - 'type' => 'updated',
346 - 'description' => __( 'The selected donor(s) and the associated donation(s) has been deleted.', 'give' ),
347 - 'show' => true,
348 - ) );
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 + );
349 407 break;
350 408
351 - case 'confirm-delete-donor' :
352 - Give()->notices->register_notice( array(
353 - 'id' => 'give-confirm-delete-donor',
354 - 'type' => 'updated',
355 - 'description' => __( 'You must confirm to delete the selected donor(s).', 'give' ),
356 - 'show' => true,
357 - ) );
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 + );
358 418 break;
359 419
360 - case 'invalid-donor-id' :
361 - Give()->notices->register_notice( array(
362 - 'id' => 'give-invalid-donor-id',
363 - 'type' => 'updated',
364 - 'description' => __( 'Invalid Donor ID.', 'give' ),
365 - 'show' => true,
366 - ) );
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 + );
367 429 break;
368 430
369 - case 'donor-delete-failed' :
370 - Give()->notices->register_notice( array(
371 - 'id' => 'give-donor-delete-failed',
372 - 'type' => 'error',
373 - 'description' => __( 'Unable to delete selected donor(s).', 'give' ),
374 - 'show' => true,
375 - ) );
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 + );
376 440 break;
377 441
378 - case 'email-added' :
379 - Give()->notices->register_notice( array(
380 - 'id' => 'give-email-added',
381 - 'type' => 'updated',
382 - 'description' => __( 'Donor email added.', 'give' ),
383 - 'show' => true,
384 - ) );
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 + );
385 451 break;
386 452
387 - case 'email-removed' :
388 - Give()->notices->register_notice( array(
389 - 'id' => 'give-email-removed',
390 - 'type' => 'updated',
391 - 'description' => __( 'Donor email removed.', 'give' ),
392 - 'show' => true,
393 - ) );
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 + );
394 462 break;
395 463
396 - case 'email-remove-failed' :
397 - Give()->notices->register_notice( array(
398 - 'id' => 'give-email-remove-failed',
399 - 'type' => 'updated',
400 - 'description' => __( 'Failed to remove donor email.', 'give' ),
401 - 'show' => true,
402 - ) );
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 + );
403 473 break;
404 474
405 - case 'primary-email-updated' :
406 - Give()->notices->register_notice( array(
407 - 'id' => 'give-primary-email-updated',
408 - 'type' => 'updated',
409 - 'description' => __( 'Primary email updated for donor.', 'give' ),
410 - 'show' => true,
411 - ) );
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 + );
412 484 break;
413 485
414 - case 'primary-email-failed' :
415 - Give()->notices->register_notice( array(
416 - 'id' => 'give-primary-email-failed',
417 - 'type' => 'updated',
418 - 'description' => __( 'Failed to set primary email.', 'give' ),
419 - 'show' => true,
420 - ) );
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 + );
421 495 break;
422 496
423 - case 'reconnect-user' :
424 - Give()->notices->register_notice( array(
425 - 'id' => 'give-reconnect-user',
426 - 'type' => 'updated',
427 - 'description' => __( 'User has been successfully connected with Donor.', 'give' ),
428 - 'show' => true,
429 - ) );
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 + );
430 506 break;
431 507
432 - case 'profile-updated' :
433 - Give()->notices->register_notice( array(
434 - 'id' => 'give-profile-updated',
435 - 'type' => 'updated',
436 - 'description' => __( 'Donor information updated successfully.', 'give' ),
437 - 'show' => true,
438 - ) );
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 + );
439 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;
440 529 }// End switch().
441 530 }// End if().
442 531 }
443 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 + }
444 573 }
445 574
446 575 add_action( 'admin_notices', '_give_register_admin_notices', - 1 );
447 576
@@ -465,17 +594,19 @@
465 594 return false;
466 595 }
467 596
468 597 // Add the main site admin menu item.
469 - $wp_admin_bar->add_menu( array(
470 - 'id' => 'give-test-notice',
471 - 'href' => admin_url( 'edit.php?post_type=give_forms&page=give-settings&tab=gateways' ),
472 - 'parent' => 'top-secondary',
473 - 'title' => __( 'Give Test Mode Active', 'give' ),
474 - 'meta' => array(
475 - 'class' => 'give-test-mode-active',
476 - ),
477 - ) );
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 + );
478 609
479 610 return true;
480 611 }
481 612
@@ -514,8 +645,24 @@
514 645 function give_import_page_link_callback() {
515 646 ?>
516 647 <a href="<?php echo esc_url( give_import_page_url() ); ?>"
517 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>
518 665
519 666 <?php
520 667 // Check if view donation single page only.
521 668 if ( ! empty( $_REQUEST['view'] ) && 'view-payment-details' === (string) give_clean( $_REQUEST['view'] ) && 'give-payment-history' === give_clean( $_REQUEST['page'] ) ) {
@@ -531,21 +678,44 @@
531 678
532 679 add_action( 'give_payments_page_top', 'give_import_page_link_callback', 11 );
533 680
534 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 +/**
535 697 * Load donation import ajax callback
536 698 * Fire when importing from CSV start
537 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.
538 703 * @since 1.8.13
539 - *
540 - * @return json $json_data
541 704 */
542 705 function give_donation_import_callback() {
543 706
707 + check_ajax_referer('give_donation_import');
708 +
709 + // Bailout.
710 + if ( ! current_user_can( 'manage_give_settings' ) ) {
711 + give_die();
712 + }
713 +
544 714 // Disable Give cache
545 715 Give_Cache::get_instance()->disable();
546 716
547 - $import_setting = array();
717 + $import_setting = [];
548 718 $fields = isset( $_POST['fields'] ) ? $_POST['fields'] : null;
549 719
550 720 parse_str( $fields, $output );
551 721
@@ -556,9 +726,9 @@
556 726 $import_setting['delete_csv'] = $output['delete_csv'];
557 727 $import_setting['dry_run'] = $output['dry_run'];
558 728
559 729 // Parent key id.
560 - $main_key = maybe_unserialize( $output['main_key'] );
730 + $main_key = give_maybe_safe_unserialize($output['main_key']);
561 731
562 732 $current = absint( $_REQUEST['current'] );
563 733 $total_ajax = absint( $_REQUEST['total_ajax'] );
564 734 $start = absint( $_REQUEST['start'] );
@@ -572,19 +742,21 @@
572 742 $delimiter = $output['delimiter'];
573 743 }
574 744
575 745 // Processing done here.
576 - $raw_data = give_get_donation_data_from_csv( $output['csv'], $start, $end, $delimiter );
577 - $raw_key = maybe_unserialize( $output['mapto'] );
746 + $raw_data = give_get_donation_data_from_csv( $output['csv'], $start, $end, $delimiter);
747 + $raw_key = give_maybe_safe_unserialize($output['mapto']);
578 748 $import_setting['raw_key'] = $raw_key;
579 749
580 750 if ( ! empty( $output['dry_run'] ) ) {
581 751 $import_setting['csv_raw_data'] = give_get_donation_data_from_csv( $output['csv'], 1, $end, $delimiter );
582 752
583 - $import_setting['donors_list'] = Give()->donors->get_donors( array(
584 - 'number' => - 1,
585 - 'fields' => array( 'id', 'user_id', 'email' ),
586 - ) );
753 + $import_setting['donors_list'] = Give()->donors->get_donors(
754 + [
755 + 'number' => - 1,
756 + 'fields' => [ 'id', 'user_id', 'email' ],
757 + ]
758 + );
587 759 }
588 760
589 761 // Prevent normal emails.
590 762 remove_action( 'give_complete_donation', 'give_trigger_donation_receipt', 999 );
@@ -590,14 +762,20 @@
590 762 remove_action( 'give_complete_donation', 'give_trigger_donation_receipt', 999 );
591 763 remove_action( 'give_insert_user', 'give_new_user_notification', 10 );
592 764 remove_action( 'give_insert_payment', 'give_payment_save_page_data' );
593 765
594 - $current_key = $start;
595 - foreach ( $raw_data as $row_data ) {
596 - $import_setting['donation_key'] = $current_key;
597 - give_save_import_donation_to_db( $raw_key, $row_data, $main_key, $import_setting );
598 - $current_key ++;
599 - }
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 + }
600 778
601 779 // Check if function exists or not.
602 780 if ( function_exists( 'give_payment_save_page_data' ) ) {
603 781 add_action( 'give_insert_payment', 'give_payment_save_page_data' );
@@ -605,12 +783,12 @@
605 783 add_action( 'give_insert_user', 'give_new_user_notification', 10, 2 );
606 784 add_action( 'give_complete_donation', 'give_trigger_donation_receipt', 999 );
607 785
608 786 if ( $next == false ) {
609 - $json_data = array(
787 + $json_data = [
610 788 'success' => true,
611 789 'message' => __( 'All donation uploaded successfully!', 'give' ),
612 - );
790 + ];
613 791 } else {
614 792 $index_start = $start;
615 793 $index_end = $end;
616 794 $last = false;
@@ -622,9 +800,9 @@
622 800 if ( $index_end >= $total ) {
623 801 $index_end = $total;
624 802 $last = true;
625 803 }
626 - $json_data = array(
804 + $json_data = [
627 805 'raw_data' => $raw_data,
628 806 'raw_key' => $raw_key,
629 807 'next' => $next,
630 808 'start' => $index_start,
@@ -629,20 +807,23 @@
629 807 'next' => $next,
630 808 'start' => $index_start,
631 809 'end' => $index_end,
632 810 'last' => $last,
633 - );
811 + ];
634 812 }
635 813
636 - $url = give_import_page_url( array(
637 - 'step' => '4',
638 - 'importer-type' => 'import_donations',
639 - 'csv' => $output['csv'],
640 - 'total' => $total,
641 - 'delete_csv' => $import_setting['delete_csv'],
642 - 'success' => ( isset( $json_data['success'] ) ? $json_data['success'] : '' ),
643 - 'dry_run' => $output['dry_run'],
644 - ) );
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 + );
645 826 $json_data['url'] = $url;
646 827
647 828 $current ++;
648 829 $json_data['current'] = $current;
@@ -659,17 +840,143 @@
659 840
660 841 add_action( 'wp_ajax_give_donation_import', 'give_donation_import_callback' );
661 842
662 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 +/**
663 965 * Load core settings import ajax callback
664 966 * Fire when importing from JSON start
665 967 *
666 968 * @since 1.8.17
667 - *
668 - * @return json $json_data
669 969 */
670 970
671 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 +
672 979 $fields = isset( $_POST['fields'] ) ? $_POST['fields'] : null;
673 980 parse_str( $fields, $fields );
674 981
675 982 $json_data['success'] = false;
@@ -695,10 +1002,10 @@
695 1002 // Get the json data from the file and then alter it in array format
696 1003 $json_string = give_get_core_settings_json( $file_name );
697 1004 $json_to_array = json_decode( $json_string, true );
698 1005
699 - // get the current settign from the options table.
700 - $host_give_options = get_option( 'give_settings', array() );
1006 + // get the current setting from the options table.
1007 + $host_give_options = Give_Cache_Setting::get_settings();
701 1008
702 1009 // Save old settins for backup.
703 1010 update_option( 'give_settings_old', $host_give_options, false );
704 1011
@@ -708,13 +1015,14 @@
708 1015 * @access public
709 1016 *
710 1017 * @since 1.8.17
711 1018 *
712 - * @param array $json_to_array Setting that are being going to get imported
713 - * @param array $type Type of Import
1019 + * @param array $type Type of Import
714 1020 * @param array $host_give_options Setting old setting that used to be in the options table.
715 - * @param array $fields Data that is being send from the ajax
1021 + * @param array $fields Data that is being send from the ajax
716 1022 *
1023 + * @param array $json_to_array Setting that are being going to get imported
1024 + *
717 1025 * @return array $json_to_array Setting that are being going to get imported
718 1026 */
719 1027 $json_to_array = (array) apply_filters( 'give_import_core_settings_data', $json_to_array, $type, $host_give_options, $fields );
720 1028
@@ -730,16 +1038,20 @@
730 1038 *
731 1039 * @access public
732 1040 *
733 1041 * @since 1.8.17
734 - *
735 1042 * @return array $url
736 1043 */
737 - $json_data['url'] = give_import_page_url( (array) apply_filters( 'give_import_core_settings_success_url', array(
738 - 'step' => ( empty( $json_data['success'] ) ? '1' : '3' ),
739 - 'importer-type' => 'import_core_setting',
740 - 'success' => ( empty( $json_data['success'] ) ? '0' : '1' ),
741 - ) ) );
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 + );
742 1054
743 1055 wp_send_json( $json_data );
744 1056 }
745 1057
@@ -759,13 +1071,14 @@
759 1071
760 1072 /**
761 1073 * Validate Fields of User Profile
762 1074 *
763 - * @param object $errors Object of WP Errors.
1075 + * @since 2.0
1076 + *
764 1077 * @param int|bool $update True or False.
765 - * @param object $user WP User Data.
1078 + * @param object $user WP User Data.
766 1079 *
767 - * @since 2.0
1080 + * @param object $errors Object of WP Errors.
768 1081 *
769 1082 * @return mixed
770 1083 */
771 1084 function give_validate_user_profile( $errors, $update, $user ) {
@@ -798,32 +1111,29 @@
798 1111
799 1112 /**
800 1113 * Show Donor Information on User Profile Page.
801 1114 *
1115 + * @since 2.0
1116 + *
802 1117 * @param object $user User Object.
803 1118 *
804 - * @since 2.0
805 1119 */
806 1120 function give_donor_information_profile_fields( $user ) {
807 1121 $donor = Give()->donors->get_donor_by( 'user_id', $user->ID );
808 1122
809 1123 // Display Donor Information, only if donor is attached with User.
810 - if ( ! empty( $donor->user_id ) ) {
1124 + if ( ! empty( $donor->user_id ) ) :
811 1125 ?>
812 - <table class="form-table">
813 - <tbody>
814 - <tr>
815 - <th scope="row"><?php _e( 'Donor', 'give' ); ?></th>
816 - <td>
817 - <a href="<?php echo admin_url( 'edit.php?post_type=give_forms&page=give-donors&view=overview&id=' . $donor->id ); ?>">
818 - <?php _e( 'View Donor Information', 'give' ); ?>
819 - </a>
820 - </td>
821 - </tr>
822 - </tbody>
823 - </table>
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>
824 1134 <?php
825 - }
1135 + endif;
826 1136 }
827 1137
828 1138 add_action( 'personal_options', 'give_donor_information_profile_fields' );
829 1139 /**
@@ -829,13 +1139,12 @@
829 1139 /**
830 1140 * Get Array of WP User Roles.
831 1141 *
832 1142 * @since 1.8.13
833 - *
834 1143 * @return array
835 1144 */
836 1145 function give_get_user_roles() {
837 - $user_roles = array();
1146 + $user_roles = [];
838 1147
839 1148 // Loop through User Roles.
840 1149 foreach ( get_editable_roles() as $role_name => $role_info ) :
841 1150 $user_roles[ $role_name ] = $role_info['name'];
@@ -845,49 +1154,110 @@
845 1154 }
846 1155
847 1156
848 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 +/**
849 1214 * Ajax handle for donor address.
850 1215 *
851 1216 * @since 2.0
852 - *
853 - * @return string
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
854 1220 */
855 -function __give_ajax_donor_manage_addresses() {
1221 +function give_ajax_donor_manage_addresses() {
856 1222 // Bailout.
857 1223 if (
858 1224 empty( $_POST['form'] ) ||
859 1225 empty( $_POST['donorID'] )
860 1226 ) {
861 - wp_send_json_error( array(
862 - 'error' => 1,
863 - ) );
1227 + wp_send_json_error(
1228 + [
1229 + 'error' => 1,
1230 + ]
1231 + );
864 1232 }
865 1233
866 - $post = give_clean( wp_parse_args( $_POST ) );
1234 + $post = give_clean( wp_parse_args( urldecode_deep( $_POST ) ) );
867 1235 $donorID = absint( $post['donorID'] );
868 1236 $form_data = give_clean( wp_parse_args( $post['form'] ) );
869 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'] );
870 1239 $address_type = false !== strpos( $form_data['address-id'], '_' ) ?
871 - array_shift( explode( '_', $form_data['address-id'] ) ) :
1240 + array_shift( $exploded_address_id ) :
872 1241 $form_data['address-id'];
873 1242 $address_id = false !== strpos( $form_data['address-id'], '_' ) ?
874 - array_pop( explode( '_', $form_data['address-id'] ) ) :
1243 + array_pop( $exploded_address_id ) :
875 1244 null;
876 - $response_data = array(
1245 + $response_data = [
877 1246 'action' => $form_data['address-action'],
878 1247 'id' => $form_data['address-id'],
879 - );
1248 + ];
880 1249
881 1250 // Security check.
882 1251 if ( ! wp_verify_nonce( $form_data['_wpnonce'], 'give-manage-donor-addresses' ) ) {
883 - wp_send_json_error( array(
1252 + wp_send_json_error(
1253 + [
884 1254 'error' => 1,
885 1255 'error_msg' => wp_sprintf(
886 1256 '<div class="notice notice-error"><p>%s</p></div>',
887 1257 __( 'Error: Security issue.', 'give' )
888 1258 ),
889 - )
1259 + ]
890 1260 );
891 1261 }
892 1262
893 1263 $donor = new Give_Donor( $donorID );
@@ -893,11 +1263,13 @@
893 1263 $donor = new Give_Donor( $donorID );
894 1264
895 1265 // Verify donor.
896 1266 if ( ! $donor->id ) {
897 - wp_send_json_error( array(
898 - 'error' => 3,
899 - ) );
1267 + wp_send_json_error(
1268 + [
1269 + 'error' => 3,
1270 + ]
1271 + );
900 1272 }
901 1273
902 1274 // Unset all data except address.
903 1275 unset(
@@ -910,15 +1282,16 @@
910 1282 switch ( $response_data['action'] ) {
911 1283
912 1284 case 'add':
913 1285 if ( ! $donor->add_address( "{$address_type}[]", $form_data ) ) {
914 - wp_send_json_error( array(
1286 + wp_send_json_error(
1287 + [
915 1288 'error' => 1,
916 1289 'error_msg' => wp_sprintf(
917 1290 '<div class="notice notice-error"><p>%s</p></div>',
918 1291 __( 'Error: Unable to save the address. Please check if address already exist.', 'give' )
919 1292 ),
920 - )
1293 + ]
921 1294 );
922 1295 }
923 1296
924 1297 $total_addresses = count( $donor->address[ $address_type ] );
@@ -932,16 +1305,16 @@
932 1305 $address_id = $is_multi_address_type ?
933 1306 end( $array_keys ) :
934 1307 $address_type;
935 1308
936 - $response_data['address_html'] = __give_get_format_address(
1309 + $response_data['address_html'] = give_get_format_address(
937 1310 end( $donor->address['billing'] ),
938 - array(
1311 + [
939 1312 // We can add only billing address from donor screen.
940 1313 'type' => 'billing',
941 1314 'id' => $address_id,
942 1315 'index' => ++ $address_index,
943 - )
1316 + ]
944 1317 );
945 1318 $response_data['success_msg'] = wp_sprintf(
946 1319 '<div class="notice updated"><p>%s</p></div>',
947 1320 __( 'Successfully added a new address to the donor.', 'give' )
@@ -954,15 +1327,16 @@
954 1327 break;
955 1328
956 1329 case 'remove':
957 1330 if ( ! $donor->remove_address( $response_data['id'] ) ) {
958 - wp_send_json_error( array(
1331 + wp_send_json_error(
1332 + [
959 1333 'error' => 2,
960 1334 'error_msg' => wp_sprintf(
961 1335 '<div class="notice notice-error"><p>%s</p></div>',
962 1336 __( 'Error: Unable to delete address.', 'give' )
963 1337 ),
964 - )
1338 + ]
965 1339 );
966 1340 }
967 1341
968 1342 $response_data['success_msg'] = wp_sprintf(
@@ -973,27 +1347,28 @@
973 1347 break;
974 1348
975 1349 case 'update':
976 1350 if ( ! $donor->update_address( $response_data['id'], $form_data ) ) {
977 - wp_send_json_error( array(
1351 + wp_send_json_error(
1352 + [
978 1353 'error' => 3,
979 1354 'error_msg' => wp_sprintf(
980 1355 '<div class="notice notice-error"><p>%s</p></div>',
981 1356 __( 'Error: Unable to update address. Please check if address already exist.', 'give' )
982 1357 ),
983 - )
1358 + ]
984 1359 );
985 1360 }
986 1361
987 - $response_data['address_html'] = __give_get_format_address(
1362 + $response_data['address_html'] = give_get_format_address(
988 1363 $is_multi_address_type ?
989 1364 $donor->address[ $address_type ][ $address_id ] :
990 1365 $donor->address[ $address_type ],
991 - array(
1366 + [
992 1367 'type' => $address_type,
993 1368 'id' => $address_id,
994 1369 'index' => $address_id,
995 - )
1370 + ]
996 1371 );
997 1372 $response_data['success_msg'] = wp_sprintf(
998 1373 '<div class="notice updated"><p>%s</p></div>',
999 1374 __( 'Successfully updated a address of donor', 'give' )
@@ -1004,13 +1379,14 @@
1004 1379
1005 1380 wp_send_json_success( $response_data );
1006 1381 }
1007 1382
1008 -add_action( 'wp_ajax_donor_manage_addresses', '__give_ajax_donor_manage_addresses' );
1383 +add_action( 'wp_ajax_donor_manage_addresses', 'give_ajax_donor_manage_addresses');
1009 1384
1010 1385 /**
1011 1386 * Admin donor billing address label
1012 1387 *
1388 + * @since 4.9.0 rename function - PHP 8 compatibility
1013 1389 * @since 2.0
1014 1390 *
1015 1391 * @param string $address_label
1016 1392 *
@@ -1015,19 +1391,20 @@
1015 1391 * @param string $address_label
1016 1392 *
1017 1393 * @return string
1018 1394 */
1019 -function __give_donor_billing_address_label( $address_label ) {
1395 +function give_donor_billing_address_label( $address_label ) {
1020 1396 $address_label = __( 'Billing Address', 'give' );
1021 1397
1022 1398 return $address_label;
1023 1399 }
1024 1400
1025 -add_action( 'give_donor_billing_address_label', '__give_donor_billing_address_label' );
1401 +add_action( 'give_donor_billing_address_label', 'give_donor_billing_address_label');
1026 1402
1027 1403 /**
1028 1404 * Admin donor personal address label
1029 1405 *
1406 + * @since 4.9.0 rename function - PHP 8 compatibility
1030 1407 * @since 2.0
1031 1408 *
1032 1409 * @param string $address_label
1033 1410 *
@@ -1032,25 +1409,25 @@
1032 1409 * @param string $address_label
1033 1410 *
1034 1411 * @return string
1035 1412 */
1036 -function __give_donor_personal_address_label( $address_label ) {
1413 +function give_donor_personal_address_label( $address_label ) {
1037 1414 $address_label = __( 'Personal Address', 'give' );
1038 1415
1039 1416 return $address_label;
1040 1417 }
1041 1418
1042 -add_action( 'give_donor_personal_address_label', '__give_donor_personal_address_label' );
1419 +add_action( 'give_donor_personal_address_label', 'give_donor_personal_address_label');
1043 1420
1044 1421 /**
1045 1422 * Update Donor Information when User Profile is updated from admin.
1046 1423 * Note: for internal use only.
1047 1424 *
1425 + * @since 2.0
1426 + *
1048 1427 * @param int $user_id
1049 1428 *
1050 1429 * @access public
1051 - * @since 2.0
1052 - *
1053 1430 * @return bool
1054 1431 */
1055 1432 function give_update_donor_name_on_user_update( $user_id = 0 ) {
1056 1433
@@ -1068,11 +1445,14 @@
1068 1445 $last_name = ( $_POST['last_name'] ) ? give_clean( $_POST['last_name'] ) : get_user_meta( $user_id, 'last_name', true );
1069 1446 $full_name = strip_tags( wp_unslash( trim( "{$first_name} {$last_name}" ) ) );
1070 1447
1071 1448 // Assign User First name and Last name to Donor.
1072 - Give()->donors->update( $donor->id, array(
1073 - 'name' => $full_name,
1074 - ) );
1449 + Give()->donors->update(
1450 + $donor->id,
1451 + [
1452 + 'name' => $full_name,
1453 + ]
1454 + );
1075 1455 Give()->donor_meta->update_meta( $donor->id, '_give_donor_first_name', $first_name );
1076 1456 Give()->donor_meta->update_meta( $donor->id, '_give_donor_last_name', $last_name );
1077 1457
1078 1458 }
@@ -1088,11 +1468,12 @@
1088 1468 *
1089 1469 * @since 1.4.3
1090 1470 * @access public
1091 1471 *
1092 - * @param int $user_id User ID.
1093 - * @param WP_User|bool $old_user_data User data.
1472 + * @param WP_User|bool $old_user_data User data.
1094 1473 *
1474 + * @param int $user_id User ID.
1475 + *
1095 1476 * @return bool
1096 1477 */
1097 1478 function give_update_donor_email_on_user_update( $user_id = 0, $old_user_data = false ) {
1098 1479
@@ -1105,11 +1486,14 @@
1105 1486 $user = get_userdata( $user_id );
1106 1487
1107 1488 if ( ! empty( $user ) && $user->user_email !== $donor->email ) {
1108 1489
1109 - $success = Give()->donors->update( $donor->id, array(
1110 - 'email' => $user->user_email,
1111 - ) );
1490 + $success = Give()->donors->update(
1491 + $donor->id,
1492 + [
1493 + 'email' => $user->user_email,
1494 + ]
1495 + );
1112 1496
1113 1497 if ( $success ) {
1114 1498 // Update some payment meta if we need to
1115 1499 $payments_array = explode( ',', $donor->payment_ids );
@@ -1127,10 +1511,11 @@
1127 1511 * Fires after updating donor email on user update.
1128 1512 *
1129 1513 * @since 1.4.3
1130 1514 *
1131 - * @param WP_User $user WordPress User object.
1132 - * @param Give_Donor $donor Give donor object.
1515 + * @param Give_Donor $donor Give donor object.
1516 + *
1517 + * @param WP_User $user WordPress User object.
1133 1518 */
1134 1519 do_action( 'give_update_donor_email_on_user_update', $user, $donor );
1135 1520
1136 1521 }
@@ -1144,18 +1529,193 @@
1144 1529 /**
1145 1530 * Flushes Give's cache.
1146 1531 */
1147 1532 function give_cache_flush() {
1148 - $result = Give_Cache::flush_cache();
1533 + if (!is_user_logged_in() || !current_user_can('manage_give_settings')) {
1534 + wp_die();
1535 + }
1149 1536
1150 - if ( $result ) {
1151 - wp_send_json_success( array(
1152 - 'message' => __( 'Cache flushed successfully.', 'give' ),
1153 - ));
1154 - } else {
1155 - wp_send_json_error( array(
1156 - 'message' => __( 'An error occured while flushing the cache.', 'give' ),
1157 - ));
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;
1158 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 + }
1159 1582 }
1160 1583
1161 -add_action( 'wp_ajax_give_cache_flush', 'give_cache_flush', 10, 0 );
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 +