PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.1.7
GiveWP – Donation Plugin and Fundraising Platform v2.1.7
4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 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 8 years ago api 8 years ago deprecated 8 years ago donors 8 years ago emails 8 years ago forms 8 years ago gateways 8 years ago libraries 8 years ago payments 8 years ago actions.php 8 years ago ajax-functions.php 8 years ago class-give-async-process.php 8 years ago class-give-background-updater.php 8 years ago class-give-cache.php 8 years ago class-give-cli-commands.php 8 years ago class-give-cron.php 8 years ago class-give-db-donor-meta.php 8 years ago class-give-db-donors.php 8 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 8 years ago class-give-db-meta.php 8 years ago class-give-db-payment-meta.php 8 years ago class-give-db-sequential-ordering.php 8 years ago class-give-db.php 8 years ago class-give-donate-form.php 8 years ago class-give-donor.php 8 years ago class-give-email-access.php 8 years ago class-give-gravatars.php 8 years ago class-give-html-elements.php 8 years ago class-give-license-handler.php 8 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 8 years ago class-give-session.php 8 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 8 years ago country-functions.php 8 years ago currency-functions.php 8 years ago error-tracking.php 8 years ago filters.php 8 years ago formatting.php 8 years ago import-functions.php 8 years ago install.php 8 years ago login-register.php 8 years ago misc-functions.php 8 years ago plugin-compatibility.php 8 years ago post-types.php 8 years ago price-functions.php 8 years ago process-donation.php 8 years ago shortcodes.php 8 years ago template-functions.php 8 years ago user-functions.php 8 years ago
process-donation.php
1453 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 $post_data = give_clean( $_POST ); // WPCS: input var ok, CSRF ok.
32 $is_ajax = isset( $post_data['give_ajax'] );
33
34 // Verify donation form nonce.
35 if ( ! give_verify_donation_form_nonce( $post_data['give-form-hash'], $post_data['give-form-id'] ) ) {
36 if ( $is_ajax ) {
37 /**
38 * Fires when AJAX sends back errors from the donation form.
39 *
40 * @since 1.0
41 */
42 do_action( 'give_ajax_donation_errors' );
43 give_die();
44 } else {
45 give_send_back_to_checkout();
46 }
47 }
48
49 /**
50 * Fires before processing the donation form.
51 *
52 * @since 1.0
53 */
54 do_action( 'give_pre_process_donation' );
55
56 // Validate the form $_POST data.
57 $valid_data = give_donation_form_validate_fields();
58
59 /**
60 * Fires after validating donation form fields.
61 *
62 * Allow you to hook to donation form errors.
63 *
64 * @since 1.0
65 *
66 * @param bool|array $valid_data Validate fields.
67 * @param array $deprecated Deprecated Since 2.0.2. Use $_POST instead.
68 */
69 $deprecated = $post_data;
70 do_action( 'give_checkout_error_checks', $valid_data, $deprecated );
71
72 // Process the login form.
73 if ( isset( $post_data['give_login_submit'] ) ) {
74 give_process_form_login();
75 }
76
77 // Validate the user.
78 $user = give_get_donation_form_user( $valid_data );
79
80 if ( false === $valid_data || give_get_errors() || ! $user ) {
81 if ( $is_ajax ) {
82 /**
83 * Fires when AJAX sends back errors from the donation form.
84 *
85 * @since 1.0
86 */
87 do_action( 'give_ajax_donation_errors' );
88 give_die();
89 } else {
90 return false;
91 }
92 }
93
94 // If AJAX send back success to proceed with form submission.
95 if ( $is_ajax ) {
96 echo 'success';
97 give_die();
98 }
99
100 // After AJAX: Setup session if not using php_sessions.
101 if ( ! Give()->session->use_php_sessions() ) {
102 // Double-check that set_cookie is publicly accessible.
103 // we're using a slightly modified class-wp-sessions.php.
104 $session_reflection = new ReflectionMethod( 'WP_Session', 'set_cookie' );
105 if ( $session_reflection->isPublic() ) {
106 // Manually set the cookie.
107 Give()->session->init()->set_cookie();
108 }
109 }
110
111 // Setup user information.
112 $user_info = array(
113 'id' => $user['user_id'],
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 $require_address = give_require_billing_address( $payment_mode );
555
556 if ( $require_address ) {
557 $required_fields['card_address'] = array(
558 'error_id' => 'invalid_card_address',
559 'error_message' => __( 'Please enter your primary billing address.', 'give' ),
560 );
561 $required_fields['card_zip'] = array(
562 'error_id' => 'invalid_zip_code',
563 'error_message' => __( 'Please enter your zip / postal code.', 'give' ),
564 );
565 $required_fields['card_city'] = array(
566 'error_id' => 'invalid_city',
567 'error_message' => __( 'Please enter your billing city.', 'give' ),
568 );
569 $required_fields['billing_country'] = array(
570 'error_id' => 'invalid_country',
571 'error_message' => __( 'Please select your billing country.', 'give' ),
572 );
573
574
575 $required_fields['card_state'] = array(
576 'error_id' => 'invalid_state',
577 'error_message' => __( 'Please enter billing state / province / County.', 'give' ),
578 );
579
580 $country = ! empty( $_POST['billing_country'] ) ? give_clean( $_POST['billing_country'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
581
582 // Check if billing country already exists.
583 if ( $country ) {
584
585 // Get the country list that does not required any states init.
586 $states_country = give_states_not_required_country_list();
587
588 // Check if states is empty or not.
589 if ( array_key_exists( $country, $states_country ) ) {
590 // If states is empty remove the required fields of state in billing cart.
591 unset( $required_fields['card_state'] );
592 }
593 }
594 } // End if().
595
596 if ( give_is_company_field_enabled( $form_id ) ) {
597 $form_option = give_get_meta( $form_id, '_give_company_field', true );
598 $global_setting = give_get_option( 'company_field' );
599
600 $is_company_field_required = false;
601
602 if ( ! empty( $form_option ) && give_is_setting_enabled( $form_option, array( 'required' ) ) ) {
603 $is_company_field_required = true;
604
605 } elseif ( 'global' === $form_option && give_is_setting_enabled( $global_setting, array( 'required' ) ) ) {
606 $is_company_field_required = true;
607
608 } elseif ( empty( $form_option ) && give_is_setting_enabled( $global_setting, array( 'required' ) ) ) {
609 $is_company_field_required = true;
610
611 }
612
613 if ( $is_company_field_required ) {
614 $required_fields['give_company_name'] = array(
615 'error_id' => 'invalid_company',
616 'error_message' => __( 'Please enter Company Name.', 'give' ),
617 );
618 }
619 }
620
621 /**
622 * Filters the donation form required field.
623 *
624 * @since 1.7
625 */
626 $required_fields = apply_filters( 'give_donation_form_required_fields', $required_fields, $form_id );
627
628 return $required_fields;
629
630 }
631
632 /**
633 * Check if the Billing Address is required
634 *
635 * @since 1.0.1
636 *
637 * @param string $payment_mode Payment Mode.
638 *
639 * @return bool
640 */
641 function give_require_billing_address( $payment_mode ) {
642
643 $return = false;
644 $billing_country = ! empty( $_POST['billing_country'] ) ? give_clean( $_POST['billing_country'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
645
646 if ( $billing_country || did_action( "give_{$payment_mode}_cc_form" ) || did_action( 'give_cc_form' ) ) {
647 $return = true;
648 }
649
650 // Let payment gateways and other extensions determine if address fields should be required.
651 return apply_filters( 'give_require_billing_address', $return );
652
653 }
654
655 /**
656 * Donation Form Validate Logged In User.
657 *
658 * @access private
659 * @since 1.0
660 *
661 * @return array
662 */
663 function give_donation_form_validate_logged_in_user() {
664
665 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
666 $user_id = get_current_user_id();
667 $form_id = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
668
669 // Start empty array to collect valid user data.
670 $valid_user_data = array(
671
672 // Assume there will be errors.
673 'user_id' => - 1,
674 );
675
676 // Proceed on;y, if valid $user_id found.
677 if ( $user_id > 0 ) {
678
679 // Get the logged in user data.
680 $user_data = get_userdata( $user_id );
681
682 // Validate Required Form Fields.
683 give_validate_required_form_fields( $form_id );
684
685 // Verify data.
686 if ( is_object( $user_data ) && $user_data->ID > 0 ) {
687
688 // Collected logged in user data.
689 $valid_user_data = array(
690 'user_id' => $user_id,
691 'user_email' => ! empty( $post_data['give_email'] ) ? sanitize_email( $post_data['give_email'] ) : $user_data->user_email,
692 'user_first' => ! empty( $post_data['give_first'] ) ? $post_data['give_first'] : $user_data->first_name,
693 'user_last' => ! empty( $post_data['give_last'] ) ? $post_data['give_last'] : $user_data->last_name,
694 );
695
696 // Validate essential form fields.
697 give_donation_form_validate_name_fields( $post_data );
698
699 if ( ! is_email( $valid_user_data['user_email'] ) ) {
700 give_set_error( 'email_invalid', esc_html__( 'Invalid email.', 'give' ) );
701 }
702 } else {
703
704 // Set invalid user information error.
705 give_set_error( 'invalid_user', esc_html__( 'The user information is invalid.', 'give' ) );
706 }
707 }
708
709 // Return user data.
710 return $valid_user_data;
711 }
712
713 /**
714 * Donate Form Validate New User
715 *
716 * @access private
717 * @since 1.0
718 *
719 * @return array
720 */
721 function give_donation_form_validate_new_user() {
722
723 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
724 $nonce = ! empty( $post_data['give-form-user-register-hash'] ) ? $post_data['give-form-user-register-hash'] : '';
725
726 // Validate user creation nonce.
727 if ( ! wp_verify_nonce( $nonce, 'give_form_create_user_nonce' ) ) {
728 give_set_error( 'invalid_nonce', __( 'Nonce verification has failed.', 'give' ) );
729 }
730
731 $auto_generated_password = wp_generate_password();
732
733 // Default user data.
734 $default_user_data = array(
735 'give-form-id' => '',
736 'user_id' => - 1, // Assume there will be errors.
737 'user_first' => '',
738 'user_last' => '',
739 'give_user_login' => false,
740 'give_email' => false,
741 'give_user_pass' => $auto_generated_password,
742 'give_user_pass_confirm' => $auto_generated_password,
743 );
744
745 // Get user data.
746 $user_data = wp_parse_args( $post_data, $default_user_data );
747 $registering_new_user = false;
748 $form_id = absint( $user_data['give-form-id'] );
749
750 give_donation_form_validate_name_fields( $user_data );
751
752 // Start an empty array to collect valid user data.
753 $valid_user_data = array(
754
755 // Assume there will be errors.
756 'user_id' => - 1,
757
758 // Get first name.
759 'user_first' => $user_data['give_first'],
760
761 // Get last name.
762 'user_last' => $user_data['give_last'],
763
764 // Get Password.
765 'user_pass' => $user_data['give_user_pass'],
766 );
767
768 // Validate Required Form Fields.
769 give_validate_required_form_fields( $form_id );
770
771 // Set Email as Username.
772 $valid_user_data['user_login'] = $user_data['give_email'];
773
774 // Check if we have an email to verify.
775 if ( give_validate_user_email( $user_data['give_email'], $registering_new_user ) ) {
776 $valid_user_data['user_email'] = $user_data['give_email'];
777 }
778
779 return $valid_user_data;
780 }
781
782 /**
783 * Donation Form Validate User Login
784 *
785 * @access private
786 * @since 1.0
787 *
788 * @return array
789 */
790 function give_donation_form_validate_user_login() {
791
792 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
793
794 // Start an array to collect valid user data.
795 $valid_user_data = array(
796
797 // Assume there will be errors.
798 'user_id' => - 1,
799 );
800
801 // Bailout, if Username is empty.
802 if ( empty( $post_data['give_user_login'] ) ) {
803 give_set_error( 'must_log_in', __( 'You must register or login to complete your donation.', 'give' ) );
804
805 return $valid_user_data;
806 }
807
808 // Get the user by login.
809 $user_data = get_user_by( 'login', strip_tags( $post_data['give_user_login'] ) );
810
811 // Check if user exists.
812 if ( $user_data ) {
813
814 // Get password.
815 $user_pass = ! empty( $post_data['give_user_pass'] ) ? $post_data['give_user_pass'] : false;
816
817 // Check user_pass.
818 if ( $user_pass ) {
819
820 // Check if password is valid.
821 if ( ! wp_check_password( $user_pass, $user_data->user_pass, $user_data->ID ) ) {
822
823 $current_page_url = site_url() . '/' . get_page_uri();
824
825 // Incorrect password.
826 give_set_error(
827 'password_incorrect',
828 sprintf(
829 '%1$s <a href="%2$s">%3$s</a>',
830 __( 'The password you entered is incorrect.', 'give' ),
831 wp_lostpassword_url( $current_page_url ),
832 __( 'Reset Password', 'give' )
833 )
834 );
835
836 } else {
837
838 // Repopulate the valid user data array.
839 $valid_user_data = array(
840 'user_id' => $user_data->ID,
841 'user_login' => $user_data->user_login,
842 'user_email' => $user_data->user_email,
843 'user_first' => $user_data->first_name,
844 'user_last' => $user_data->last_name,
845 'user_pass' => $user_pass,
846 );
847 }
848 } else {
849 // Empty password.
850 give_set_error( 'password_empty', __( 'Enter a password.', 'give' ) );
851 }
852 } else {
853 // No username.
854 give_set_error( 'username_incorrect', __( 'The username you entered does not exist.', 'give' ) );
855 } // End if().
856
857 return $valid_user_data;
858 }
859
860 /**
861 * Donation Form Validate Guest User
862 *
863 * @access private
864 * @since 1.0
865 *
866 * @return array
867 */
868 function give_donation_form_validate_guest_user() {
869
870 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
871 $form_id = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
872
873 // Start an array to collect valid user data.
874 $valid_user_data = array(
875 // Set a default id for guests.
876 'user_id' => 0,
877 );
878
879 // Validate name fields.
880 give_donation_form_validate_name_fields( $post_data );
881
882 // Validate Required Form Fields.
883 give_validate_required_form_fields( $form_id );
884
885 // Get the guest email.
886 $guest_email = ! empty( $post_data['give_email'] ) ? $post_data['give_email'] : false;
887
888 // Check email.
889 if ( $guest_email && strlen( $guest_email ) > 0 ) {
890
891 // Validate email.
892 if ( ! is_email( $guest_email ) ) {
893
894 // Invalid email.
895 give_set_error( 'email_invalid', __( 'Invalid email.', 'give' ) );
896
897 } else {
898
899 // All is good to go.
900 $valid_user_data['user_email'] = $guest_email;
901
902 // Get user_id from donor if exist.
903 $donor = new Give_Donor( $guest_email );
904
905 if ( $donor->id && $donor->user_id ) {
906 $valid_user_data['user_id'] = $donor->user_id;
907 }
908 }
909 } else {
910 // No email.
911 give_set_error( 'email_empty', __( 'Enter an email.', 'give' ) );
912 }
913
914 return $valid_user_data;
915 }
916
917 /**
918 * Register And Login New User
919 *
920 * @param array $user_data User Data.
921 *
922 * @access private
923 * @since 1.0
924 *
925 * @return integer
926 */
927 function give_register_and_login_new_user( $user_data = array() ) {
928 // Verify the array.
929 if ( empty( $user_data ) ) {
930 return - 1;
931 }
932
933 if ( give_get_errors() ) {
934 return - 1;
935 }
936
937 $user_args = apply_filters( 'give_insert_user_args', array(
938 'user_login' => isset( $user_data['user_login'] ) ? $user_data['user_login'] : '',
939 'user_pass' => isset( $user_data['user_pass'] ) ? $user_data['user_pass'] : '',
940 'user_email' => isset( $user_data['user_email'] ) ? $user_data['user_email'] : '',
941 'first_name' => isset( $user_data['user_first'] ) ? $user_data['user_first'] : '',
942 'last_name' => isset( $user_data['user_last'] ) ? $user_data['user_last'] : '',
943 'user_registered' => date( 'Y-m-d H:i:s' ),
944 'role' => give_get_option( 'donor_default_user_role', 'give_donor' ),
945 ), $user_data );
946
947 // Insert new user.
948 $user_id = wp_insert_user( $user_args );
949
950 // Validate inserted user.
951 if ( is_wp_error( $user_id ) ) {
952 return - 1;
953 }
954
955 // Allow themes and plugins to filter the user data.
956 $user_data = apply_filters( 'give_insert_user_data', $user_data, $user_args );
957
958 /**
959 * Fires after inserting user.
960 *
961 * @since 1.0
962 *
963 * @param int $user_id User id.
964 * @param array $user_data Array containing user data.
965 */
966 do_action( 'give_insert_user', $user_id, $user_data );
967
968 /**
969 * Filter allow user to alter if user when to login or not when user is register for the first time.
970 *
971 * @since 1.8.13
972 *
973 * return bool True if login with registration and False if only want to register.
974 */
975 if ( true === (bool) apply_filters( 'give_log_user_in_on_register', true ) ) {
976 // Login new user.
977 give_log_user_in( $user_id, $user_data['user_login'], $user_data['user_pass'] );
978 }
979
980 // Return user id.
981 return $user_id;
982 }
983
984 /**
985 * Get Donation Form User
986 *
987 * @param array $valid_data Valid Data.
988 *
989 * @access private
990 * @since 1.0
991 *
992 * @return array|bool
993 */
994 function give_get_donation_form_user( $valid_data = array() ) {
995
996 // Initialize user.
997 $user = false;
998 $is_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
999 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1000
1001 if ( $is_ajax ) {
1002
1003 // Do not create or login the user during the ajax submission (check for errors only).
1004 return true;
1005 } elseif ( is_user_logged_in() ) {
1006
1007 // Set the valid user as the logged in collected data.
1008 $user = $valid_data['logged_in_user'];
1009 } elseif ( true === $valid_data['need_new_user'] || true === $valid_data['need_user_login'] ) {
1010
1011 // New user registration.
1012 if ( true === $valid_data['need_new_user'] ) {
1013
1014 // Set user.
1015 $user = $valid_data['new_user_data'];
1016
1017 // Register and login new user.
1018 $user['user_id'] = give_register_and_login_new_user( $user );
1019
1020 } elseif ( true === $valid_data['need_user_login'] && ! $is_ajax ) {
1021
1022 /**
1023 * The login form is now processed in the give_process_donation_login() function.
1024 * This is still here for backwards compatibility.
1025 * This also allows the old login process to still work if a user removes the checkout login submit button.
1026 *
1027 * 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.
1028 */
1029 $user = $valid_data['login_user_data'];
1030
1031 // Login user.
1032 give_log_user_in( $user['user_id'], $user['user_login'], $user['user_pass'] );
1033 }
1034 } // End if().
1035
1036 // Check guest checkout.
1037 if ( false === $user && false === give_logged_in_only( $post_data['give-form-id'] ) ) {
1038
1039 // Set user.
1040 $user = $valid_data['guest_user_data'];
1041 }
1042
1043 // Verify we have an user.
1044 if ( false === $user || empty( $user ) ) {
1045 return false;
1046 }
1047
1048 // Get user first name.
1049 if ( ! isset( $user['user_first'] ) || strlen( trim( $user['user_first'] ) ) < 1 ) {
1050 $user['user_first'] = isset( $post_data['give_first'] ) ? strip_tags( trim( $post_data['give_first'] ) ) : '';
1051 }
1052
1053 // Get user last name.
1054 if ( ! isset( $user['user_last'] ) || strlen( trim( $user['user_last'] ) ) < 1 ) {
1055 $user['user_last'] = isset( $post_data['give_last'] ) ? strip_tags( trim( $post_data['give_last'] ) ) : '';
1056 }
1057
1058 // Get the user's billing address details.
1059 $user['address'] = array();
1060 $user['address']['line1'] = ! empty( $post_data['card_address'] ) ? $post_data['card_address'] : false;
1061 $user['address']['line2'] = ! empty( $post_data['card_address_2'] ) ? $post_data['card_address_2'] : false;
1062 $user['address']['city'] = ! empty( $post_data['card_city'] ) ? $post_data['card_city'] : false;
1063 $user['address']['state'] = ! empty( $post_data['card_state'] ) ? $post_data['card_state'] : false;
1064 $user['address']['zip'] = ! empty( $post_data['card_zip'] ) ? $post_data['card_zip'] : false;
1065 $user['address']['country'] = ! empty( $post_data['billing_country'] ) ? $post_data['billing_country'] : false;
1066
1067 if ( empty( $user['address']['country'] ) ) {
1068 $user['address'] = false;
1069 } // End if().
1070
1071 // Return valid user.
1072 return $user;
1073 }
1074
1075 /**
1076 * Validates the credit card info.
1077 *
1078 * @access private
1079 * @since 1.0
1080 *
1081 * @return array
1082 */
1083 function give_donation_form_validate_cc() {
1084
1085 $card_data = give_get_donation_cc_info();
1086
1087 // Validate the card zip.
1088 if ( ! empty( $card_data['card_zip'] ) ) {
1089 if ( ! give_donation_form_validate_cc_zip( $card_data['card_zip'], $card_data['card_country'] ) ) {
1090 give_set_error( 'invalid_cc_zip', __( 'The zip / postal code you entered for your billing address is invalid.', 'give' ) );
1091 }
1092 }
1093
1094 // Ensure no spaces.
1095 if ( ! empty( $card_data['card_number'] ) ) {
1096 $card_data['card_number'] = str_replace( '+', '', $card_data['card_number'] ); // no "+" signs.
1097 $card_data['card_number'] = str_replace( ' ', '', $card_data['card_number'] ); // No spaces.
1098 }
1099
1100 // This should validate card numbers at some point too.
1101 return $card_data;
1102 }
1103
1104 /**
1105 * Get credit card info.
1106 *
1107 * @access private
1108 * @since 1.0
1109 *
1110 * @return array
1111 */
1112 function give_get_donation_cc_info() {
1113
1114 // Sanitize the values submitted with donation form.
1115 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1116
1117 $cc_info = array();
1118 $cc_info['card_name'] = ! empty( $post_data['card_name'] ) ? $post_data['card_name'] : '';
1119 $cc_info['card_number'] = ! empty( $post_data['card_number'] ) ? $post_data['card_number'] : '';
1120 $cc_info['card_cvc'] = ! empty( $post_data['card_cvc'] ) ? $post_data['card_cvc'] : '';
1121 $cc_info['card_exp_month'] = ! empty( $post_data['card_exp_month'] ) ? $post_data['card_exp_month'] : '';
1122 $cc_info['card_exp_year'] = ! empty( $post_data['card_exp_year'] ) ? $post_data['card_exp_year'] : '';
1123 $cc_info['card_address'] = ! empty( $post_data['card_address'] ) ? $post_data['card_address'] : '';
1124 $cc_info['card_address_2'] = ! empty( $post_data['card_address_2'] ) ? $post_data['card_address_2'] : '';
1125 $cc_info['card_city'] = ! empty( $post_data['card_city'] ) ? $post_data['card_city'] : '';
1126 $cc_info['card_state'] = ! empty( $post_data['card_state'] ) ? $post_data['card_state'] : '';
1127 $cc_info['card_country'] = ! empty( $post_data['billing_country'] ) ? $post_data['billing_country'] : '';
1128 $cc_info['card_zip'] = ! empty( $post_data['card_zip'] ) ? $post_data['card_zip'] : '';
1129
1130 // Return cc info.
1131 return $cc_info;
1132 }
1133
1134 /**
1135 * Validate zip code based on country code
1136 *
1137 * @since 1.0
1138 *
1139 * @param int $zip ZIP Code.
1140 * @param string $country_code Country Code.
1141 *
1142 * @return bool|mixed
1143 */
1144 function give_donation_form_validate_cc_zip( $zip = 0, $country_code = '' ) {
1145 $ret = false;
1146
1147 if ( empty( $zip ) || empty( $country_code ) ) {
1148 return $ret;
1149 }
1150
1151 $country_code = strtoupper( $country_code );
1152
1153 $zip_regex = array(
1154 'AD' => 'AD\d{3}',
1155 'AM' => '(37)?\d{4}',
1156 'AR' => '^([A-Z]{1}\d{4}[A-Z]{3}|[A-Z]{1}\d{4}|\d{4})$',
1157 'AS' => '96799',
1158 'AT' => '\d{4}',
1159 '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})$',
1160 'AX' => '22\d{3}',
1161 'AZ' => '\d{4}',
1162 'BA' => '\d{5}',
1163 'BB' => '(BB\d{5})?',
1164 'BD' => '\d{4}',
1165 'BE' => '^[1-9]{1}[0-9]{3}$',
1166 'BG' => '\d{4}',
1167 'BH' => '((1[0-2]|[2-9])\d{2})?',
1168 'BM' => '[A-Z]{2}[ ]?[A-Z0-9]{2}',
1169 'BN' => '[A-Z]{2}[ ]?\d{4}',
1170 'BR' => '\d{5}[\-]?\d{3}',
1171 'BY' => '\d{6}',
1172 'CA' => '^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$',
1173 'CC' => '6799',
1174 'CH' => '^[1-9][0-9][0-9][0-9]$',
1175 'CK' => '\d{4}',
1176 'CL' => '\d{7}',
1177 'CN' => '\d{6}',
1178 'CR' => '\d{4,5}|\d{3}-\d{4}',
1179 'CS' => '\d{5}',
1180 'CV' => '\d{4}',
1181 'CX' => '6798',
1182 'CY' => '\d{4}',
1183 'CZ' => '\d{3}[ ]?\d{2}',
1184 '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',
1185 'DK' => '^([D-d][K-k])?( |-)?[1-9]{1}[0-9]{3}$',
1186 'DO' => '\d{5}',
1187 'DZ' => '\d{5}',
1188 'EC' => '([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?',
1189 'EE' => '\d{5}',
1190 'EG' => '\d{5}',
1191 'ES' => '^([1-9]{2}|[0-9][1-9]|[1-9][0-9])[0-9]{3}$',
1192 'ET' => '\d{4}',
1193 'FI' => '\d{5}',
1194 'FK' => 'FIQQ 1ZZ',
1195 'FM' => '(9694[1-4])([ \-]\d{4})?',
1196 'FO' => '\d{3}',
1197 'FR' => '^(F-)?((2[A|B])|[0-9]{2})[0-9]{3}$',
1198 'GE' => '\d{4}',
1199 'GF' => '9[78]3\d{2}',
1200 'GL' => '39\d{2}',
1201 'GN' => '\d{3}',
1202 'GP' => '9[78][01]\d{2}',
1203 'GR' => '\d{3}[ ]?\d{2}',
1204 'GS' => 'SIQQ 1ZZ',
1205 'GT' => '\d{5}',
1206 'GU' => '969[123]\d([ \-]\d{4})?',
1207 'GW' => '\d{4}',
1208 'HM' => '\d{4}',
1209 'HN' => '(?:\d{5})?',
1210 'HR' => '\d{5}',
1211 'HT' => '\d{4}',
1212 'HU' => '\d{4}',
1213 'ID' => '\d{5}',
1214 'IE' => '((D|DUBLIN)?([1-9]|6[wW]|1[0-8]|2[024]))?',
1215 'IL' => '\d{5}',
1216 'IN' => '^[1-9][0-9][0-9][0-9][0-9][0-9]$', // India.
1217 'IO' => 'BBND 1ZZ',
1218 'IQ' => '\d{5}',
1219 'IS' => '\d{3}',
1220 'IT' => '^(V-|I-)?[0-9]{5}$',
1221 'JO' => '\d{5}',
1222 'JP' => '\d{3}-\d{4}',
1223 'KE' => '\d{5}',
1224 'KG' => '\d{6}',
1225 'KH' => '\d{5}',
1226 'KR' => '\d{3}[\-]\d{3}',
1227 'KW' => '\d{5}',
1228 'KZ' => '\d{6}',
1229 'LA' => '\d{5}',
1230 'LB' => '(\d{4}([ ]?\d{4})?)?',
1231 'LI' => '(948[5-9])|(949[0-7])',
1232 'LK' => '\d{5}',
1233 'LR' => '\d{4}',
1234 'LS' => '\d{3}',
1235 'LT' => '\d{5}',
1236 'LU' => '\d{4}',
1237 'LV' => '\d{4}',
1238 'MA' => '\d{5}',
1239 'MC' => '980\d{2}',
1240 'MD' => '\d{4}',
1241 'ME' => '8\d{4}',
1242 'MG' => '\d{3}',
1243 'MH' => '969[67]\d([ \-]\d{4})?',
1244 'MK' => '\d{4}',
1245 'MN' => '\d{6}',
1246 'MP' => '9695[012]([ \-]\d{4})?',
1247 'MQ' => '9[78]2\d{2}',
1248 'MT' => '[A-Z]{3}[ ]?\d{2,4}',
1249 'MU' => '(\d{3}[A-Z]{2}\d{3})?',
1250 'MV' => '\d{5}',
1251 'MX' => '\d{5}',
1252 'MY' => '\d{5}',
1253 'NC' => '988\d{2}',
1254 'NE' => '\d{4}',
1255 'NF' => '2899',
1256 'NG' => '(\d{6})?',
1257 'NI' => '((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?',
1258 'NL' => '^[1-9][0-9]{3}\s?([a-zA-Z]{2})?$',
1259 'NO' => '\d{4}',
1260 'NP' => '\d{5}',
1261 'NZ' => '\d{4}',
1262 'OM' => '(PC )?\d{3}',
1263 'PF' => '987\d{2}',
1264 'PG' => '\d{3}',
1265 'PH' => '\d{4}',
1266 'PK' => '\d{5}',
1267 'PL' => '\d{2}-\d{3}',
1268 'PM' => '9[78]5\d{2}',
1269 'PN' => 'PCRN 1ZZ',
1270 'PR' => '00[679]\d{2}([ \-]\d{4})?',
1271 'PT' => '\d{4}([\-]\d{3})?',
1272 'PW' => '96940',
1273 'PY' => '\d{4}',
1274 'RE' => '9[78]4\d{2}',
1275 'RO' => '\d{6}',
1276 'RS' => '\d{5}',
1277 'RU' => '\d{6}',
1278 'SA' => '\d{5}',
1279 'SE' => '^(s-|S-){0,1}[0-9]{3}\s?[0-9]{2}$',
1280 'SG' => '\d{6}',
1281 'SH' => '(ASCN|STHL) 1ZZ',
1282 'SI' => '\d{4}',
1283 'SJ' => '\d{4}',
1284 'SK' => '\d{3}[ ]?\d{2}',
1285 'SM' => '4789\d',
1286 'SN' => '\d{5}',
1287 'SO' => '\d{5}',
1288 'SZ' => '[HLMS]\d{3}',
1289 'TC' => 'TKCA 1ZZ',
1290 'TH' => '\d{5}',
1291 'TJ' => '\d{6}',
1292 'TM' => '\d{6}',
1293 'TN' => '\d{4}',
1294 'TR' => '\d{5}',
1295 'TW' => '\d{3}(\d{2})?',
1296 'UA' => '\d{5}',
1297 'UK' => '^(GIR|[A-Z]\d[A-Z\d]??|[A-Z]{2}\d[A-Z\d]??)[ ]??(\d[A-Z]{2})$',
1298 'US' => '^\d{5}([\-]?\d{4})?$',
1299 'UY' => '\d{5}',
1300 'UZ' => '\d{6}',
1301 'VA' => '00120',
1302 'VE' => '\d{4}',
1303 'VI' => '008(([0-4]\d)|(5[01]))([ \-]\d{4})?',
1304 'WF' => '986\d{2}',
1305 'YT' => '976\d{2}',
1306 'YU' => '\d{5}',
1307 'ZA' => '\d{4}',
1308 'ZM' => '\d{5}',
1309 );
1310
1311 if ( ! isset( $zip_regex[ $country_code ] ) || preg_match( '/' . $zip_regex[ $country_code ] . '/i', $zip ) ) {
1312 $ret = true;
1313 }
1314
1315 return apply_filters( 'give_is_zip_valid', $ret, $zip, $country_code );
1316 }
1317
1318 /**
1319 * Validate donation amount and auto set correct donation level id on basis of amount.
1320 *
1321 * 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.
1322 *
1323 * @param array $valid_data List of Valid Data.
1324 *
1325 * @return bool
1326 */
1327 function give_validate_donation_amount( $valid_data ) {
1328
1329 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1330
1331 /* @var Give_Donate_Form $form */
1332 $form = new Give_Donate_Form( $post_data['give-form-id'] );
1333
1334 // Get the form currency.
1335 $form_currency = give_get_currency( $post_data['give-form-id'] );
1336
1337 $donation_level_matched = false;
1338
1339 if ( $form->is_set_type_donation_form() ) {
1340
1341 // Sanitize donation amount.
1342 $post_data['give-amount'] = give_maybe_sanitize_amount( $post_data['give-amount'], array( 'currency' => $form_currency ) );
1343
1344 // Backward compatibility.
1345 if ( $form->is_custom_price( $post_data['give-amount'] ) ) {
1346 $post_data['give-price-id'] = 'custom';
1347 }
1348
1349 $donation_level_matched = true;
1350
1351 } elseif ( $form->is_multi_type_donation_form() ) {
1352
1353 $variable_prices = $form->get_prices();
1354
1355 // Bailout.
1356 if ( ! $variable_prices ) {
1357 return false;
1358 }
1359
1360 // Sanitize donation amount.
1361 $post_data['give-amount'] = give_maybe_sanitize_amount( $post_data['give-amount'], array( 'currency' => $form_currency ) );
1362 $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 ) );
1363 $new_price_id = '';
1364
1365 if ( $post_data['give-amount'] === $variable_price_option_amount ) {
1366 return true;
1367 }
1368
1369 if ( $form->is_custom_price( $post_data['give-amount'] ) ) {
1370 $new_price_id = 'custom';
1371 } else {
1372
1373 // Find correct donation level from all donation levels.
1374 foreach ( $variable_prices as $variable_price ) {
1375
1376 // Sanitize level amount.
1377 $variable_price['_give_amount'] = give_maybe_sanitize_amount( $variable_price['_give_amount'] );
1378
1379 // Set first match donation level ID.
1380 if ( $post_data['give-amount'] === $variable_price['_give_amount'] ) {
1381 $new_price_id = $variable_price['_give_id']['level_id'];
1382 break;
1383 }
1384 }
1385 }
1386
1387 // If donation amount is not find in donation levels then check if form has custom donation feature enable or not.
1388 // If yes then set price id to custom if amount is greater then custom minimum amount (if any).
1389 if ( $post_data['give-price-id'] === $new_price_id ) {
1390 $donation_level_matched = true;
1391 }
1392 } // End if().
1393
1394 if ( ! $donation_level_matched ) {
1395 give_set_error(
1396 'invalid_donation_amount',
1397 sprintf(
1398 /* translators: %s: invalid donation amount */
1399 __( 'Donation amount %s is invalid.', 'give' ),
1400 give_currency_filter(
1401 give_format_amount( $post_data['give-amount'], array( 'sanitize' => false, ) )
1402 )
1403 )
1404 );
1405 }
1406 }
1407
1408 add_action( 'give_checkout_error_checks', 'give_validate_donation_amount', 10, 1 );
1409
1410 /**
1411 * Validate Required Form Fields.
1412 *
1413 * @param int $form_id Form ID.
1414 *
1415 * @since 2.0
1416 */
1417 function give_validate_required_form_fields( $form_id ) {
1418
1419 // Sanitize values submitted with donation form.
1420 $post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
1421
1422 // Loop through required fields and show error messages.
1423 foreach ( give_get_required_fields( $form_id ) as $field_name => $value ) {
1424
1425 // Clean Up Data of the input fields.
1426 $field_value = $post_data[ $field_name ];
1427
1428 // Check whether the required field is empty, then show the error message.
1429 if ( in_array( $value, give_get_required_fields( $form_id ), true ) && empty( $field_value ) ) {
1430 give_set_error( $value['error_id'], $value['error_message'] );
1431 }
1432 }
1433 }
1434
1435 /**
1436 * Validates and checks if name fields are valid or not.
1437 *
1438 * @param array $post_data List of post data.
1439 *
1440 * @since 2.1
1441 *
1442 * @return void
1443 */
1444 function give_donation_form_validate_name_fields( $post_data ) {
1445
1446 $is_alpha_first_name = ( ! is_email( $post_data['give_first'] ) && ! preg_match( '~[0-9]~', $post_data['give_first'] ) );
1447 $is_alpha_last_name = ( ! is_email( $post_data['give_last'] ) && ! preg_match( '~[0-9]~', $post_data['give_last'] ) );
1448
1449 if ( ! $is_alpha_first_name || ( ! empty( $post_data['give_last'] ) && ! $is_alpha_last_name ) ) {
1450 give_set_error( 'invalid_name', esc_html__( 'The First Name and Last Name fields cannot contain an email address or numbers.', 'give' ) );
1451 }
1452 }
1453