PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.25.0
GiveWP – Donation Plugin and Fundraising Platform v2.25.0
4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / includes / process-donation.php
give / includes Last commit date
admin 3 years ago api 3 years ago database 5 years ago deprecated 3 years ago donors 3 years ago emails 3 years ago forms 3 years ago frontend 6 years ago gateways 3 years ago libraries 4 years ago payments 4 years ago actions.php 5 years ago ajax-functions.php 4 years ago class-give-async-process.php 6 years ago class-give-background-updater.php 6 years ago class-give-cache-setting.php 4 years ago class-give-cache.php 3 years ago class-give-cli-commands.php 3 years ago class-give-comment.php 6 years ago class-give-cron.php 6 years ago class-give-donate-form.php 4 years ago class-give-donor.php 3 years ago class-give-email-access.php 5 years ago class-give-license-handler.php 4 years ago class-give-logging.php 5 years ago class-give-readme-parser.php 4 years ago class-give-roles.php 6 years ago class-give-scripts.php 4 years ago class-give-session.php 5 years ago class-give-stats.php 6 years ago class-give-template-loader.php 6 years ago class-give-tooltips.php 6 years ago class-give-translation.php 4 years ago class-notices.php 4 years ago country-functions.php 5 years ago currencies-list.php 4 years ago currency-functions.php 3 years ago error-tracking.php 6 years ago filters.php 3 years ago formatting.php 3 years ago install.php 4 years ago login-register.php 4 years ago misc-functions.php 4 years ago plugin-compatibility.php 6 years ago post-types.php 5 years ago price-functions.php 6 years ago process-donation.php 4 years ago setting-functions.php 6 years ago shortcodes.php 3 years ago template-functions.php 4 years ago user-functions.php 3 years ago
process-donation.php
1602 lines
1 <?php
2 /**
3 * Process Donation
4 *
5 * @package Give
6 * @subpackage Functions
7 * @copyright Copyright (c) 2016, GiveWP
8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 * @since 1.0
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Process Donation Form
19 *
20 * Handles the donation form process.
21 *
22 * @access private
23 * @since 1.0
24 *
25 * @throws ReflectionException Exception Handling.
26 *
27 * @return mixed
28 */
29 function give_process_donation_form() {
30
31 // Sanitize Posted Data.
32 $post_data = give_clean( $_POST ); // WPCS: input var ok, CSRF ok.
33
34 // Check whether the form submitted via AJAX or not.
35 $is_ajax = isset( $post_data['give_ajax'] );
36
37 // Verify donation form nonce.
38 if ( ! give_verify_donation_form_nonce( $post_data['give-form-hash'], $post_data['give-form-id'] ) ) {
39 if ( $is_ajax ) {
40 /**
41 * Fires when AJAX sends back errors from the donation form.
42 *
43 * @since 1.0
44 */
45 do_action( 'give_ajax_donation_errors' );
46 give_die();
47 } else {
48 give_send_back_to_checkout();
49 }
50 }
51
52 /**
53 * Fires before processing the donation form.
54 *
55 * @since 1.0
56 */
57 do_action( 'give_pre_process_donation' );
58
59 // Validate the form $_POST data.
60 $valid_data = give_donation_form_validate_fields();
61
62 /**
63 * Fires after validating donation form fields.
64 *
65 * Allow you to hook to donation form errors.
66 *
67 * @since 1.0
68 *
69 * @param bool|array $valid_data Validate fields.
70 * @param array $deprecated Deprecated Since 2.0.2. Use $_POST instead.
71 */
72 $deprecated = $post_data;
73 do_action( 'give_checkout_error_checks', $valid_data, $deprecated );
74
75 // Process the login form.
76 if ( isset( $post_data['give_login_submit'] ) ) {
77 give_process_form_login();
78 }
79
80 // Validate the user.
81 $user = give_get_donation_form_user( $valid_data );
82
83 if ( false === $valid_data || ! $user || give_get_errors() ) {
84 if ( $is_ajax ) {
85 /**
86 * Fires when AJAX sends back errors from the donation form.
87 *
88 * @since 1.0
89 */
90 do_action( 'give_ajax_donation_errors' );
91 give_die();
92 } else {
93 return false;
94 }
95 }
96
97 // If AJAX send back success to proceed with form submission.
98 if ( $is_ajax ) {
99 echo 'success';
100 give_die();
101 }
102
103 /**
104 * Fires action after donation form field validated.
105 *
106 * @since 2.2.0
107 */
108 do_action( 'give_process_donation_after_validation' );
109
110 // Setup user information.
111 $user_info = [
112 'id' => $user['user_id'],
113 'title' => $user['user_title'],
114 'email' => $user['user_email'],
115 'first_name' => $user['user_first'],
116 'last_name' => $user['user_last'],
117 'address' => $user['address'],
118 ];
119
120 $auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
121
122 // Donation form ID.
123 $form_id = isset( $post_data['give-form-id'] ) ? absint( $post_data['give-form-id'] ) : 0;
124
125 $price = isset( $post_data['give-amount'] ) ?
126 (float) apply_filters( 'give_donation_total', give_maybe_sanitize_amount( $post_data['give-amount'], [ 'currency' => give_get_currency( $form_id ) ] ) ) :
127 '0.00';
128 $purchase_key = strtolower( md5( $user['user_email'] . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'give', true ) ) );
129
130 /**
131 * Update donation Purchase key.
132 *
133 * Use this filter to update default donation purchase key
134 * and add prefix in Invoice.
135 *
136 * @since 2.2.4
137 *
138 * @param string $purchase_key
139 * @param string $gateway
140 * @param string $purchase_key
141 *
142 * @return string $purchase_key
143 */
144 $purchase_key = apply_filters(
145 'give_donation_purchase_key',
146 $purchase_key,
147 $valid_data['gateway'],
148 // Use this purchase key value if you want to generate custom donation purchase key
149 // because donation purchase key editable by filters and you may get unedited donation purchase key.
150 $purchase_key
151 );
152
153 // Setup donation information.
154 $donation_data = [
155 'price' => $price,
156 'purchase_key' => $purchase_key,
157 'user_email' => $user['user_email'],
158 'date' => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
159 'user_info' => stripslashes_deep( $user_info ),
160 'post_data' => $post_data,
161 'gateway' => $valid_data['gateway'],
162 'card_info' => $valid_data['cc_info'],
163 ];
164
165 // Add the user data for hooks.
166 $valid_data['user'] = $user;
167
168 /**
169 * Fires before donation form gateway.
170 *
171 * Allow you to hook to donation form before the gateway.
172 *
173 * @since 1.0
174 *
175 * @param array $post_data Array of variables passed via the HTTP POST.
176 * @param array $user_info Array containing basic user information.
177 * @param bool|array $valid_data Validate fields.
178 */
179 do_action( 'give_checkout_before_gateway', $post_data, $user_info, $valid_data );
180
181 // Sanity check for price.
182 if ( ! $donation_data['price'] ) {
183 // Revert to manual.
184 $donation_data['gateway'] = 'manual';
185 $_POST['give-gateway'] = 'manual';
186 }
187
188 /**
189 * Allow the donation data to be modified before it is sent to the gateway.
190 *
191 * @since 1.7
192 */
193 $donation_data = apply_filters( 'give_donation_data_before_gateway', $donation_data, $valid_data );
194
195 // Setup the data we're storing in the donation session.
196 $session_data = $donation_data;
197
198 // Make sure credit card numbers are never stored in sessions.
199 unset( $session_data['card_info']['card_number'] );
200 unset( $session_data['post_data']['card_number'] );
201
202 // Used for showing data to non logged-in users after donation, and for other plugins needing donation data.
203 give_set_purchase_session( $session_data );
204
205 /**
206 * Prevent PHP notices from breaking receipt display.
207 * This is specifically an issue with the Stripe SDK.
208 *
209 * @link https://github.com/impress-org/givewp/issues/5199
210 */
211 ob_start();
212 // Send info to the gateway for payment processing.
213 give_send_to_gateway( $donation_data['gateway'], $donation_data );
214 ob_get_clean();
215 give_die();
216 }
217
218 add_action( 'give_purchase', 'give_process_donation_form' );
219 add_action( 'wp_ajax_give_process_donation', 'give_process_donation_form' );
220 add_action( 'wp_ajax_nopriv_give_process_donation', 'give_process_donation_form' );
221
222 /**
223 * Verify that when a logged in user makes a donation that the email address used doesn't belong to a different customer.
224 * Note: only for internal use
225 *
226 * @see https://github.com/impress-org/give/issues/4025
227 *
228 * @since 1.7
229 * @since 2.4.2 This function runs independently instead of give_checkout_error_checks hook and also edit donor email.
230 *
231 * @param array $valid_data Validated data submitted for the donation.
232 *
233 * @return void
234 */
235 function give_check_logged_in_user_for_existing_email( &$valid_data ) {
236
237 // Verify that the email address belongs to this donor.
238 if ( is_user_logged_in() ) {
239
240 $donor = new Give_Donor( get_current_user_id(), true );
241
242 // Bailout: check if wp user is existing donor or not.
243 if ( ! $donor->id ) {
244 return;
245 }
246
247 $submitted_email = strtolower( $valid_data['user_email'] );
248
249 $donor_emails = array_map( 'strtolower', $donor->emails );
250 $email_index = array_search( $submitted_email, $donor_emails, true );
251
252 // If donor matched with email then return set formatted email from database.
253 if ( false !== $email_index ) {
254 $valid_data['user_email'] = $donor->emails[ $email_index ];
255
256 return;
257 }
258
259 // If this email address is not registered with this customer, see if it belongs to any other customer.
260 $found_donor = new Give_Donor( $submitted_email );
261
262 if ( $found_donor->id > 0 ) {
263 give_set_error(
264 'give-customer-email-exists',
265 sprintf(
266 /* translators: 1. Donor Email, 2. Submitted Email */
267 __( 'You are logged in as %1$s, and are submitting a donation as %2$s, which is an existing donor. To ensure that the email address is tied to the correct donor, please submit this donation from a logged-out browser, or choose another email address.', 'give' ),
268 $donor->email,
269 $submitted_email
270 )
271 );
272 }
273 }
274 }
275
276 /**
277 * Process the checkout login form
278 *
279 * @access private
280 * @since 1.0
281 *
282 * @return void
283 */
284 function give_process_form_login() {
285
286 $is_ajax = ! empty( $_POST['give_ajax'] ) ? give_clean( $_POST['give_ajax'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
287 $referrer = wp_get_referer();
288 $user_data = give_donation_form_validate_user_login();
289
290 if ( give_get_errors() || $user_data['user_id'] < 1 ) {
291 if ( $is_ajax ) {
292 /**
293 * Fires when AJAX sends back errors from the donation form.
294 *
295 * @since 1.0
296 */
297 ob_start();
298 do_action( 'give_ajax_donation_errors' );
299 $message = ob_get_contents();
300 ob_end_clean();
301 wp_send_json_error( $message );
302 } else {
303 wp_safe_redirect( $referrer );
304 exit;
305 }
306 }
307
308 give_log_user_in( $user_data['user_id'], $user_data['user_login'], $user_data['user_pass'] );
309
310 if ( $is_ajax ) {
311 $message = Give_Notices::print_frontend_notice(
312 sprintf(
313 /* translators: %s: user first name */
314 esc_html__( 'Welcome %s! You have successfully logged into your account.', 'give' ),
315 ( ! empty( $user_data['user_first'] ) ) ? $user_data['user_first'] : $user_data['user_login']
316 ),
317 false,
318 'success'
319 );
320
321 wp_send_json_success( $message );
322 } else {
323 wp_safe_redirect( $referrer );
324 }
325 }
326
327 add_action( 'wp_ajax_give_process_donation_login', 'give_process_form_login' );
328 add_action( 'wp_ajax_nopriv_give_process_donation_login', 'give_process_form_login' );
329
330 /**
331 * Donation Form Validate Fields.
332 *
333 * @access private
334 * @since 1.0
335 *
336 * @return bool|array
337 */
338 function give_donation_form_validate_fields() {
339
340 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
341
342 // Validate Honeypot First.
343 if ( ! empty( $post_data['give-honeypot'] ) ) {
344 give_set_error( 'invalid_honeypot', esc_html__( 'Honeypot field detected. Go away bad bot!', 'give' ) );
345 }
346
347 // Check spam detect.
348 if (
349 isset( $post_data['action'] )
350 && give_is_spam_donation()
351 ) {
352 give_set_error( 'spam_donation', __( 'The email you are using has been flagged as one used in SPAM comments or donations by our system. Please try using a different email address or contact the site administrator if you have any questions.', 'give' ) );
353 }
354
355 // Start an array to collect valid data.
356 $valid_data = [
357 'gateway' => give_donation_form_validate_gateway(), // Gateway fallback (amount is validated here).
358 'need_new_user' => false, // New user flag.
359 'need_user_login' => false, // Login user flag.
360 'logged_user_data' => [], // Logged user collected data.
361 'new_user_data' => [], // New user collected data.
362 'login_user_data' => [], // Login user collected data.
363 'guest_user_data' => [], // Guest user collected data.
364 'cc_info' => give_donation_form_validate_cc(), // Credit card info.
365 ];
366
367 $form_id = (int) $post_data['give-form-id'];
368
369 // Validate agree to terms.
370 if ( give_is_terms_enabled( $form_id ) ) {
371 give_donation_form_validate_agree_to_terms();
372 }
373
374 if ( is_user_logged_in() ) {
375
376 // Collect logged in user data.
377 $valid_data['logged_in_user'] = give_donation_form_validate_logged_in_user();
378 } elseif (
379 isset( $post_data['give-purchase-var'] )
380 && 'needs-to-register' === $post_data['give-purchase-var']
381 && ! empty( $post_data['give_create_account'] )
382 ) {
383
384 // Set new user registration as required.
385 $valid_data['need_new_user'] = true;
386
387 // Validate new user data.
388 $valid_data['new_user_data'] = give_donation_form_validate_new_user();
389 } elseif (
390 isset( $post_data['give-purchase-var'] )
391 && 'needs-to-login' === $post_data['give-purchase-var']
392 ) {
393
394 // Set user login as required.
395 $valid_data['need_user_login'] = true;
396
397 // Validate users login info.
398 $valid_data['login_user_data'] = give_donation_form_validate_user_login();
399 } else {
400
401 // Not registering or logging in, so setup guest user data.
402 $valid_data['guest_user_data'] = give_donation_form_validate_guest_user();
403 }
404
405 // Return collected data.
406 return $valid_data;
407 }
408
409 /**
410 * Detect spam donation.
411 *
412 * @since 1.8.14
413 *
414 * @return bool|mixed
415 */
416 function give_is_spam_donation() {
417 $spam = false;
418
419 $user_agent = (string) isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
420
421 if ( strlen( $user_agent ) < 2 ) {
422 $spam = true;
423 }
424
425 // Allow developer to customized Akismet spam detect API call and it's response.
426 return apply_filters( 'give_spam', $spam );
427 }
428
429 /**
430 * Donation Form Validate Gateway
431 *
432 * Validate the gateway and donation amount.
433 *
434 * @access private
435 * @since 1.0
436 *
437 * @return string
438 */
439 function give_donation_form_validate_gateway() {
440
441 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
442 $form_id = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
443 $amount = ! empty( $post_data['give-amount'] ) ? give_maybe_sanitize_amount( $post_data['give-amount'] ) : 0;
444 $gateway = ! empty( $post_data['give-gateway'] ) ? $post_data['give-gateway'] : 0;
445
446 // Bailout, if payment gateway is not submitted with donation form data.
447 if ( empty( $gateway ) ) {
448
449 give_set_error( 'empty_gateway', __( 'The donation form will process with a valid payment gateway.', 'give' ) );
450
451 } elseif ( ! give_is_gateway_active( $gateway ) ) {
452
453 give_set_error( 'invalid_gateway', __( 'The selected payment gateway is not enabled.', 'give' ) );
454
455 } elseif ( empty( $amount ) ) {
456
457 give_set_error( 'invalid_donation_amount', __( 'Please insert a valid donation amount.', 'give' ) );
458
459 } elseif ( ! give_verify_minimum_price( 'minimum' ) ) {
460
461 give_set_error(
462 'invalid_donation_minimum',
463 sprintf(
464 /* translators: %s: minimum donation amount */
465 __( 'This form has a minimum donation amount of %s.', 'give' ),
466 give_currency_filter(
467 give_format_amount(
468 give_get_form_minimum_price( $form_id ),
469 [
470 'sanitize' => false,
471 ]
472 )
473 )
474 )
475 );
476 } elseif ( ! give_verify_minimum_price( 'maximum' ) ) {
477
478 give_set_error(
479 'invalid_donation_maximum',
480 sprintf(
481 /* translators: %s: Maximum donation amount */
482 __( 'This form has a maximum donation amount of %s.', 'give' ),
483 give_currency_filter(
484 give_format_amount(
485 give_get_form_maximum_price( $form_id ),
486 [
487 'sanitize' => false,
488 ]
489 )
490 )
491 )
492 );
493 } // End if().
494
495 return $gateway;
496
497 }
498
499 /**
500 * Donation Form Validate Minimum or Maximum Donation Amount
501 *
502 * @access private
503 * @since 1.3.6
504 * @since 2.1 Added support for give maximum amount.
505 * @since 2.1.3 Added new filter to modify the return value.
506 *
507 * @param string $amount_range Which amount needs to verify? minimum or maximum.
508 *
509 * @return bool
510 */
511 function give_verify_minimum_price( $amount_range = 'minimum' ) {
512
513 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
514 $form_id = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
515 $amount = ! empty( $post_data['give-amount'] ) ? give_maybe_sanitize_amount( $post_data['give-amount'], [ 'currency' => give_get_currency( $form_id ) ] ) : 0;
516 $price_id = isset( $post_data['give-price-id'] ) ? absint( $post_data['give-price-id'] ) : '';
517
518 $variable_prices = give_has_variable_prices( $form_id );
519 $price_ids = array_map( 'absint', give_get_variable_price_ids( $form_id ) );
520 $verified_stat = false;
521
522 if ( $variable_prices && in_array( $price_id, $price_ids, true ) ) {
523
524 $price_level_amount = give_get_price_option_amount( $form_id, $price_id );
525
526 if ( $price_level_amount == $amount ) {
527 $verified_stat = true;
528 }
529 }
530
531 if ( ! $verified_stat ) {
532 switch ( $amount_range ) {
533 case 'minimum':
534 $verified_stat = ( give_get_form_minimum_price( $form_id ) > $amount ) ? false : true;
535 break;
536 case 'maximum':
537 $verified_stat = ( give_get_form_maximum_price( $form_id ) < $amount ) ? false : true;
538 break;
539 }
540 }
541
542 /**
543 * Filter the verify amount
544 *
545 * @since 2.1.3
546 *
547 * @param bool $verified_stat Was verification passed or not?
548 * @param string $amount_range Type of the amount.
549 * @param integer $form_id Give Donation Form ID.
550 */
551 return apply_filters( 'give_verify_minimum_maximum_price', $verified_stat, $amount_range, $form_id );
552 }
553
554 /**
555 * Donation form validate agree to "Terms and Conditions".
556 *
557 * @access private
558 * @since 1.0
559 *
560 * @return void
561 */
562 function give_donation_form_validate_agree_to_terms() {
563
564 $agree_to_terms = ! empty( $_POST['give_agree_to_terms'] ) ? give_clean( $_POST['give_agree_to_terms'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
565
566 // Proceed only, if donor agreed to terms.
567 if ( ! $agree_to_terms ) {
568
569 // User did not agree.
570 give_set_error( 'agree_to_terms', apply_filters( 'give_agree_to_terms_text', __( 'You must agree to the terms and conditions.', 'give' ) ) );
571 }
572 }
573
574 /**
575 * Donation Form Required Fields.
576 *
577 * @access private
578 * @since 1.0
579 *
580 * @param int $form_id Donation Form ID.
581 *
582 * @return array
583 */
584 function give_get_required_fields( $form_id ) {
585
586 $posted_data = give_clean( filter_input_array( INPUT_POST ) );
587 $payment_mode = give_get_chosen_gateway( $form_id );
588
589 $required_fields = [
590 'give_email' => [
591 'error_id' => 'invalid_email',
592 'error_message' => __( 'Please enter a valid email address.', 'give' ),
593 ],
594 'give_first' => [
595 'error_id' => 'invalid_first_name',
596 'error_message' => __( 'Please enter your first name.', 'give' ),
597 ],
598 ];
599
600 $name_title_prefix = give_is_name_title_prefix_required( $form_id );
601 if ( $name_title_prefix ) {
602 $required_fields['give_title'] = [
603 'error_id' => 'invalid_title',
604 'error_message' => __( 'Please enter your title.', 'give' ),
605 ];
606 }
607
608 // If credit card fields related actions exists then check for the cc fields validations.
609 if (
610 has_action( "give_{$payment_mode}_cc_form", 'give_get_cc_form' ) ||
611 has_action( 'give_cc_form', 'give_get_cc_form' )
612 ) {
613
614 // Validate card number field for empty check.
615 if (
616 isset( $posted_data['card_number'] ) &&
617 empty( $posted_data['card_number'] )
618 ) {
619 $required_fields['card_number'] = [
620 'error_id' => 'empty_card_number',
621 'error_message' => __( 'Please enter a credit card number.', 'give' ),
622 ];
623 }
624
625 // Validate card cvc field for empty check.
626 if (
627 isset( $posted_data['card_cvc'] ) &&
628 empty( $posted_data['card_cvc'] )
629 ) {
630 $required_fields['card_cvc'] = [
631 'error_id' => 'empty_card_cvc',
632 'error_message' => __( 'Please enter a credit card CVC information.', 'give' ),
633 ];
634 }
635
636 // Validate card name field for empty check.
637 if (
638 (
639 isset( $posted_data['give_validate_stripe_payment_fields'] ) &&
640 '1' === $posted_data['give_validate_stripe_payment_fields'] &&
641 isset( $posted_data['card_name'] ) &&
642 empty( $posted_data['card_name'] )
643 ) ||
644 (
645 ! isset( $posted_data['give_validate_stripe_payment_fields'] ) &&
646 isset( $posted_data['card_name'] ) &&
647 empty( $posted_data['card_name'] )
648 )
649 ) {
650 $required_fields['card_name'] = [
651 'error_id' => 'empty_card_name',
652 'error_message' => __( 'Please enter a name of your credit card account holder.', 'give' ),
653 ];
654 }
655
656 // Validate card expiry field for empty check.
657 if (
658 isset( $posted_data['card_expiry'] ) &&
659 empty( $posted_data['card_expiry'] )
660 ) {
661 $required_fields['card_expiry'] = [
662 'error_id' => 'empty_card_expiry',
663 'error_message' => __( 'Please enter a credit card expiry date.', 'give' ),
664 ];
665 }
666 }
667
668 $require_address = give_require_billing_address( $payment_mode );
669
670 if ( $require_address ) {
671 $required_fields['card_address'] = [
672 'error_id' => 'invalid_card_address',
673 'error_message' => __( 'Please enter your primary billing address.', 'give' ),
674 ];
675 $required_fields['card_zip'] = [
676 'error_id' => 'invalid_zip_code',
677 'error_message' => __( 'Please enter your zip / postal code.', 'give' ),
678 ];
679 $required_fields['card_city'] = [
680 'error_id' => 'invalid_city',
681 'error_message' => __( 'Please enter your billing city.', 'give' ),
682 ];
683 $required_fields['billing_country'] = [
684 'error_id' => 'invalid_country',
685 'error_message' => __( 'Please select your billing country.', 'give' ),
686 ];
687
688 $required_fields['card_state'] = [
689 'error_id' => 'invalid_state',
690 'error_message' => __( 'Please enter billing state / province / County.', 'give' ),
691 ];
692
693 $country = ! empty( $_POST['billing_country'] ) ? give_clean( $_POST['billing_country'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
694
695 // Check if billing country already exists.
696 if ( $country ) {
697
698 // Check if states is empty or not.
699 if ( array_key_exists( $country, give_states_not_required_country_list() ) ) {
700 // If states is empty remove the required fields of state in billing cart.
701 unset( $required_fields['card_state'] );
702 }
703
704 // Check if city is empty or not.
705 if ( array_key_exists( $country, give_city_not_required_country_list() ) ) {
706 // If states is empty remove the required fields of city in billing cart.
707 unset( $required_fields['card_city'] );
708 }
709
710 // Check if country is without post codes.
711 if ( array_key_exists( $country, give_get_country_list_without_postcodes() ) ) {
712 // If country is on the list, zip code is not required.
713 unset( $required_fields['card_zip'] );
714 }
715 }
716 } // End if().
717
718 if ( give_is_company_field_enabled( $form_id ) ) {
719 $form_option = give_get_meta( $form_id, '_give_company_field', true );
720 $global_setting = give_get_option( 'company_field' );
721
722 $is_company_field_required = false;
723
724 if ( ! empty( $form_option ) && give_is_setting_enabled( $form_option, [ 'required' ] ) ) {
725 $is_company_field_required = true;
726
727 } elseif ( 'global' === $form_option && give_is_setting_enabled( $global_setting, [ 'required' ] ) ) {
728 $is_company_field_required = true;
729
730 } elseif ( empty( $form_option ) && give_is_setting_enabled( $global_setting, [ 'required' ] ) ) {
731 $is_company_field_required = true;
732
733 }
734
735 if ( $is_company_field_required ) {
736 $required_fields['give_company_name'] = [
737 'error_id' => 'invalid_company',
738 'error_message' => __( 'Please enter Company Name.', 'give' ),
739 ];
740 }
741 }
742
743 if ( give_is_last_name_required( $form_id ) ) {
744 $required_fields['give_last'] = [
745 'error_id' => 'invalid_last_name',
746 'error_message' => __( 'Please enter your last name.', 'give' ),
747 ];
748 }
749
750 /**
751 * Filters the donation form required field.
752 *
753 * @since 1.7
754 */
755 $required_fields = apply_filters( 'give_donation_form_required_fields', $required_fields, $form_id );
756
757 return $required_fields;
758
759 }
760
761 /**
762 * Check if the Billing Address is required
763 *
764 * @since 1.0.1
765 *
766 * @param string $payment_mode Payment Mode.
767 *
768 * @return bool
769 */
770 function give_require_billing_address( $payment_mode ) {
771
772 $return = false;
773 $billing_country = ! empty( $_POST['billing_country'] ) ? give_clean( $_POST['billing_country'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
774
775 if ( $billing_country || did_action( "give_{$payment_mode}_cc_form" ) || did_action( 'give_cc_form' ) ) {
776 $return = true;
777 }
778
779 // Let payment gateways and other extensions determine if address fields should be required.
780 return apply_filters( 'give_require_billing_address', $return );
781
782 }
783
784 /**
785 * Donation Form Validate Logged In User.
786 *
787 * @access private
788 * @since 1.0
789 *
790 * @return array
791 */
792 function give_donation_form_validate_logged_in_user() {
793
794 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
795 $user_id = get_current_user_id();
796 $form_id = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
797
798 // Start empty array to collect valid user data.
799 $valid_user_data = [
800
801 // Assume there will be errors.
802 'user_id' => - 1,
803 ];
804
805 // Proceed only, if valid $user_id found.
806 if ( $user_id > 0 ) {
807
808 // Get the logged in user data.
809 $user_data = get_userdata( $user_id );
810
811 // Validate Required Form Fields.
812 give_validate_required_form_fields( $form_id );
813
814 // Verify data.
815 if ( is_object( $user_data ) && $user_data->ID > 0 ) {
816 // Collected logged in user data.
817 $valid_user_data = [
818 'user_id' => $user_id,
819 'user_email' => ! empty( $post_data['give_email'] )
820 ? sanitize_email( $post_data['give_email'] )
821 : $user_data->user_email,
822 'user_first' => ! empty( $post_data['give_first'] )
823 ? $post_data['give_first']
824 : $user_data->first_name,
825 'user_last' => ! empty( $post_data['give_last'] )
826 ? $post_data['give_last']
827 : $user_data->last_name,
828 ];
829
830 // Validate essential form fields.
831 give_donation_form_validate_name_fields( $post_data );
832
833 give_check_logged_in_user_for_existing_email( $valid_user_data );
834
835 if ( ! is_email( $valid_user_data['user_email'] ) ) {
836 give_set_error( 'email_invalid', esc_html__( 'Invalid email.', 'give' ) );
837 }
838 } else {
839
840 // Set invalid user information error.
841 give_set_error( 'invalid_user', esc_html__( 'The user information is invalid.', 'give' ) );
842 }
843 }
844
845 // Return user data.
846 return $valid_user_data;
847 }
848
849 /**
850 * Donate Form Validate New User
851 *
852 * @access private
853 * @since 1.0
854 *
855 * @return array
856 */
857 function give_donation_form_validate_new_user() {
858 // Default user data.
859 $auto_generated_password = wp_generate_password();
860 $default_user_data = [
861 'give-form-id' => '',
862 'user_id' => - 1, // Assume there will be errors.
863 'user_first' => '',
864 'user_last' => '',
865 'give_user_login' => false,
866 'give_email' => false,
867 'give_user_pass' => $auto_generated_password,
868 'give_user_pass_confirm' => $auto_generated_password,
869 ];
870
871 // Get data.
872 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
873 $user_data = wp_parse_args( $post_data, $default_user_data );
874
875 $form_id = absint( $user_data['give-form-id'] );
876 $nonce = ! empty( $post_data['give-form-user-register-hash'] ) ? $post_data['give-form-user-register-hash'] : '';
877
878 // Validate user creation nonce.
879 if ( ! wp_verify_nonce( $nonce, "give_form_create_user_nonce_{$form_id}" ) ) {
880 give_set_error( 'invalid_nonce', __( 'We\'re unable to recognize your session. Please refresh the screen to try again; otherwise contact your website administrator for assistance.', 'give' ) );
881 }
882
883 $registering_new_user = false;
884
885 give_donation_form_validate_name_fields( $user_data );
886
887 // Start an empty array to collect valid user data.
888 $valid_user_data = [
889
890 // Assume there will be errors.
891 'user_id' => - 1,
892
893 // Get first name.
894 'user_first' => $user_data['give_first'],
895
896 // Get last name.
897 'user_last' => $user_data['give_last'],
898
899 // Get Password.
900 'user_pass' => $user_data['give_user_pass'],
901 ];
902
903 // Validate Required Form Fields.
904 give_validate_required_form_fields( $form_id );
905
906 // Set Email as Username.
907 $valid_user_data['user_login'] = $user_data['give_email'];
908
909 // Check if we have an email to verify.
910 if ( give_validate_user_email( $user_data['give_email'], $registering_new_user ) ) {
911 $valid_user_data['user_email'] = $user_data['give_email'];
912 }
913
914 return $valid_user_data;
915 }
916
917 /**
918 * Donation Form Validate User Login
919 *
920 * @access private
921 * @since 1.0
922 *
923 * @return array
924 */
925 function give_donation_form_validate_user_login() {
926
927 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
928
929 // Start an array to collect valid user data.
930 $valid_user_data = [
931
932 // Assume there will be errors.
933 'user_id' => - 1,
934 ];
935
936 // Bailout, if Username is empty.
937 if ( empty( $post_data['give_user_login'] ) ) {
938 give_set_error( 'must_log_in', __( 'Please enter your username or email to log in.', 'give' ) );
939
940 return $valid_user_data;
941 }
942
943 $give_user_login = strip_tags( $post_data['give_user_login'] );
944 if ( is_email( $give_user_login ) ) {
945 // Get the user data by email.
946 $user_data = get_user_by( 'email', $give_user_login );
947 } else {
948 // Get the user data by login.
949 $user_data = get_user_by( 'login', $give_user_login );
950 }
951
952 // Check if user exists.
953 if ( $user_data ) {
954
955 // Get password.
956 $user_pass = ! empty( $post_data['give_user_pass'] ) ? $post_data['give_user_pass'] : false;
957
958 // Check user_pass.
959 if ( $user_pass ) {
960
961 // Check if password is valid.
962 if ( ! wp_check_password( $user_pass, $user_data->user_pass, $user_data->ID ) ) {
963
964 $current_page_url = site_url() . '/' . get_page_uri();
965
966 // Incorrect password.
967 give_set_error(
968 'password_incorrect',
969 sprintf(
970 '%1$s <a href="%2$s">%3$s</a>',
971 __( 'The password you entered is incorrect.', 'give' ),
972 wp_lostpassword_url( $current_page_url ),
973 __( 'Reset Password', 'give' )
974 )
975 );
976
977 } else {
978
979 // Repopulate the valid user data array.
980 $valid_user_data = [
981 'user_id' => $user_data->ID,
982 'user_login' => $user_data->user_login,
983 'user_email' => $user_data->user_email,
984 'user_first' => $user_data->first_name,
985 'user_last' => $user_data->last_name,
986 'user_pass' => $user_pass,
987 ];
988 }
989 } else {
990 // Empty password.
991 give_set_error( 'password_empty', __( 'Enter a password.', 'give' ) );
992 }
993 } else {
994 // No username.
995 give_set_error( 'username_incorrect', __( 'The username you entered does not exist.', 'give' ) );
996 } // End if().
997
998 return $valid_user_data;
999 }
1000
1001 /**
1002 * Donation Form Validate Guest User
1003 *
1004 * @access private
1005 * @since 1.0
1006 *
1007 * @return array
1008 */
1009 function give_donation_form_validate_guest_user() {
1010
1011 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1012 $form_id = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
1013
1014 // Start an array to collect valid user data.
1015 $valid_user_data = [
1016 // Set a default id for guests.
1017 'user_id' => 0,
1018 ];
1019
1020 // Validate name fields.
1021 give_donation_form_validate_name_fields( $post_data );
1022
1023 // Validate Required Form Fields.
1024 give_validate_required_form_fields( $form_id );
1025
1026 // Get the guest email.
1027 $guest_email = ! empty( $post_data['give_email'] ) ? $post_data['give_email'] : false;
1028
1029 // Check email.
1030 if ( $guest_email && strlen( $guest_email ) > 0 ) {
1031
1032 // Validate email.
1033 if ( ! is_email( $guest_email ) ) {
1034
1035 // Invalid email.
1036 give_set_error( 'email_invalid', __( 'Invalid email.', 'give' ) );
1037
1038 } else {
1039
1040 // All is good to go.
1041 $valid_user_data['user_email'] = $guest_email;
1042
1043 // Get user_id from donor if exist.
1044 $donor = new Give_Donor( $guest_email );
1045
1046 if ( $donor->id ) {
1047 $donor_email_index = array_search(
1048 strtolower( $guest_email ),
1049 array_map( 'strtolower', $donor->emails ),
1050 true
1051 );
1052
1053 $valid_user_data['user_id'] = $donor->user_id;
1054
1055 // Set email to original format.
1056 // @see https://github.com/impress-org/give/issues/4025
1057 $valid_user_data['user_email'] = $donor->emails[ $donor_email_index ];
1058 }
1059 }
1060 } else {
1061 // No email.
1062 give_set_error( 'email_empty', __( 'Enter an email.', 'give' ) );
1063 }
1064
1065 return $valid_user_data;
1066 }
1067
1068 /**
1069 * Register And Login New User
1070 *
1071 * @param array $user_data User Data.
1072 *
1073 * @access private
1074 * @since 1.0
1075 *
1076 * @return integer
1077 */
1078 function give_register_and_login_new_user( $user_data = [] ) {
1079 // Verify the array.
1080 if ( empty( $user_data ) ) {
1081 return - 1;
1082 }
1083
1084 if ( give_get_errors() ) {
1085 return - 1;
1086 }
1087
1088 $user_args = apply_filters(
1089 'give_insert_user_args',
1090 [
1091 'user_login' => isset( $user_data['user_login'] ) ? $user_data['user_login'] : '',
1092 'user_pass' => isset( $user_data['user_pass'] ) ? $user_data['user_pass'] : '',
1093 'user_email' => isset( $user_data['user_email'] ) ? $user_data['user_email'] : '',
1094 'first_name' => isset( $user_data['user_first'] ) ? $user_data['user_first'] : '',
1095 'last_name' => isset( $user_data['user_last'] ) ? $user_data['user_last'] : '',
1096 'user_registered' => date( 'Y-m-d H:i:s' ),
1097 'role' => give_get_option( 'donor_default_user_role', 'give_donor' ),
1098 ],
1099 $user_data
1100 );
1101
1102 // Insert new user.
1103 $user_id = wp_insert_user( $user_args );
1104
1105 // Validate inserted user.
1106 if ( is_wp_error( $user_id ) ) {
1107 return - 1;
1108 }
1109
1110 // Allow themes and plugins to filter the user data.
1111 $user_data = apply_filters( 'give_insert_user_data', $user_data, $user_args );
1112
1113 /**
1114 * Fires after inserting user.
1115 *
1116 * @since 1.0
1117 *
1118 * @param int $user_id User id.
1119 * @param array $user_data Array containing user data.
1120 */
1121 do_action( 'give_insert_user', $user_id, $user_data );
1122
1123 /**
1124 * Filter allow user to alter if user when to login or not when user is register for the first time.
1125 *
1126 * @since 1.8.13
1127 *
1128 * return bool True if login with registration and False if only want to register.
1129 */
1130 if ( true === (bool) apply_filters( 'give_log_user_in_on_register', true ) ) {
1131 // Login new user.
1132 give_log_user_in( $user_id, $user_data['user_login'], $user_data['user_pass'] );
1133 }
1134
1135 // Return user id.
1136 return $user_id;
1137 }
1138
1139 /**
1140 * Get Donation Form User
1141 *
1142 * @since 1.0
1143 * @since 2.17.1 Do not run validation check for ajax request expect donation validation ajax request.
1144 *
1145 * @param array $valid_data Valid Data.
1146 *
1147 * @access private
1148 * @return array|bool
1149 */
1150 function give_get_donation_form_user( $valid_data = [] ) {
1151 // Initialize user.
1152 $user = false;
1153 $post_data = give_clean($_POST); // WPCS: input var ok, sanitization ok, CSRF ok.
1154 $is_validating_donation_form_on_ajax = ! empty($_POST['give_ajax']) ? $post_data['give_ajax'] : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
1155
1156 if ( $is_validating_donation_form_on_ajax ) {
1157 // Do not create or login the user during the ajax submission (check for errors only).
1158 return true;
1159 } elseif ( is_user_logged_in() ) {
1160 // Set the valid user as the logged in collected data.
1161 $user = $valid_data['logged_in_user'];
1162 } elseif ( true === $valid_data['need_new_user'] || true === $valid_data['need_user_login'] ) {
1163 // New user registration.
1164 if ( true === $valid_data['need_new_user'] ) {
1165 // Set user.
1166 $user = $valid_data['new_user_data'];
1167
1168 // Register and login new user.
1169 $user['user_id'] = give_register_and_login_new_user($user);
1170 } elseif ( true === $valid_data['need_user_login'] ) {
1171 /**
1172 * The login form is now processed in the give_process_donation_login() function.
1173 * This is still here for backwards compatibility.
1174 * This also allows the old login process to still work if a user removes the checkout login submit button.
1175 *
1176 * This also ensures that the donor is logged in correctly if they click "Donation" instead of submitting the login form, meaning the donor is logged in during the donation process.
1177 */
1178 $user = $valid_data['login_user_data'];
1179
1180 // Login user.
1181 give_log_user_in( $user['user_id'], $user['user_login'], $user['user_pass'] );
1182 }
1183 } // End if().
1184
1185 // Check guest checkout.
1186 if ( false === $user && false === give_logged_in_only( $post_data['give-form-id'] ) ) {
1187
1188 // Set user.
1189 $user = $valid_data['guest_user_data'];
1190 }
1191
1192 // Verify we have an user.
1193 if ( false === $user || empty( $user ) ) {
1194 return false;
1195 }
1196
1197 // Get user first name.
1198 if ( ! isset( $user['user_first'] ) || strlen( trim( $user['user_first'] ) ) < 1 ) {
1199 $user['user_first'] = isset( $post_data['give_first'] ) ? strip_tags( trim( $post_data['give_first'] ) ) : '';
1200 }
1201
1202 // Get user last name.
1203 if ( ! isset( $user['user_last'] ) || strlen( trim( $user['user_last'] ) ) < 1 ) {
1204 $user['user_last'] = isset( $post_data['give_last'] ) ? strip_tags( trim( $post_data['give_last'] ) ) : '';
1205 }
1206
1207 // Add Title Prefix to user information.
1208 if ( empty( $user['user_title'] ) || strlen( trim( $user['user_title'] ) ) < 1 ) {
1209 $user['user_title'] = ! empty( $post_data['give_title'] ) ? strip_tags( trim( $post_data['give_title'] ) ) : '';
1210 }
1211
1212 // Get the user's billing address details.
1213 $user['address'] = [];
1214 $user['address']['line1'] = ! empty( $post_data['card_address'] ) ? $post_data['card_address'] : false;
1215 $user['address']['line2'] = ! empty( $post_data['card_address_2'] ) ? $post_data['card_address_2'] : false;
1216 $user['address']['city'] = ! empty( $post_data['card_city'] ) ? $post_data['card_city'] : false;
1217 $user['address']['state'] = ! empty( $post_data['card_state'] ) ? $post_data['card_state'] : false;
1218 $user['address']['zip'] = ! empty( $post_data['card_zip'] ) ? $post_data['card_zip'] : false;
1219 $user['address']['country'] = ! empty( $post_data['billing_country'] ) ? $post_data['billing_country'] : false;
1220
1221 if ( empty( $user['address']['country'] ) ) {
1222 $user['address'] = false;
1223 } // End if().
1224
1225 // Return valid user.
1226 return $user;
1227 }
1228
1229 /**
1230 * Validates the credit card info.
1231 *
1232 * @access private
1233 * @since 1.0
1234 *
1235 * @return array
1236 */
1237 function give_donation_form_validate_cc() {
1238
1239 $card_data = give_get_donation_cc_info();
1240
1241 // Validate the card zip.
1242 if ( ! empty( $card_data['card_zip'] ) ) {
1243 if ( ! give_donation_form_validate_cc_zip( $card_data['card_zip'], $card_data['card_country'] ) ) {
1244 give_set_error( 'invalid_cc_zip', __( 'The zip / postal code you entered for your billing address is invalid.', 'give' ) );
1245 }
1246 }
1247
1248 // Ensure no spaces.
1249 if ( ! empty( $card_data['card_number'] ) ) {
1250 $card_data['card_number'] = str_replace( '+', '', $card_data['card_number'] ); // no "+" signs.
1251 $card_data['card_number'] = str_replace( ' ', '', $card_data['card_number'] ); // No spaces.
1252 }
1253
1254 // This should validate card numbers at some point too.
1255 return $card_data;
1256 }
1257
1258 /**
1259 * Get credit card info.
1260 *
1261 * @access private
1262 * @since 1.0
1263 *
1264 * @return array
1265 */
1266 function give_get_donation_cc_info() {
1267
1268 // Sanitize the values submitted with donation form.
1269 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1270
1271 $cc_info = [];
1272 $cc_info['card_name'] = ! empty( $post_data['card_name'] ) ? $post_data['card_name'] : '';
1273 $cc_info['card_number'] = ! empty( $post_data['card_number'] ) ? $post_data['card_number'] : '';
1274 $cc_info['card_cvc'] = ! empty( $post_data['card_cvc'] ) ? $post_data['card_cvc'] : '';
1275 $cc_info['card_exp_month'] = ! empty( $post_data['card_exp_month'] ) ? $post_data['card_exp_month'] : '';
1276 $cc_info['card_exp_year'] = ! empty( $post_data['card_exp_year'] ) ? $post_data['card_exp_year'] : '';
1277 $cc_info['card_address'] = ! empty( $post_data['card_address'] ) ? $post_data['card_address'] : '';
1278 $cc_info['card_address_2'] = ! empty( $post_data['card_address_2'] ) ? $post_data['card_address_2'] : '';
1279 $cc_info['card_city'] = ! empty( $post_data['card_city'] ) ? $post_data['card_city'] : '';
1280 $cc_info['card_state'] = ! empty( $post_data['card_state'] ) ? $post_data['card_state'] : '';
1281 $cc_info['card_country'] = ! empty( $post_data['billing_country'] ) ? $post_data['billing_country'] : '';
1282 $cc_info['card_zip'] = ! empty( $post_data['card_zip'] ) ? $post_data['card_zip'] : '';
1283
1284 // Return cc info.
1285 return $cc_info;
1286 }
1287
1288 /**
1289 * Validate zip code based on country code
1290 *
1291 * @since 1.0
1292 *
1293 * @param int $zip ZIP Code.
1294 * @param string $country_code Country Code.
1295 *
1296 * @return bool|mixed
1297 */
1298 function give_donation_form_validate_cc_zip( $zip = 0, $country_code = '' ) {
1299 $ret = false;
1300
1301 if ( empty( $zip ) || empty( $country_code ) ) {
1302 return $ret;
1303 }
1304
1305 $country_code = strtoupper( $country_code );
1306
1307 $zip_regex = [
1308 'AD' => 'AD\d{3}',
1309 'AM' => '(37)?\d{4}',
1310 'AR' => '^([A-Z]{1}\d{4}[A-Z]{3}|[A-Z]{1}\d{4}|\d{4})$',
1311 'AS' => '96799',
1312 'AT' => '\d{4}',
1313 'AU' => '^(0[289][0-9]{2})|([1345689][0-9]{3})|(2[0-8][0-9]{2})|(290[0-9])|(291[0-4])|(7[0-4][0-9]{2})|(7[8-9][0-9]{2})$',
1314 'AX' => '22\d{3}',
1315 'AZ' => '\d{4}',
1316 'BA' => '\d{5}',
1317 'BB' => '(BB\d{5})?',
1318 'BD' => '\d{4}',
1319 'BE' => '^[1-9]{1}[0-9]{3}$',
1320 'BG' => '\d{4}',
1321 'BH' => '((1[0-2]|[2-9])\d{2})?',
1322 'BM' => '[A-Z]{2}[ ]?[A-Z0-9]{2}',
1323 'BN' => '[A-Z]{2}[ ]?\d{4}',
1324 'BR' => '\d{5}[\-]?\d{3}',
1325 'BY' => '\d{6}',
1326 'CA' => '^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$',
1327 'CC' => '6799',
1328 'CH' => '^[1-9][0-9][0-9][0-9]$',
1329 'CK' => '\d{4}',
1330 'CL' => '\d{7}',
1331 'CN' => '\d{6}',
1332 'CR' => '\d{4,5}|\d{3}-\d{4}',
1333 'CS' => '\d{5}',
1334 'CV' => '\d{4}',
1335 'CX' => '6798',
1336 'CY' => '\d{4}',
1337 'CZ' => '\d{3}[ ]?\d{2}',
1338 'DE' => '\b((?:0[1-46-9]\d{3})|(?:[1-357-9]\d{4})|(?:[4][0-24-9]\d{3})|(?:[6][013-9]\d{3}))\b',
1339 'DK' => '^([D-d][K-k])?( |-)?[1-9]{1}[0-9]{3}$',
1340 'DO' => '\d{5}',
1341 'DZ' => '\d{5}',
1342 'EC' => '([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?',
1343 'EE' => '\d{5}',
1344 'EG' => '\d{5}',
1345 'ES' => '^([1-9]{2}|[0-9][1-9]|[1-9][0-9])[0-9]{3}$',
1346 'ET' => '\d{4}',
1347 'FI' => '\d{5}',
1348 'FK' => 'FIQQ 1ZZ',
1349 'FM' => '(9694[1-4])([ \-]\d{4})?',
1350 'FO' => '\d{3}',
1351 'FR' => '^(F-)?((2[A|B])|[0-9]{2})[0-9]{3}$',
1352 'GE' => '\d{4}',
1353 'GF' => '9[78]3\d{2}',
1354 'GL' => '39\d{2}',
1355 'GN' => '\d{3}',
1356 'GP' => '9[78][01]\d{2}',
1357 'GR' => '\d{3}[ ]?\d{2}',
1358 'GS' => 'SIQQ 1ZZ',
1359 'GT' => '\d{5}',
1360 'GU' => '969[123]\d([ \-]\d{4})?',
1361 'GW' => '\d{4}',
1362 'HM' => '\d{4}',
1363 'HN' => '(?:\d{5})?',
1364 'HR' => '\d{5}',
1365 'HT' => '\d{4}',
1366 'HU' => '\d{4}',
1367 'ID' => '\d{5}',
1368 'IE' => '((D|DUBLIN)?([1-9]|6[wW]|1[0-8]|2[024]))?',
1369 'IL' => '\d{5}',
1370 'IN' => '^[1-9][0-9][0-9][0-9][0-9][0-9]$', // India.
1371 'IO' => 'BBND 1ZZ',
1372 'IQ' => '\d{5}',
1373 'IS' => '\d{3}',
1374 'IT' => '^(V-|I-)?[0-9]{5}$',
1375 'JO' => '\d{5}',
1376 'JP' => '\d{3}-\d{4}',
1377 'KE' => '\d{5}',
1378 'KG' => '\d{6}',
1379 'KH' => '\d{5}',
1380 'KR' => '\d{5}',
1381 'KW' => '\d{5}',
1382 'KZ' => '\d{6}',
1383 'LA' => '\d{5}',
1384 'LB' => '(\d{4}([ ]?\d{4})?)?',
1385 'LI' => '(948[5-9])|(949[0-7])',
1386 'LK' => '\d{5}',
1387 'LR' => '\d{4}',
1388 'LS' => '\d{3}',
1389 'LT' => '\d{5}',
1390 'LU' => '\d{4}',
1391 'LV' => '\d{4}',
1392 'MA' => '\d{5}',
1393 'MC' => '980\d{2}',
1394 'MD' => '\d{4}',
1395 'ME' => '8\d{4}',
1396 'MG' => '\d{3}',
1397 'MH' => '969[67]\d([ \-]\d{4})?',
1398 'MK' => '\d{4}',
1399 'MN' => '\d{6}',
1400 'MP' => '9695[012]([ \-]\d{4})?',
1401 'MQ' => '9[78]2\d{2}',
1402 'MT' => '[A-Z]{3}[ ]?\d{2,4}',
1403 'MU' => '(\d{3}[A-Z]{2}\d{3})?',
1404 'MV' => '\d{5}',
1405 'MX' => '\d{5}',
1406 'MY' => '\d{5}',
1407 'NC' => '988\d{2}',
1408 'NE' => '\d{4}',
1409 'NF' => '2899',
1410 'NG' => '(\d{6})?',
1411 'NI' => '((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?',
1412 'NL' => '^[1-9][0-9]{3}\s?([a-zA-Z]{2})?$',
1413 'NO' => '\d{4}',
1414 'NP' => '\d{5}',
1415 'NZ' => '\d{4}',
1416 'OM' => '(PC )?\d{3}',
1417 'PF' => '987\d{2}',
1418 'PG' => '\d{3}',
1419 'PH' => '\d{4}',
1420 'PK' => '\d{5}',
1421 'PL' => '\d{2}-\d{3}',
1422 'PM' => '9[78]5\d{2}',
1423 'PN' => 'PCRN 1ZZ',
1424 'PR' => '00[679]\d{2}([ \-]\d{4})?',
1425 'PT' => '\d{4}([\-]\d{3})?',
1426 'PW' => '96940',
1427 'PY' => '\d{4}',
1428 'RE' => '9[78]4\d{2}',
1429 'RO' => '\d{6}',
1430 'RS' => '\d{5}',
1431 'RU' => '\d{6}',
1432 'SA' => '\d{5}',
1433 'SE' => '^(s-|S-){0,1}[0-9]{3}\s?[0-9]{2}$',
1434 'SG' => '\d{6}',
1435 'SH' => '(ASCN|STHL) 1ZZ',
1436 'SI' => '\d{4}',
1437 'SJ' => '\d{4}',
1438 'SK' => '\d{3}[ ]?\d{2}',
1439 'SM' => '4789\d',
1440 'SN' => '\d{5}',
1441 'SO' => '\d{5}',
1442 'SZ' => '[HLMS]\d{3}',
1443 'TC' => 'TKCA 1ZZ',
1444 'TH' => '\d{5}',
1445 'TJ' => '\d{6}',
1446 'TM' => '\d{6}',
1447 'TN' => '\d{4}',
1448 'TR' => '\d{5}',
1449 'TW' => '\d{3}(\d{2})?',
1450 'UA' => '\d{5}',
1451 'UK' => '^(GIR|[A-Z]\d[A-Z\d]??|[A-Z]{2}\d[A-Z\d]??)[ ]??(\d[A-Z]{2})$',
1452 'US' => '^\d{5}([\-]?\d{4})?$',
1453 'UY' => '\d{5}',
1454 'UZ' => '\d{6}',
1455 'VA' => '00120',
1456 'VE' => '\d{4}',
1457 'VI' => '008(([0-4]\d)|(5[01]))([ \-]\d{4})?',
1458 'WF' => '986\d{2}',
1459 'YT' => '976\d{2}',
1460 'YU' => '\d{5}',
1461 'ZA' => '\d{4}',
1462 'ZM' => '\d{5}',
1463 ];
1464
1465 if ( ! isset( $zip_regex[ $country_code ] ) || preg_match( '/' . $zip_regex[ $country_code ] . '/i', $zip ) ) {
1466 $ret = true;
1467 }
1468
1469 return apply_filters( 'give_is_zip_valid', $ret, $zip, $country_code );
1470 }
1471
1472 /**
1473 * Validate donation amount and auto set correct donation level id on basis of amount.
1474 *
1475 * Note: If amount does not match to donation level amount then level id will be auto select to first match level id on basis of amount.
1476 *
1477 * @param array $valid_data List of Valid Data.
1478 *
1479 * @return bool
1480 */
1481 function give_validate_donation_amount( $valid_data ) {
1482
1483 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1484
1485 /* @var Give_Donate_Form $form */
1486 $form = new Give_Donate_Form( $post_data['give-form-id'] );
1487
1488 // Get the form currency.
1489 $form_currency = give_get_currency( $post_data['give-form-id'] );
1490
1491 $donation_level_matched = false;
1492
1493 if ( $form->is_set_type_donation_form() ) {
1494
1495 // Sanitize donation amount.
1496 $post_data['give-amount'] = give_maybe_sanitize_amount( $post_data['give-amount'], [ 'currency' => $form_currency ] );
1497
1498 // Backward compatibility.
1499 if ( $form->is_custom_price( $post_data['give-amount'] ) ) {
1500 $post_data['give-price-id'] = 'custom';
1501 }
1502
1503 $donation_level_matched = true;
1504
1505 } elseif ( $form->is_multi_type_donation_form() ) {
1506
1507 $variable_prices = $form->get_prices();
1508
1509 // Bailout.
1510 if ( ! $variable_prices ) {
1511 return false;
1512 }
1513
1514 // Sanitize donation amount.
1515 $post_data['give-amount'] = give_maybe_sanitize_amount( $post_data['give-amount'], [ 'currency' => $form_currency ] );
1516 $variable_price_option_amount = give_maybe_sanitize_amount( give_get_price_option_amount( $post_data['give-form-id'], $post_data['give-price-id'] ), [ 'currency' => $form_currency ] );
1517 $new_price_id = '';
1518
1519 if ( $post_data['give-amount'] === $variable_price_option_amount ) {
1520 return true;
1521 }
1522
1523 if ( $form->is_custom_price( $post_data['give-amount'] ) ) {
1524 $new_price_id = 'custom';
1525 } else {
1526
1527 // Find correct donation level from all donation levels.
1528 foreach ( $variable_prices as $variable_price ) {
1529
1530 // Sanitize level amount.
1531 $variable_price['_give_amount'] = give_maybe_sanitize_amount( $variable_price['_give_amount'] );
1532
1533 // Set first match donation level ID.
1534 if ( $post_data['give-amount'] === $variable_price['_give_amount'] ) {
1535 $new_price_id = $variable_price['_give_id']['level_id'];
1536 break;
1537 }
1538 }
1539 }
1540
1541 // If donation amount is not find in donation levels then check if form has custom donation feature enable or not.
1542 // If yes then set price id to custom if amount is greater then custom minimum amount (if any).
1543 if ( $post_data['give-price-id'] === $new_price_id ) {
1544 $donation_level_matched = true;
1545 }
1546 } // End if().
1547
1548 if ( ! $donation_level_matched ) {
1549 give_set_error(
1550 'invalid_donation_amount',
1551 sprintf(
1552 /* translators: %s: invalid donation amount */
1553 __( 'Donation amount %s is invalid.', 'give' ),
1554 give_currency_filter(
1555 give_format_amount( $post_data['give-amount'], [ 'sanitize' => false ] )
1556 )
1557 )
1558 );
1559 }
1560 }
1561
1562 add_action( 'give_checkout_error_checks', 'give_validate_donation_amount', 10, 1 );
1563
1564 /**
1565 * Validate Required Form Fields.
1566 *
1567 * @param int $form_id Form ID.
1568 *
1569 * @since 2.0
1570 */
1571 function give_validate_required_form_fields( $form_id ) {
1572 // Sanitize values submitted with donation form.
1573 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1574 $requiredFormFields = give_get_required_fields( $form_id );
1575
1576 // Loop through required fields and show error messages.
1577 foreach ( $requiredFormFields as $field_name => $value ) {
1578 if ( empty( $post_data[ $field_name ] ) ) {
1579 give_set_error( $value['error_id'], $value['error_message'] );
1580 }
1581 }
1582 }
1583
1584 /**
1585 * Validates and checks if name fields are valid or not.
1586 *
1587 * @param array $post_data List of post data.
1588 *
1589 * @since 2.1
1590 *
1591 * @return void
1592 */
1593 function give_donation_form_validate_name_fields( $post_data ) {
1594
1595 $is_alpha_first_name = ( ! is_email( $post_data['give_first'] ) && ! preg_match( '~[0-9]~', $post_data['give_first'] ) );
1596 $is_alpha_last_name = ( ! is_email( $post_data['give_last'] ) && ! preg_match( '~[0-9]~', $post_data['give_last'] ) );
1597
1598 if ( ! $is_alpha_first_name || ( ! empty( $post_data['give_last'] ) && ! $is_alpha_last_name ) ) {
1599 give_set_error( 'invalid_name', esc_html__( 'The First Name and Last Name fields cannot contain an email address or numbers.', 'give' ) );
1600 }
1601 }
1602