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