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