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