PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.7.5
GiveWP – Donation Plugin and Fundraising Platform v2.7.5
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 5 years ago api 6 years ago database 6 years ago deprecated 6 years ago donors 5 years ago emails 6 years ago forms 5 years ago frontend 6 years ago gateways 6 years ago libraries 6 years ago payments 5 years ago actions.php 6 years ago ajax-functions.php 5 years ago class-give-async-process.php 6 years ago class-give-background-updater.php 6 years ago class-give-cache-setting.php 6 years ago class-give-cache.php 6 years ago class-give-cli-commands.php 6 years ago class-give-comment.php 6 years ago class-give-cron.php 6 years ago class-give-donate-form.php 6 years ago class-give-donor.php 6 years ago class-give-email-access.php 6 years ago class-give-license-handler.php 6 years ago class-give-logging.php 6 years ago class-give-readme-parser.php 6 years ago class-give-roles.php 6 years ago class-give-scripts.php 6 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 6 years ago class-notices.php 6 years ago country-functions.php 5 years ago currencies-list.php 6 years ago currency-functions.php 6 years ago error-tracking.php 6 years ago filters.php 6 years ago formatting.php 6 years ago install.php 6 years ago login-register.php 6 years ago misc-functions.php 5 years ago plugin-compatibility.php 6 years ago post-types.php 6 years ago price-functions.php 6 years ago process-donation.php 5 years ago setting-functions.php 6 years ago shortcodes.php 6 years ago template-functions.php 6 years ago user-functions.php 6 years ago
process-donation.php
1589 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 = array(
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'], array( '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 = array(
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 // Send info to the gateway for payment processing.
206 give_send_to_gateway( $donation_data['gateway'], $donation_data );
207 give_die();
208 }
209
210 add_action( 'give_purchase', 'give_process_donation_form' );
211 add_action( 'wp_ajax_give_process_donation', 'give_process_donation_form' );
212 add_action( 'wp_ajax_nopriv_give_process_donation', 'give_process_donation_form' );
213
214 /**
215 * Verify that when a logged in user makes a donation that the email address used doesn't belong to a different customer.
216 * Note: only for internal use
217 *
218 * @see https://github.com/impress-org/give/issues/4025
219 *
220 * @since 1.7
221 * @since 2.4.2 This function runs independently instead of give_checkout_error_checks hook and also edit donor email.
222 *
223 * @param array $valid_data Validated data submitted for the donation.
224 *
225 * @return void
226 */
227 function give_check_logged_in_user_for_existing_email( &$valid_data ) {
228
229 // Verify that the email address belongs to this donor.
230 if ( is_user_logged_in() ) {
231
232 $donor = new Give_Donor( get_current_user_id(), true );
233
234 // Bailout: check if wp user is existing donor or not.
235 if ( ! $donor->id ) {
236 return;
237 }
238
239 $submitted_email = strtolower( $valid_data['user_email'] );
240
241 $donor_emails = array_map( 'strtolower', $donor->emails );
242 $email_index = array_search( $submitted_email, $donor_emails, true );
243
244 // If donor matched with email then return set formatted email from database.
245 if ( false !== $email_index ) {
246 $valid_data['user_email'] = $donor->emails[ $email_index ];
247
248 return;
249 }
250
251 // If this email address is not registered with this customer, see if it belongs to any other customer.
252 $found_donor = new Give_Donor( $submitted_email );
253
254 if ( $found_donor->id > 0 ) {
255 give_set_error(
256 'give-customer-email-exists',
257 sprintf(
258 /* translators: 1. Donor Email, 2. Submitted Email */
259 __( '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' ),
260 $donor->email,
261 $submitted_email
262 )
263 );
264 }
265 }
266 }
267
268 /**
269 * Process the checkout login form
270 *
271 * @access private
272 * @since 1.0
273 *
274 * @return void
275 */
276 function give_process_form_login() {
277
278 $is_ajax = ! empty( $_POST['give_ajax'] ) ? give_clean( $_POST['give_ajax'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
279 $referrer = wp_get_referer();
280 $user_data = give_donation_form_validate_user_login();
281
282 if ( give_get_errors() || $user_data['user_id'] < 1 ) {
283 if ( $is_ajax ) {
284 /**
285 * Fires when AJAX sends back errors from the donation form.
286 *
287 * @since 1.0
288 */
289 ob_start();
290 do_action( 'give_ajax_donation_errors' );
291 $message = ob_get_contents();
292 ob_end_clean();
293 wp_send_json_error( $message );
294 } else {
295 wp_safe_redirect( $referrer );
296 exit;
297 }
298 }
299
300 give_log_user_in( $user_data['user_id'], $user_data['user_login'], $user_data['user_pass'] );
301
302 if ( $is_ajax ) {
303 $message = Give_Notices::print_frontend_notice(
304 sprintf(
305 /* translators: %s: user first name */
306 esc_html__( 'Welcome %s! You have successfully logged into your account.', 'give' ),
307 ( ! empty( $user_data['user_first'] ) ) ? $user_data['user_first'] : $user_data['user_login']
308 ),
309 false,
310 'success'
311 );
312
313 wp_send_json_success( $message );
314 } else {
315 wp_safe_redirect( $referrer );
316 }
317 }
318
319 add_action( 'wp_ajax_give_process_donation_login', 'give_process_form_login' );
320 add_action( 'wp_ajax_nopriv_give_process_donation_login', 'give_process_form_login' );
321
322 /**
323 * Donation Form Validate Fields.
324 *
325 * @access private
326 * @since 1.0
327 *
328 * @return bool|array
329 */
330 function give_donation_form_validate_fields() {
331
332 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
333
334 // Validate Honeypot First.
335 if ( ! empty( $post_data['give-honeypot'] ) ) {
336 give_set_error( 'invalid_honeypot', esc_html__( 'Honeypot field detected. Go away bad bot!', 'give' ) );
337 }
338
339 // Check spam detect.
340 if (
341 isset( $post_data['action'] )
342 && give_is_spam_donation()
343 ) {
344 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' ) );
345 }
346
347 // Start an array to collect valid data.
348 $valid_data = array(
349 'gateway' => give_donation_form_validate_gateway(), // Gateway fallback (amount is validated here).
350 'need_new_user' => false, // New user flag.
351 'need_user_login' => false, // Login user flag.
352 'logged_user_data' => array(), // Logged user collected data.
353 'new_user_data' => array(), // New user collected data.
354 'login_user_data' => array(), // Login user collected data.
355 'guest_user_data' => array(), // Guest user collected data.
356 'cc_info' => give_donation_form_validate_cc(), // Credit card info.
357 );
358
359 $form_id = (int) $post_data['give-form-id'];
360
361 // Validate agree to terms.
362 if ( give_is_terms_enabled( $form_id ) ) {
363 give_donation_form_validate_agree_to_terms();
364 }
365
366 if ( is_user_logged_in() ) {
367
368 // Collect logged in user data.
369 $valid_data['logged_in_user'] = give_donation_form_validate_logged_in_user();
370 } elseif (
371 isset( $post_data['give-purchase-var'] )
372 && 'needs-to-register' === $post_data['give-purchase-var']
373 && ! empty( $post_data['give_create_account'] )
374 ) {
375
376 // Set new user registration as required.
377 $valid_data['need_new_user'] = true;
378
379 // Validate new user data.
380 $valid_data['new_user_data'] = give_donation_form_validate_new_user();
381 } elseif (
382 isset( $post_data['give-purchase-var'] )
383 && 'needs-to-login' === $post_data['give-purchase-var']
384 ) {
385
386 // Set user login as required.
387 $valid_data['need_user_login'] = true;
388
389 // Validate users login info.
390 $valid_data['login_user_data'] = give_donation_form_validate_user_login();
391 } else {
392
393 // Not registering or logging in, so setup guest user data.
394 $valid_data['guest_user_data'] = give_donation_form_validate_guest_user();
395 }
396
397 // Return collected data.
398 return $valid_data;
399 }
400
401 /**
402 * Detect spam donation.
403 *
404 * @since 1.8.14
405 *
406 * @return bool|mixed
407 */
408 function give_is_spam_donation() {
409 $spam = false;
410
411 $user_agent = (string) isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
412
413 if ( strlen( $user_agent ) < 2 ) {
414 $spam = true;
415 }
416
417 // Allow developer to customized Akismet spam detect API call and it's response.
418 return apply_filters( 'give_spam', $spam );
419 }
420
421 /**
422 * Donation Form Validate Gateway
423 *
424 * Validate the gateway and donation amount.
425 *
426 * @access private
427 * @since 1.0
428 *
429 * @return string
430 */
431 function give_donation_form_validate_gateway() {
432
433 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
434 $form_id = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
435 $amount = ! empty( $post_data['give-amount'] ) ? give_maybe_sanitize_amount( $post_data['give-amount'] ) : 0;
436 $gateway = ! empty( $post_data['give-gateway'] ) ? $post_data['give-gateway'] : 0;
437
438 // Bailout, if payment gateway is not submitted with donation form data.
439 if ( empty( $gateway ) ) {
440
441 give_set_error( 'empty_gateway', __( 'The donation form will process with a valid payment gateway.', 'give' ) );
442
443 } elseif ( ! give_is_gateway_active( $gateway ) ) {
444
445 give_set_error( 'invalid_gateway', __( 'The selected payment gateway is not enabled.', 'give' ) );
446
447 } elseif ( empty( $amount ) ) {
448
449 give_set_error( 'invalid_donation_amount', __( 'Please insert a valid donation amount.', 'give' ) );
450
451 } elseif ( ! give_verify_minimum_price( 'minimum' ) ) {
452
453 give_set_error(
454 'invalid_donation_minimum',
455 sprintf(
456 /* translators: %s: minimum donation amount */
457 __( 'This form has a minimum donation amount of %s.', 'give' ),
458 give_currency_filter(
459 give_format_amount(
460 give_get_form_minimum_price( $form_id ),
461 array(
462 'sanitize' => false,
463 )
464 )
465 )
466 )
467 );
468 } elseif ( ! give_verify_minimum_price( 'maximum' ) ) {
469
470 give_set_error(
471 'invalid_donation_maximum',
472 sprintf(
473 /* translators: %s: Maximum donation amount */
474 __( 'This form has a maximum donation amount of %s.', 'give' ),
475 give_currency_filter(
476 give_format_amount(
477 give_get_form_maximum_price( $form_id ),
478 array(
479 'sanitize' => false,
480 )
481 )
482 )
483 )
484 );
485 } // End if().
486
487 return $gateway;
488
489 }
490
491 /**
492 * Donation Form Validate Minimum or Maximum Donation Amount
493 *
494 * @access private
495 * @since 1.3.6
496 * @since 2.1 Added support for give maximum amount.
497 * @since 2.1.3 Added new filter to modify the return value.
498 *
499 * @param string $amount_range Which amount needs to verify? minimum or maximum.
500 *
501 * @return bool
502 */
503 function give_verify_minimum_price( $amount_range = 'minimum' ) {
504
505 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
506 $form_id = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
507 $amount = ! empty( $post_data['give-amount'] ) ? give_maybe_sanitize_amount( $post_data['give-amount'], array( 'currency' => give_get_currency( $form_id ) ) ) : 0;
508 $price_id = isset( $post_data['give-price-id'] ) ? absint( $post_data['give-price-id'] ) : '';
509
510 $variable_prices = give_has_variable_prices( $form_id );
511 $price_ids = array_map( 'absint', give_get_variable_price_ids( $form_id ) );
512 $verified_stat = false;
513
514 if ( $variable_prices && in_array( $price_id, $price_ids, true ) ) {
515
516 $price_level_amount = give_get_price_option_amount( $form_id, $price_id );
517
518 if ( $price_level_amount == $amount ) {
519 $verified_stat = true;
520 }
521 }
522
523 if ( ! $verified_stat ) {
524 switch ( $amount_range ) {
525 case 'minimum':
526 $verified_stat = ( give_get_form_minimum_price( $form_id ) > $amount ) ? false : true;
527 break;
528 case 'maximum':
529 $verified_stat = ( give_get_form_maximum_price( $form_id ) < $amount ) ? false : true;
530 break;
531 }
532 }
533
534 /**
535 * Filter the verify amount
536 *
537 * @since 2.1.3
538 *
539 * @param bool $verified_stat Was verification passed or not?
540 * @param string $amount_range Type of the amount.
541 * @param integer $form_id Give Donation Form ID.
542 */
543 return apply_filters( 'give_verify_minimum_maximum_price', $verified_stat, $amount_range, $form_id );
544 }
545
546 /**
547 * Donation form validate agree to "Terms and Conditions".
548 *
549 * @access private
550 * @since 1.0
551 *
552 * @return void
553 */
554 function give_donation_form_validate_agree_to_terms() {
555
556 $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.
557
558 // Proceed only, if donor agreed to terms.
559 if ( ! $agree_to_terms ) {
560
561 // User did not agree.
562 give_set_error( 'agree_to_terms', apply_filters( 'give_agree_to_terms_text', __( 'You must agree to the terms and conditions.', 'give' ) ) );
563 }
564 }
565
566 /**
567 * Donation Form Required Fields.
568 *
569 * @access private
570 * @since 1.0
571 *
572 * @param int $form_id Donation Form ID.
573 *
574 * @return array
575 */
576 function give_get_required_fields( $form_id ) {
577
578 $posted_data = give_clean( filter_input_array( INPUT_POST ) );
579 $payment_mode = give_get_chosen_gateway( $form_id );
580
581 $required_fields = array(
582 'give_email' => array(
583 'error_id' => 'invalid_email',
584 'error_message' => __( 'Please enter a valid email address.', 'give' ),
585 ),
586 'give_first' => array(
587 'error_id' => 'invalid_first_name',
588 'error_message' => __( 'Please enter your first name.', 'give' ),
589 ),
590 );
591
592 $name_title_prefix = give_is_name_title_prefix_required( $form_id );
593 if ( $name_title_prefix ) {
594 $required_fields['give_title'] = array(
595 'error_id' => 'invalid_title',
596 'error_message' => __( 'Please enter your title.', 'give' ),
597 );
598 }
599
600 // If credit card fields related actions exists then check for the cc fields validations.
601 if (
602 has_action( "give_{$payment_mode}_cc_form", 'give_get_cc_form' ) ||
603 has_action( 'give_cc_form', 'give_get_cc_form' )
604 ) {
605
606 // Validate card number field for empty check.
607 if (
608 isset( $posted_data['card_number'] ) &&
609 empty( $posted_data['card_number'] )
610 ) {
611 $required_fields['card_number'] = array(
612 'error_id' => 'empty_card_number',
613 'error_message' => __( 'Please enter a credit card number.', 'give' ),
614 );
615 }
616
617 // Validate card cvc field for empty check.
618 if (
619 isset( $posted_data['card_cvc'] ) &&
620 empty( $posted_data['card_cvc'] )
621 ) {
622 $required_fields['card_cvc'] = array(
623 'error_id' => 'empty_card_cvc',
624 'error_message' => __( 'Please enter a credit card CVC information.', 'give' ),
625 );
626 }
627
628 // Validate card name field for empty check.
629 if (
630 isset( $posted_data['card_name'] ) &&
631 empty( $posted_data['card_name'] )
632 ) {
633 $required_fields['card_name'] = array(
634 'error_id' => 'empty_card_name',
635 'error_message' => __( 'Please enter a name of your credit card account holder.', 'give' ),
636 );
637 }
638
639 // Validate card expiry field for empty check.
640 if (
641 isset( $posted_data['card_expiry'] ) &&
642 empty( $posted_data['card_expiry'] )
643 ) {
644 $required_fields['card_expiry'] = array(
645 'error_id' => 'empty_card_expiry',
646 'error_message' => __( 'Please enter a credit card expiry date.', 'give' ),
647 );
648 }
649 }
650
651 $require_address = give_require_billing_address( $payment_mode );
652
653 if ( $require_address ) {
654 $required_fields['card_address'] = array(
655 'error_id' => 'invalid_card_address',
656 'error_message' => __( 'Please enter your primary billing address.', 'give' ),
657 );
658 $required_fields['card_zip'] = array(
659 'error_id' => 'invalid_zip_code',
660 'error_message' => __( 'Please enter your zip / postal code.', 'give' ),
661 );
662 $required_fields['card_city'] = array(
663 'error_id' => 'invalid_city',
664 'error_message' => __( 'Please enter your billing city.', 'give' ),
665 );
666 $required_fields['billing_country'] = array(
667 'error_id' => 'invalid_country',
668 'error_message' => __( 'Please select your billing country.', 'give' ),
669 );
670
671 $required_fields['card_state'] = array(
672 'error_id' => 'invalid_state',
673 'error_message' => __( 'Please enter billing state / province / County.', 'give' ),
674 );
675
676 $country = ! empty( $_POST['billing_country'] ) ? give_clean( $_POST['billing_country'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
677
678 // Check if billing country already exists.
679 if ( $country ) {
680
681 // Check if states is empty or not.
682 if ( array_key_exists( $country, give_states_not_required_country_list() ) ) {
683 // If states is empty remove the required fields of state in billing cart.
684 unset( $required_fields['card_state'] );
685 }
686
687 // Check if city is empty or not.
688 if ( array_key_exists( $country, give_city_not_required_country_list() ) ) {
689 // If states is empty remove the required fields of city in billing cart.
690 unset( $required_fields['card_city'] );
691 }
692
693 // Check if country is without post codes.
694 if ( array_key_exists( $country, give_get_country_list_without_postcodes() ) ) {
695 // If country is on the list, zip code is not required.
696 unset( $required_fields['card_zip'] );
697 }
698 }
699 } // End if().
700
701 if ( give_is_company_field_enabled( $form_id ) ) {
702 $form_option = give_get_meta( $form_id, '_give_company_field', true );
703 $global_setting = give_get_option( 'company_field' );
704
705 $is_company_field_required = false;
706
707 if ( ! empty( $form_option ) && give_is_setting_enabled( $form_option, array( 'required' ) ) ) {
708 $is_company_field_required = true;
709
710 } elseif ( 'global' === $form_option && give_is_setting_enabled( $global_setting, array( 'required' ) ) ) {
711 $is_company_field_required = true;
712
713 } elseif ( empty( $form_option ) && give_is_setting_enabled( $global_setting, array( 'required' ) ) ) {
714 $is_company_field_required = true;
715
716 }
717
718 if ( $is_company_field_required ) {
719 $required_fields['give_company_name'] = array(
720 'error_id' => 'invalid_company',
721 'error_message' => __( 'Please enter Company Name.', 'give' ),
722 );
723 }
724 }
725
726 /**
727 * Filters the donation form required field.
728 *
729 * @since 1.7
730 */
731 $required_fields = apply_filters( 'give_donation_form_required_fields', $required_fields, $form_id );
732
733 return $required_fields;
734
735 }
736
737 /**
738 * Check if the Billing Address is required
739 *
740 * @since 1.0.1
741 *
742 * @param string $payment_mode Payment Mode.
743 *
744 * @return bool
745 */
746 function give_require_billing_address( $payment_mode ) {
747
748 $return = false;
749 $billing_country = ! empty( $_POST['billing_country'] ) ? give_clean( $_POST['billing_country'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
750
751 if ( $billing_country || did_action( "give_{$payment_mode}_cc_form" ) || did_action( 'give_cc_form' ) ) {
752 $return = true;
753 }
754
755 // Let payment gateways and other extensions determine if address fields should be required.
756 return apply_filters( 'give_require_billing_address', $return );
757
758 }
759
760 /**
761 * Donation Form Validate Logged In User.
762 *
763 * @access private
764 * @since 1.0
765 *
766 * @return array
767 */
768 function give_donation_form_validate_logged_in_user() {
769
770 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
771 $user_id = get_current_user_id();
772 $form_id = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
773
774 // Start empty array to collect valid user data.
775 $valid_user_data = array(
776
777 // Assume there will be errors.
778 'user_id' => - 1,
779 );
780
781 // Proceed only, if valid $user_id found.
782 if ( $user_id > 0 ) {
783
784 // Get the logged in user data.
785 $user_data = get_userdata( $user_id );
786
787 // Validate Required Form Fields.
788 give_validate_required_form_fields( $form_id );
789
790 // Verify data.
791 if ( is_object( $user_data ) && $user_data->ID > 0 ) {
792 // Collected logged in user data.
793 $valid_user_data = array(
794 'user_id' => $user_id,
795 'user_email' => ! empty( $post_data['give_email'] )
796 ? sanitize_email( $post_data['give_email'] )
797 : $user_data->user_email,
798 'user_first' => ! empty( $post_data['give_first'] )
799 ? $post_data['give_first']
800 : $user_data->first_name,
801 'user_last' => ! empty( $post_data['give_last'] )
802 ? $post_data['give_last']
803 : $user_data->last_name,
804 );
805
806 // Validate essential form fields.
807 give_donation_form_validate_name_fields( $post_data );
808
809 give_check_logged_in_user_for_existing_email( $valid_user_data );
810
811 if ( ! is_email( $valid_user_data['user_email'] ) ) {
812 give_set_error( 'email_invalid', esc_html__( 'Invalid email.', 'give' ) );
813 }
814 } else {
815
816 // Set invalid user information error.
817 give_set_error( 'invalid_user', esc_html__( 'The user information is invalid.', 'give' ) );
818 }
819 }
820
821 // Return user data.
822 return $valid_user_data;
823 }
824
825 /**
826 * Donate Form Validate New User
827 *
828 * @access private
829 * @since 1.0
830 *
831 * @return array
832 */
833 function give_donation_form_validate_new_user() {
834 // Default user data.
835 $auto_generated_password = wp_generate_password();
836 $default_user_data = array(
837 'give-form-id' => '',
838 'user_id' => - 1, // Assume there will be errors.
839 'user_first' => '',
840 'user_last' => '',
841 'give_user_login' => false,
842 'give_email' => false,
843 'give_user_pass' => $auto_generated_password,
844 'give_user_pass_confirm' => $auto_generated_password,
845 );
846
847 // Get data.
848 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
849 $user_data = wp_parse_args( $post_data, $default_user_data );
850
851 $form_id = absint( $user_data['give-form-id'] );
852 $nonce = ! empty( $post_data['give-form-user-register-hash'] ) ? $post_data['give-form-user-register-hash'] : '';
853
854 // Validate user creation nonce.
855 if ( ! wp_verify_nonce( $nonce, "give_form_create_user_nonce_{$form_id}" ) ) {
856 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' ) );
857 }
858
859 $registering_new_user = false;
860
861 give_donation_form_validate_name_fields( $user_data );
862
863 // Start an empty array to collect valid user data.
864 $valid_user_data = array(
865
866 // Assume there will be errors.
867 'user_id' => - 1,
868
869 // Get first name.
870 'user_first' => $user_data['give_first'],
871
872 // Get last name.
873 'user_last' => $user_data['give_last'],
874
875 // Get Password.
876 'user_pass' => $user_data['give_user_pass'],
877 );
878
879 // Validate Required Form Fields.
880 give_validate_required_form_fields( $form_id );
881
882 // Set Email as Username.
883 $valid_user_data['user_login'] = $user_data['give_email'];
884
885 // Check if we have an email to verify.
886 if ( give_validate_user_email( $user_data['give_email'], $registering_new_user ) ) {
887 $valid_user_data['user_email'] = $user_data['give_email'];
888 }
889
890 return $valid_user_data;
891 }
892
893 /**
894 * Donation Form Validate User Login
895 *
896 * @access private
897 * @since 1.0
898 *
899 * @return array
900 */
901 function give_donation_form_validate_user_login() {
902
903 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
904
905 // Start an array to collect valid user data.
906 $valid_user_data = array(
907
908 // Assume there will be errors.
909 'user_id' => - 1,
910 );
911
912 // Bailout, if Username is empty.
913 if ( empty( $post_data['give_user_login'] ) ) {
914 give_set_error( 'must_log_in', __( 'Please enter your username or email to log in.', 'give' ) );
915
916 return $valid_user_data;
917 }
918
919 $give_user_login = strip_tags( $post_data['give_user_login'] );
920 if ( is_email( $give_user_login ) ) {
921 // Get the user data by email.
922 $user_data = get_user_by( 'email', $give_user_login );
923 } else {
924 // Get the user data by login.
925 $user_data = get_user_by( 'login', $give_user_login );
926 }
927
928 // Check if user exists.
929 if ( $user_data ) {
930
931 // Get password.
932 $user_pass = ! empty( $post_data['give_user_pass'] ) ? $post_data['give_user_pass'] : false;
933
934 // Check user_pass.
935 if ( $user_pass ) {
936
937 // Check if password is valid.
938 if ( ! wp_check_password( $user_pass, $user_data->user_pass, $user_data->ID ) ) {
939
940 $current_page_url = site_url() . '/' . get_page_uri();
941
942 // Incorrect password.
943 give_set_error(
944 'password_incorrect',
945 sprintf(
946 '%1$s <a href="%2$s">%3$s</a>',
947 __( 'The password you entered is incorrect.', 'give' ),
948 wp_lostpassword_url( $current_page_url ),
949 __( 'Reset Password', 'give' )
950 )
951 );
952
953 } else {
954
955 // Repopulate the valid user data array.
956 $valid_user_data = array(
957 'user_id' => $user_data->ID,
958 'user_login' => $user_data->user_login,
959 'user_email' => $user_data->user_email,
960 'user_first' => $user_data->first_name,
961 'user_last' => $user_data->last_name,
962 'user_pass' => $user_pass,
963 );
964 }
965 } else {
966 // Empty password.
967 give_set_error( 'password_empty', __( 'Enter a password.', 'give' ) );
968 }
969 } else {
970 // No username.
971 give_set_error( 'username_incorrect', __( 'The username you entered does not exist.', 'give' ) );
972 } // End if().
973
974 return $valid_user_data;
975 }
976
977 /**
978 * Donation Form Validate Guest User
979 *
980 * @access private
981 * @since 1.0
982 *
983 * @return array
984 */
985 function give_donation_form_validate_guest_user() {
986
987 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
988 $form_id = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
989
990 // Start an array to collect valid user data.
991 $valid_user_data = array(
992 // Set a default id for guests.
993 'user_id' => 0,
994 );
995
996 // Validate name fields.
997 give_donation_form_validate_name_fields( $post_data );
998
999 // Validate Required Form Fields.
1000 give_validate_required_form_fields( $form_id );
1001
1002 // Get the guest email.
1003 $guest_email = ! empty( $post_data['give_email'] ) ? $post_data['give_email'] : false;
1004
1005 // Check email.
1006 if ( $guest_email && strlen( $guest_email ) > 0 ) {
1007
1008 // Validate email.
1009 if ( ! is_email( $guest_email ) ) {
1010
1011 // Invalid email.
1012 give_set_error( 'email_invalid', __( 'Invalid email.', 'give' ) );
1013
1014 } else {
1015
1016 // All is good to go.
1017 $valid_user_data['user_email'] = $guest_email;
1018
1019 // Get user_id from donor if exist.
1020 $donor = new Give_Donor( $guest_email );
1021
1022 if ( $donor->id ) {
1023 $donor_email_index = array_search(
1024 strtolower( $guest_email ),
1025 array_map( 'strtolower', $donor->emails ),
1026 true
1027 );
1028
1029 $valid_user_data['user_id'] = $donor->user_id;
1030
1031 // Set email to original format.
1032 // @see https://github.com/impress-org/give/issues/4025
1033 $valid_user_data['user_email'] = $donor->emails[ $donor_email_index ];
1034 }
1035 }
1036 } else {
1037 // No email.
1038 give_set_error( 'email_empty', __( 'Enter an email.', 'give' ) );
1039 }
1040
1041 return $valid_user_data;
1042 }
1043
1044 /**
1045 * Register And Login New User
1046 *
1047 * @param array $user_data User Data.
1048 *
1049 * @access private
1050 * @since 1.0
1051 *
1052 * @return integer
1053 */
1054 function give_register_and_login_new_user( $user_data = array() ) {
1055 // Verify the array.
1056 if ( empty( $user_data ) ) {
1057 return - 1;
1058 }
1059
1060 if ( give_get_errors() ) {
1061 return - 1;
1062 }
1063
1064 $user_args = apply_filters(
1065 'give_insert_user_args',
1066 array(
1067 'user_login' => isset( $user_data['user_login'] ) ? $user_data['user_login'] : '',
1068 'user_pass' => isset( $user_data['user_pass'] ) ? $user_data['user_pass'] : '',
1069 'user_email' => isset( $user_data['user_email'] ) ? $user_data['user_email'] : '',
1070 'first_name' => isset( $user_data['user_first'] ) ? $user_data['user_first'] : '',
1071 'last_name' => isset( $user_data['user_last'] ) ? $user_data['user_last'] : '',
1072 'user_registered' => date( 'Y-m-d H:i:s' ),
1073 'role' => give_get_option( 'donor_default_user_role', 'give_donor' ),
1074 ),
1075 $user_data
1076 );
1077
1078 // Insert new user.
1079 $user_id = wp_insert_user( $user_args );
1080
1081 // Validate inserted user.
1082 if ( is_wp_error( $user_id ) ) {
1083 return - 1;
1084 }
1085
1086 // Allow themes and plugins to filter the user data.
1087 $user_data = apply_filters( 'give_insert_user_data', $user_data, $user_args );
1088
1089 /**
1090 * Fires after inserting user.
1091 *
1092 * @since 1.0
1093 *
1094 * @param int $user_id User id.
1095 * @param array $user_data Array containing user data.
1096 */
1097 do_action( 'give_insert_user', $user_id, $user_data );
1098
1099 /**
1100 * Filter allow user to alter if user when to login or not when user is register for the first time.
1101 *
1102 * @since 1.8.13
1103 *
1104 * return bool True if login with registration and False if only want to register.
1105 */
1106 if ( true === (bool) apply_filters( 'give_log_user_in_on_register', true ) ) {
1107 // Login new user.
1108 give_log_user_in( $user_id, $user_data['user_login'], $user_data['user_pass'] );
1109 }
1110
1111 // Return user id.
1112 return $user_id;
1113 }
1114
1115 /**
1116 * Get Donation Form User
1117 *
1118 * @param array $valid_data Valid Data.
1119 *
1120 * @access private
1121 * @since 1.0
1122 *
1123 * @return array|bool
1124 */
1125 function give_get_donation_form_user( $valid_data = array() ) {
1126
1127 // Initialize user.
1128 $user = false;
1129 $is_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
1130 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1131
1132 if ( $is_ajax ) {
1133
1134 // Do not create or login the user during the ajax submission (check for errors only).
1135 return true;
1136 } elseif ( is_user_logged_in() ) {
1137
1138 // Set the valid user as the logged in collected data.
1139 $user = $valid_data['logged_in_user'];
1140 } elseif ( true === $valid_data['need_new_user'] || true === $valid_data['need_user_login'] ) {
1141
1142 // New user registration.
1143 if ( true === $valid_data['need_new_user'] ) {
1144
1145 // Set user.
1146 $user = $valid_data['new_user_data'];
1147
1148 // Register and login new user.
1149 $user['user_id'] = give_register_and_login_new_user( $user );
1150
1151 } elseif ( true === $valid_data['need_user_login'] && ! $is_ajax ) {
1152
1153 /**
1154 * The login form is now processed in the give_process_donation_login() function.
1155 * This is still here for backwards compatibility.
1156 * This also allows the old login process to still work if a user removes the checkout login submit button.
1157 *
1158 * 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.
1159 */
1160 $user = $valid_data['login_user_data'];
1161
1162 // Login user.
1163 give_log_user_in( $user['user_id'], $user['user_login'], $user['user_pass'] );
1164 }
1165 } // End if().
1166
1167 // Check guest checkout.
1168 if ( false === $user && false === give_logged_in_only( $post_data['give-form-id'] ) ) {
1169
1170 // Set user.
1171 $user = $valid_data['guest_user_data'];
1172 }
1173
1174 // Verify we have an user.
1175 if ( false === $user || empty( $user ) ) {
1176 return false;
1177 }
1178
1179 // Get user first name.
1180 if ( ! isset( $user['user_first'] ) || strlen( trim( $user['user_first'] ) ) < 1 ) {
1181 $user['user_first'] = isset( $post_data['give_first'] ) ? strip_tags( trim( $post_data['give_first'] ) ) : '';
1182 }
1183
1184 // Get user last name.
1185 if ( ! isset( $user['user_last'] ) || strlen( trim( $user['user_last'] ) ) < 1 ) {
1186 $user['user_last'] = isset( $post_data['give_last'] ) ? strip_tags( trim( $post_data['give_last'] ) ) : '';
1187 }
1188
1189 // Add Title Prefix to user information.
1190 if ( empty( $user['user_title'] ) || strlen( trim( $user['user_title'] ) ) < 1 ) {
1191 $user['user_title'] = ! empty( $post_data['give_title'] ) ? strip_tags( trim( $post_data['give_title'] ) ) : '';
1192 }
1193
1194 // Get the user's billing address details.
1195 $user['address'] = array();
1196 $user['address']['line1'] = ! empty( $post_data['card_address'] ) ? $post_data['card_address'] : false;
1197 $user['address']['line2'] = ! empty( $post_data['card_address_2'] ) ? $post_data['card_address_2'] : false;
1198 $user['address']['city'] = ! empty( $post_data['card_city'] ) ? $post_data['card_city'] : false;
1199 $user['address']['state'] = ! empty( $post_data['card_state'] ) ? $post_data['card_state'] : false;
1200 $user['address']['zip'] = ! empty( $post_data['card_zip'] ) ? $post_data['card_zip'] : false;
1201 $user['address']['country'] = ! empty( $post_data['billing_country'] ) ? $post_data['billing_country'] : false;
1202
1203 if ( empty( $user['address']['country'] ) ) {
1204 $user['address'] = false;
1205 } // End if().
1206
1207 // Return valid user.
1208 return $user;
1209 }
1210
1211 /**
1212 * Validates the credit card info.
1213 *
1214 * @access private
1215 * @since 1.0
1216 *
1217 * @return array
1218 */
1219 function give_donation_form_validate_cc() {
1220
1221 $card_data = give_get_donation_cc_info();
1222
1223 // Validate the card zip.
1224 if ( ! empty( $card_data['card_zip'] ) ) {
1225 if ( ! give_donation_form_validate_cc_zip( $card_data['card_zip'], $card_data['card_country'] ) ) {
1226 give_set_error( 'invalid_cc_zip', __( 'The zip / postal code you entered for your billing address is invalid.', 'give' ) );
1227 }
1228 }
1229
1230 // Ensure no spaces.
1231 if ( ! empty( $card_data['card_number'] ) ) {
1232 $card_data['card_number'] = str_replace( '+', '', $card_data['card_number'] ); // no "+" signs.
1233 $card_data['card_number'] = str_replace( ' ', '', $card_data['card_number'] ); // No spaces.
1234 }
1235
1236 // This should validate card numbers at some point too.
1237 return $card_data;
1238 }
1239
1240 /**
1241 * Get credit card info.
1242 *
1243 * @access private
1244 * @since 1.0
1245 *
1246 * @return array
1247 */
1248 function give_get_donation_cc_info() {
1249
1250 // Sanitize the values submitted with donation form.
1251 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1252
1253 $cc_info = array();
1254 $cc_info['card_name'] = ! empty( $post_data['card_name'] ) ? $post_data['card_name'] : '';
1255 $cc_info['card_number'] = ! empty( $post_data['card_number'] ) ? $post_data['card_number'] : '';
1256 $cc_info['card_cvc'] = ! empty( $post_data['card_cvc'] ) ? $post_data['card_cvc'] : '';
1257 $cc_info['card_exp_month'] = ! empty( $post_data['card_exp_month'] ) ? $post_data['card_exp_month'] : '';
1258 $cc_info['card_exp_year'] = ! empty( $post_data['card_exp_year'] ) ? $post_data['card_exp_year'] : '';
1259 $cc_info['card_address'] = ! empty( $post_data['card_address'] ) ? $post_data['card_address'] : '';
1260 $cc_info['card_address_2'] = ! empty( $post_data['card_address_2'] ) ? $post_data['card_address_2'] : '';
1261 $cc_info['card_city'] = ! empty( $post_data['card_city'] ) ? $post_data['card_city'] : '';
1262 $cc_info['card_state'] = ! empty( $post_data['card_state'] ) ? $post_data['card_state'] : '';
1263 $cc_info['card_country'] = ! empty( $post_data['billing_country'] ) ? $post_data['billing_country'] : '';
1264 $cc_info['card_zip'] = ! empty( $post_data['card_zip'] ) ? $post_data['card_zip'] : '';
1265
1266 // Return cc info.
1267 return $cc_info;
1268 }
1269
1270 /**
1271 * Validate zip code based on country code
1272 *
1273 * @since 1.0
1274 *
1275 * @param int $zip ZIP Code.
1276 * @param string $country_code Country Code.
1277 *
1278 * @return bool|mixed
1279 */
1280 function give_donation_form_validate_cc_zip( $zip = 0, $country_code = '' ) {
1281 $ret = false;
1282
1283 if ( empty( $zip ) || empty( $country_code ) ) {
1284 return $ret;
1285 }
1286
1287 $country_code = strtoupper( $country_code );
1288
1289 $zip_regex = array(
1290 'AD' => 'AD\d{3}',
1291 'AM' => '(37)?\d{4}',
1292 'AR' => '^([A-Z]{1}\d{4}[A-Z]{3}|[A-Z]{1}\d{4}|\d{4})$',
1293 'AS' => '96799',
1294 'AT' => '\d{4}',
1295 '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})$',
1296 'AX' => '22\d{3}',
1297 'AZ' => '\d{4}',
1298 'BA' => '\d{5}',
1299 'BB' => '(BB\d{5})?',
1300 'BD' => '\d{4}',
1301 'BE' => '^[1-9]{1}[0-9]{3}$',
1302 'BG' => '\d{4}',
1303 'BH' => '((1[0-2]|[2-9])\d{2})?',
1304 'BM' => '[A-Z]{2}[ ]?[A-Z0-9]{2}',
1305 'BN' => '[A-Z]{2}[ ]?\d{4}',
1306 'BR' => '\d{5}[\-]?\d{3}',
1307 'BY' => '\d{6}',
1308 'CA' => '^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$',
1309 'CC' => '6799',
1310 'CH' => '^[1-9][0-9][0-9][0-9]$',
1311 'CK' => '\d{4}',
1312 'CL' => '\d{7}',
1313 'CN' => '\d{6}',
1314 'CR' => '\d{4,5}|\d{3}-\d{4}',
1315 'CS' => '\d{5}',
1316 'CV' => '\d{4}',
1317 'CX' => '6798',
1318 'CY' => '\d{4}',
1319 'CZ' => '\d{3}[ ]?\d{2}',
1320 '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',
1321 'DK' => '^([D-d][K-k])?( |-)?[1-9]{1}[0-9]{3}$',
1322 'DO' => '\d{5}',
1323 'DZ' => '\d{5}',
1324 'EC' => '([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?',
1325 'EE' => '\d{5}',
1326 'EG' => '\d{5}',
1327 'ES' => '^([1-9]{2}|[0-9][1-9]|[1-9][0-9])[0-9]{3}$',
1328 'ET' => '\d{4}',
1329 'FI' => '\d{5}',
1330 'FK' => 'FIQQ 1ZZ',
1331 'FM' => '(9694[1-4])([ \-]\d{4})?',
1332 'FO' => '\d{3}',
1333 'FR' => '^(F-)?((2[A|B])|[0-9]{2})[0-9]{3}$',
1334 'GE' => '\d{4}',
1335 'GF' => '9[78]3\d{2}',
1336 'GL' => '39\d{2}',
1337 'GN' => '\d{3}',
1338 'GP' => '9[78][01]\d{2}',
1339 'GR' => '\d{3}[ ]?\d{2}',
1340 'GS' => 'SIQQ 1ZZ',
1341 'GT' => '\d{5}',
1342 'GU' => '969[123]\d([ \-]\d{4})?',
1343 'GW' => '\d{4}',
1344 'HM' => '\d{4}',
1345 'HN' => '(?:\d{5})?',
1346 'HR' => '\d{5}',
1347 'HT' => '\d{4}',
1348 'HU' => '\d{4}',
1349 'ID' => '\d{5}',
1350 'IE' => '((D|DUBLIN)?([1-9]|6[wW]|1[0-8]|2[024]))?',
1351 'IL' => '\d{5}',
1352 'IN' => '^[1-9][0-9][0-9][0-9][0-9][0-9]$', // India.
1353 'IO' => 'BBND 1ZZ',
1354 'IQ' => '\d{5}',
1355 'IS' => '\d{3}',
1356 'IT' => '^(V-|I-)?[0-9]{5}$',
1357 'JO' => '\d{5}',
1358 'JP' => '\d{3}-\d{4}',
1359 'KE' => '\d{5}',
1360 'KG' => '\d{6}',
1361 'KH' => '\d{5}',
1362 'KR' => '\d{3}[\-]\d{3}',
1363 'KW' => '\d{5}',
1364 'KZ' => '\d{6}',
1365 'LA' => '\d{5}',
1366 'LB' => '(\d{4}([ ]?\d{4})?)?',
1367 'LI' => '(948[5-9])|(949[0-7])',
1368 'LK' => '\d{5}',
1369 'LR' => '\d{4}',
1370 'LS' => '\d{3}',
1371 'LT' => '\d{5}',
1372 'LU' => '\d{4}',
1373 'LV' => '\d{4}',
1374 'MA' => '\d{5}',
1375 'MC' => '980\d{2}',
1376 'MD' => '\d{4}',
1377 'ME' => '8\d{4}',
1378 'MG' => '\d{3}',
1379 'MH' => '969[67]\d([ \-]\d{4})?',
1380 'MK' => '\d{4}',
1381 'MN' => '\d{6}',
1382 'MP' => '9695[012]([ \-]\d{4})?',
1383 'MQ' => '9[78]2\d{2}',
1384 'MT' => '[A-Z]{3}[ ]?\d{2,4}',
1385 'MU' => '(\d{3}[A-Z]{2}\d{3})?',
1386 'MV' => '\d{5}',
1387 'MX' => '\d{5}',
1388 'MY' => '\d{5}',
1389 'NC' => '988\d{2}',
1390 'NE' => '\d{4}',
1391 'NF' => '2899',
1392 'NG' => '(\d{6})?',
1393 'NI' => '((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?',
1394 'NL' => '^[1-9][0-9]{3}\s?([a-zA-Z]{2})?$',
1395 'NO' => '\d{4}',
1396 'NP' => '\d{5}',
1397 'NZ' => '\d{4}',
1398 'OM' => '(PC )?\d{3}',
1399 'PF' => '987\d{2}',
1400 'PG' => '\d{3}',
1401 'PH' => '\d{4}',
1402 'PK' => '\d{5}',
1403 'PL' => '\d{2}-\d{3}',
1404 'PM' => '9[78]5\d{2}',
1405 'PN' => 'PCRN 1ZZ',
1406 'PR' => '00[679]\d{2}([ \-]\d{4})?',
1407 'PT' => '\d{4}([\-]\d{3})?',
1408 'PW' => '96940',
1409 'PY' => '\d{4}',
1410 'RE' => '9[78]4\d{2}',
1411 'RO' => '\d{6}',
1412 'RS' => '\d{5}',
1413 'RU' => '\d{6}',
1414 'SA' => '\d{5}',
1415 'SE' => '^(s-|S-){0,1}[0-9]{3}\s?[0-9]{2}$',
1416 'SG' => '\d{6}',
1417 'SH' => '(ASCN|STHL) 1ZZ',
1418 'SI' => '\d{4}',
1419 'SJ' => '\d{4}',
1420 'SK' => '\d{3}[ ]?\d{2}',
1421 'SM' => '4789\d',
1422 'SN' => '\d{5}',
1423 'SO' => '\d{5}',
1424 'SZ' => '[HLMS]\d{3}',
1425 'TC' => 'TKCA 1ZZ',
1426 'TH' => '\d{5}',
1427 'TJ' => '\d{6}',
1428 'TM' => '\d{6}',
1429 'TN' => '\d{4}',
1430 'TR' => '\d{5}',
1431 'TW' => '\d{3}(\d{2})?',
1432 'UA' => '\d{5}',
1433 'UK' => '^(GIR|[A-Z]\d[A-Z\d]??|[A-Z]{2}\d[A-Z\d]??)[ ]??(\d[A-Z]{2})$',
1434 'US' => '^\d{5}([\-]?\d{4})?$',
1435 'UY' => '\d{5}',
1436 'UZ' => '\d{6}',
1437 'VA' => '00120',
1438 'VE' => '\d{4}',
1439 'VI' => '008(([0-4]\d)|(5[01]))([ \-]\d{4})?',
1440 'WF' => '986\d{2}',
1441 'YT' => '976\d{2}',
1442 'YU' => '\d{5}',
1443 'ZA' => '\d{4}',
1444 'ZM' => '\d{5}',
1445 );
1446
1447 if ( ! isset( $zip_regex[ $country_code ] ) || preg_match( '/' . $zip_regex[ $country_code ] . '/i', $zip ) ) {
1448 $ret = true;
1449 }
1450
1451 return apply_filters( 'give_is_zip_valid', $ret, $zip, $country_code );
1452 }
1453
1454 /**
1455 * Validate donation amount and auto set correct donation level id on basis of amount.
1456 *
1457 * 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.
1458 *
1459 * @param array $valid_data List of Valid Data.
1460 *
1461 * @return bool
1462 */
1463 function give_validate_donation_amount( $valid_data ) {
1464
1465 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1466
1467 /* @var Give_Donate_Form $form */
1468 $form = new Give_Donate_Form( $post_data['give-form-id'] );
1469
1470 // Get the form currency.
1471 $form_currency = give_get_currency( $post_data['give-form-id'] );
1472
1473 $donation_level_matched = false;
1474
1475 if ( $form->is_set_type_donation_form() ) {
1476
1477 // Sanitize donation amount.
1478 $post_data['give-amount'] = give_maybe_sanitize_amount( $post_data['give-amount'], array( 'currency' => $form_currency ) );
1479
1480 // Backward compatibility.
1481 if ( $form->is_custom_price( $post_data['give-amount'] ) ) {
1482 $post_data['give-price-id'] = 'custom';
1483 }
1484
1485 $donation_level_matched = true;
1486
1487 } elseif ( $form->is_multi_type_donation_form() ) {
1488
1489 $variable_prices = $form->get_prices();
1490
1491 // Bailout.
1492 if ( ! $variable_prices ) {
1493 return false;
1494 }
1495
1496 // Sanitize donation amount.
1497 $post_data['give-amount'] = give_maybe_sanitize_amount( $post_data['give-amount'], array( 'currency' => $form_currency ) );
1498 $variable_price_option_amount = give_maybe_sanitize_amount( give_get_price_option_amount( $post_data['give-form-id'], $post_data['give-price-id'] ), array( 'currency' => $form_currency ) );
1499 $new_price_id = '';
1500
1501 if ( $post_data['give-amount'] === $variable_price_option_amount ) {
1502 return true;
1503 }
1504
1505 if ( $form->is_custom_price( $post_data['give-amount'] ) ) {
1506 $new_price_id = 'custom';
1507 } else {
1508
1509 // Find correct donation level from all donation levels.
1510 foreach ( $variable_prices as $variable_price ) {
1511
1512 // Sanitize level amount.
1513 $variable_price['_give_amount'] = give_maybe_sanitize_amount( $variable_price['_give_amount'] );
1514
1515 // Set first match donation level ID.
1516 if ( $post_data['give-amount'] === $variable_price['_give_amount'] ) {
1517 $new_price_id = $variable_price['_give_id']['level_id'];
1518 break;
1519 }
1520 }
1521 }
1522
1523 // If donation amount is not find in donation levels then check if form has custom donation feature enable or not.
1524 // If yes then set price id to custom if amount is greater then custom minimum amount (if any).
1525 if ( $post_data['give-price-id'] === $new_price_id ) {
1526 $donation_level_matched = true;
1527 }
1528 } // End if().
1529
1530 if ( ! $donation_level_matched ) {
1531 give_set_error(
1532 'invalid_donation_amount',
1533 sprintf(
1534 /* translators: %s: invalid donation amount */
1535 __( 'Donation amount %s is invalid.', 'give' ),
1536 give_currency_filter(
1537 give_format_amount( $post_data['give-amount'], array( 'sanitize' => false ) )
1538 )
1539 )
1540 );
1541 }
1542 }
1543
1544 add_action( 'give_checkout_error_checks', 'give_validate_donation_amount', 10, 1 );
1545
1546 /**
1547 * Validate Required Form Fields.
1548 *
1549 * @param int $form_id Form ID.
1550 *
1551 * @since 2.0
1552 */
1553 function give_validate_required_form_fields( $form_id ) {
1554
1555 // Sanitize values submitted with donation form.
1556 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1557
1558 // Loop through required fields and show error messages.
1559 foreach ( give_get_required_fields( $form_id ) as $field_name => $value ) {
1560
1561 // Clean Up Data of the input fields.
1562 $field_value = $post_data[ $field_name ];
1563
1564 // Check whether the required field is empty, then show the error message.
1565 if ( in_array( $value, give_get_required_fields( $form_id ), true ) && empty( $field_value ) ) {
1566 give_set_error( $value['error_id'], $value['error_message'] );
1567 }
1568 }
1569 }
1570
1571 /**
1572 * Validates and checks if name fields are valid or not.
1573 *
1574 * @param array $post_data List of post data.
1575 *
1576 * @since 2.1
1577 *
1578 * @return void
1579 */
1580 function give_donation_form_validate_name_fields( $post_data ) {
1581
1582 $is_alpha_first_name = ( ! is_email( $post_data['give_first'] ) && ! preg_match( '~[0-9]~', $post_data['give_first'] ) );
1583 $is_alpha_last_name = ( ! is_email( $post_data['give_last'] ) && ! preg_match( '~[0-9]~', $post_data['give_last'] ) );
1584
1585 if ( ! $is_alpha_first_name || ( ! empty( $post_data['give_last'] ) && ! $is_alpha_last_name ) ) {
1586 give_set_error( 'invalid_name', esc_html__( 'The First Name and Last Name fields cannot contain an email address or numbers.', 'give' ) );
1587 }
1588 }
1589