Completed
Push — issues/611 ( 661115...758b1c )
by Ravinder
21:11
created

process-donation.php ➔ give_process_purchase_form()   D

Complexity

Conditions 12
Paths 194

Size

Total Lines 136
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 51
nc 194
nop 0
dl 0
loc 136
rs 4.6933
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 26 and the first side effect is on line 14.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Process Donation
4
 *
5
 * @package     Give
6
 * @subpackage  Functions
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.0
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Process Donation Form
19
 *
20
 * Handles the donation form process.
21
 *
22
 * @access      private
23
 * @since       1.0
24
 * @return      false|null
25
 */
26
function give_process_donation_form() {
27
28
	/**
29
	 * Fires before processing the donation form.
30
	 *
31
	 * @since 1.0
32
	 */
33
	do_action( 'give_pre_process_donation' );
34
35
	// Validate the form $_POST data
36
	$valid_data = give_purchase_form_validate_fields();
37
38
	/**
39
	 * Fires after validating donation form fields.
40
	 *
41
	 * Allow you to hook to donation form errors.
42
	 *
43
	 * @since 1.0
44
	 *
45
	 * @param bool|array $valid_data Validate fields.
46
	 * @param array      $_POST      Array of variables passed via the HTTP POST.
47
	 */
48
	do_action( 'give_checkout_error_checks', $valid_data, $_POST );
49
50
	$is_ajax = isset( $_POST['give_ajax'] );
51
52
	// Process the login form
53
	if ( isset( $_POST['give_login_submit'] ) ) {
54
		give_process_form_login();
55
	}
56
57
	// Validate the user
58
	$user = give_get_purchase_form_user( $valid_data );
59
60
	if ( false === $valid_data || give_get_errors() || ! $user ) {
61
		if ( $is_ajax ) {
62
			/**
63
			 * Fires when AJAX sends back errors from the donation form.
64
			 *
65
			 * @since 1.0
66
			 */
67
			do_action( 'give_ajax_donation_errors' );
68
			give_die();
69
		} else {
70
			return false;
71
		}
72
	}
73
74
	// If AJAX send back success to proceed with form submission
75
	if ( $is_ajax ) {
76
		echo 'success';
77
		give_die();
78
	}
79
80
	// After AJAX: Setup session if not using php_sessions
81
	if ( ! Give()->session->use_php_sessions() ) {
82
		// Double-check that set_cookie is publicly accessible;
83
		// we're using a slightly modified class-wp-sessions.php
84
		$session_reflection = new ReflectionMethod( 'WP_Session', 'set_cookie' );
85
		if ( $session_reflection->isPublic() ) {
86
			// Manually set the cookie.
87
			Give()->session->init()->set_cookie();
0 ignored issues
show
Bug introduced by
The method set_cookie cannot be called on Give()->session->init() (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
88
		}
89
	}
90
91
	// Setup user information
92
	$user_info = array(
93
		'id'         => $user['user_id'],
94
		'email'      => $user['user_email'],
95
		'first_name' => $user['user_first'],
96
		'last_name'  => $user['user_last'],
97
		'address'    => $user['address'],
98
	);
99
100
	$auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
101
102
	$price        = isset( $_POST['give-amount'] ) ? (float) apply_filters( 'give_donation_total', give_sanitize_amount( give_format_amount( $_POST['give-amount'] ) ) ) : '0.00';
103
	$purchase_key = strtolower( md5( $user['user_email'] . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'give', true ) ) );
104
105
	// Setup donation information
106
	$purchase_data = array(
107
		'price'        => $price,
108
		'purchase_key' => $purchase_key,
109
		'user_email'   => $user['user_email'],
110
		'date'         => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
111
		'user_info'    => stripslashes_deep( $user_info ),
112
		'post_data'    => $_POST,
113
		'gateway'      => $valid_data['gateway'],
114
		'card_info'    => $valid_data['cc_info'],
115
	);
116
117
	// Add the user data for hooks
118
	$valid_data['user'] = $user;
119
120
	/**
121
	 * Fires before donation form gateway.
122
	 *
123
	 * Allow you to hook to donation form before the gateway.
124
	 *
125
	 * @since 1.0
126
	 *
127
	 * @param array      $_POST      Array of variables passed via the HTTP POST.
128
	 * @param array      $user_info  Array containing basic user information.
129
	 * @param bool|array $valid_data Validate fields.
130
	 */
131
	do_action( 'give_checkout_before_gateway', $_POST, $user_info, $valid_data );
132
133
	// Sanity check for price
134
	if ( ! $purchase_data['price'] ) {
135
		// Revert to manual
136
		$purchase_data['gateway'] = 'manual';
137
		$_POST['give-gateway']    = 'manual';
138
	}
139
140
	/**
141
	 * Allow the purchase data to be modified before it is sent to the gateway
142
	 *
143
	 * @since 1.7
144
	 */
145
	$purchase_data = apply_filters( 'give_donation_data_before_gateway', $purchase_data, $valid_data );
146
147
	// Setup the data we're storing in the donation session
148
	$session_data = $purchase_data;
149
150
	// Make sure credit card numbers are never stored in sessions
151
	unset( $session_data['card_info']['card_number'] );
152
	unset( $session_data['post_data']['card_number'] );
153
154
	// Used for showing data to non logged-in users after donation, and for other plugins needing donation data.
155
	give_set_purchase_session( $session_data );
156
157
	// Send info to the gateway for payment processing
158
	give_send_to_gateway( $purchase_data['gateway'], $purchase_data );
159
	give_die();
160
161
}
162
163
add_action( 'give_purchase', 'give_process_donation_form' );
164
add_action( 'wp_ajax_give_process_donation', 'give_process_donation_form' );
165
add_action( 'wp_ajax_nopriv_give_process_donation', 'give_process_donation_form' );
166
167
168
/**
169
 * Verify that when a logged in user makes a donation that the email address used doesn't belong to a different customer
170
 *
171
 * @since  1.7
172
 *
173
 * @param  array $valid_data Validated data submitted for the purchase
174
 * @param  array $post       Additional $_POST data submitted
175
 *
176
 * @return void
177
 */
178
function give_checkout_check_existing_email( $valid_data, $post ) {
0 ignored issues
show
Unused Code introduced by
The parameter $post is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
179
180
	// Verify that the email address belongs to this customer.
181
	if ( is_user_logged_in() ) {
182
183
		$email    = $valid_data['logged_in_user']['user_email'];
184
		$customer = new Give_Customer( get_current_user_id(), true );
185
186
		// If this email address is not registered with this customer, see if it belongs to any other customer
187
		if ( $email !== $customer->email && ( is_array( $customer->emails ) && ! in_array( $email, $customer->emails ) ) ) {
188
			$found_customer = new Give_Customer( $email );
189
190
			if ( $found_customer->id > 0 ) {
191
				give_set_error( 'give-customer-email-exists', sprintf( esc_html__( 'The email address %s is already in use.', 'give' ), $email ) );
192
			}
193
		}
194
	}
195
}
196
197
add_action( 'give_checkout_error_checks', 'give_checkout_check_existing_email', 10, 2 );
198
199
/**
200
 * Process the checkout login form
201
 *
202
 * @access      private
203
 * @since       1.0
204
 * @return      void
205
 */
206
function give_process_form_login() {
207
208
	$is_ajax = isset( $_POST['give_ajax'] );
209
210
	$user_data = give_purchase_form_validate_user_login();
211
212
	if ( give_get_errors() || $user_data['user_id'] < 1 ) {
213
		if ( $is_ajax ) {
214
			/**
215
			 * Fires when AJAX sends back errors from the donation form.
216
			 *
217
			 * @since 1.0
218
			 */
219
			do_action( 'give_ajax_donation_errors' );
220
			give_die();
221
		} else {
222
			wp_redirect( $_SERVER['HTTP_REFERER'] );
223
			exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function give_process_form_login() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
224
		}
225
	}
226
227
	give_log_user_in( $user_data['user_id'], $user_data['user_login'], $user_data['user_pass'] );
228
229
	if ( $is_ajax ) {
230
		echo 'success';
231
		give_die();
232
	} else {
233
		wp_redirect( $_SERVER['HTTP_REFERER'] );
234
	}
235
}
236
237
add_action( 'wp_ajax_give_process_donation_login', 'give_process_form_login' );
238
add_action( 'wp_ajax_nopriv_give_process_donation_login', 'give_process_form_login' );
239
240
/**
241
 * Donation Form Validate Fields
242
 *
243
 * @access      private
244
 * @since       1.0
245
 * @return      bool|array
246
 */
247
function give_purchase_form_validate_fields() {
248
249
	// Check if there is $_POST
250
	if ( empty( $_POST ) ) {
251
		return false;
252
	}
253
254
	$form_id = isset( $_POST['give-form-id'] ) ? $_POST['give-form-id'] : '';
255
256
	// Start an array to collect valid data
257
	$valid_data = array(
258
		'gateway'          => give_purchase_form_validate_gateway(), // Gateway fallback (amount is validated here)
259
		'need_new_user'    => false,     // New user flag
260
		'need_user_login'  => false,     // Login user flag
261
		'logged_user_data' => array(),   // Logged user collected data
262
		'new_user_data'    => array(),   // New user collected data
263
		'login_user_data'  => array(),   // Login user collected data
264
		'guest_user_data'  => array(),   // Guest user collected data
265
		'cc_info'          => give_purchase_form_validate_cc(),// Credit card info
266
	);
267
268
	// Validate Honeypot First
269
	if ( ! empty( $_POST['give-honeypot'] ) ) {
270
		give_set_error( 'invalid_honeypot', esc_html__( 'Honeypot field detected. Go away bad bot!', 'give' ) );
271
	}
272
273
	// Validate agree to terms
274
	if ( give_is_terms_enabled( $form_id ) ) {
275
		give_purchase_form_validate_agree_to_terms();
276
	}
277
278
	// Stop processing donor registration, if donor registration is optional and donor can do guest checkout.
279
	// If registration form username field is empty that means donor do not want to registration instead want guest checkout.
280
	if (
281
		! give_logged_in_only( $form_id )
282
		&& isset( $_POST['give-purchase-var'] )
283
		&& $_POST['give-purchase-var'] == 'needs-to-register'
284
		&& empty( $_POST['give_user_login'] )
285
	) {
286
		unset( $_POST['give-purchase-var'] );
287
	}
288
289
	if ( is_user_logged_in() ) {
290
		// Collect logged in user data
291
		$valid_data['logged_in_user'] = give_purchase_form_validate_logged_in_user();
292
	} elseif ( isset( $_POST['give-purchase-var'] ) && $_POST['give-purchase-var'] == 'needs-to-register' ) {
293
		// Set new user registration as required
294
		$valid_data['need_new_user'] = true;
295
		// Validate new user data
296
		$valid_data['new_user_data'] = give_purchase_form_validate_new_user();
297
		// Check if login validation is needed
298
	} elseif ( isset( $_POST['give-purchase-var'] ) && $_POST['give-purchase-var'] == 'needs-to-login' ) {
299
		// Set user login as required
300
		$valid_data['need_user_login'] = true;
301
		// Validate users login info
302
		$valid_data['login_user_data'] = give_purchase_form_validate_user_login();
303
	} else {
304
		// Not registering or logging in, so setup guest user data
305
		$valid_data['guest_user_data'] = give_purchase_form_validate_guest_user();
306
	}
307
308
	// Return collected data
309
	return $valid_data;
310
}
311
312
/**
313
 * Donation Form Validate Gateway
314
 *
315
 * Validate the gateway and donation amount
316
 *
317
 * @access      private
318
 * @since       1.0
319
 * @return      string
320
 */
321
function give_purchase_form_validate_gateway() {
322
323
	$form_id = isset( $_REQUEST['give-form-id'] ) ? $_REQUEST['give-form-id'] : 0;
324
	$amount  = isset( $_REQUEST['give-amount'] ) ? give_sanitize_amount( $_REQUEST['give-amount'] ) : 0;
325
	$gateway = give_get_default_gateway( $form_id );
326
327
	// Check if a gateway value is present
328
	if ( ! empty( $_REQUEST['give-gateway'] ) ) {
329
330
		$gateway = sanitize_text_field( $_REQUEST['give-gateway'] );
331
332
		// Is amount being donated in LIVE mode 0.00? If so, error:
333
		if ( $amount == 0 && ! give_is_test_mode() ) {
334
335
			give_set_error( 'invalid_donation_amount', esc_html__( 'Please insert a valid donation amount.', 'give' ) );
336
337
		} //Check for a minimum custom amount
338
		elseif ( ! give_verify_minimum_price() ) {
339
			// translators: %s: minimum donation amount.
340
			give_set_error(
341
				'invalid_donation_minimum',
342
				sprintf(
343
					/* translators: %s: minimum donation amount */
344
					esc_html__( 'This form has a minimum donation amount of %s.', 'give' ),
345
					give_currency_filter( give_format_amount( give_get_form_minimum_price( $form_id ) ) )
346
				)
347
			);
348
349
		} //Is this test mode zero donation? Let it through but set to manual gateway.
350
		elseif ( $amount == 0 && give_is_test_mode() ) {
351
352
			$gateway = 'manual';
353
354
		} //Check if this gateway is active.
355
		elseif ( ! give_is_gateway_active( $gateway ) ) {
356
357
			give_set_error( 'invalid_gateway', esc_html__( 'The selected payment gateway is not enabled.', 'give' ) );
358
359
		}
360
	}
361
362
	return $gateway;
363
364
}
365
366
/**
367
 * Donation Form Validate Minimum Donation Amount
368
 *
369
 * @access      private
370
 * @since       1.3.6
371
 * @return      bool
372
 */
373
function give_verify_minimum_price() {
374
375
	$amount          = give_sanitize_amount( $_REQUEST['give-amount'] );
376
	$form_id         = isset( $_REQUEST['give-form-id'] ) ? $_REQUEST['give-form-id'] : 0;
377
	$price_id        = isset( $_REQUEST['give-price-id'] ) ? $_REQUEST['give-price-id'] : 0;
378
	$variable_prices = give_has_variable_prices( $form_id );
379
380
	if ( $variable_prices && ! empty( $price_id ) ) {
381
382
		$price_level_amount = give_get_price_option_amount( $form_id, $price_id );
383
384
		if ( $price_level_amount == $amount ) {
385
			return true;
386
		}
387
	}
388
389
	$minimum = give_get_form_minimum_price( $form_id );
390
391
	if ( $minimum > $amount ) {
392
		return false;
393
	}
394
395
	return true;
396
}
397
398
/**
399
 * Donation form validate agree to "Terms and Conditions".
400
 *
401
 * @access      private
402
 * @since       1.0
403
 * @return      void
404
 */
405
function give_purchase_form_validate_agree_to_terms() {
406
	// Validate agree to terms.
407
	if ( ! isset( $_POST['give_agree_to_terms'] ) || $_POST['give_agree_to_terms'] != 1 ) {
408
		// User did not agree.
409
		give_set_error( 'agree_to_terms', apply_filters( 'give_agree_to_terms_text', esc_html__( 'You must agree to the terms and conditions.', 'give' ) ) );
410
	}
411
}
412
413
/**
414
 * Donation Form Required Fields.
415
 *
416
 * @access      private
417
 * @since       1.0
418
 *
419
 * @param       $form_id
420
 *
421
 * @return      array
422
 */
423
function give_get_required_fields( $form_id ) {
424
425
	$payment_mode = give_get_chosen_gateway( $form_id );
426
427
	$required_fields = array(
428
		'give_email' => array(
429
			'error_id'      => 'invalid_email',
430
			'error_message' => esc_html__( 'Please enter a valid email address.', 'give' ),
431
		),
432
		'give_first' => array(
433
			'error_id'      => 'invalid_first_name',
434
			'error_message' => esc_html__( 'Please enter your first name.', 'give' ),
435
		),
436
	);
437
438
	$require_address = give_require_billing_address( $payment_mode );
439
440
	if ( $require_address ) {
441
		$required_fields['card_address']    = array(
442
			'error_id'      => 'invalid_card_address',
443
			'error_message' => esc_html__( 'Please enter your primary billing address.', 'give' ),
444
		);
445
		$required_fields['card_zip']        = array(
446
			'error_id'      => 'invalid_zip_code',
447
			'error_message' => esc_html__( 'Please enter your zip / postal code.', 'give' ),
448
		);
449
		$required_fields['card_city']       = array(
450
			'error_id'      => 'invalid_city',
451
			'error_message' => esc_html__( 'Please enter your billing city.', 'give' ),
452
		);
453
		$required_fields['billing_country'] = array(
454
			'error_id'      => 'invalid_country',
455
			'error_message' => esc_html__( 'Please select your billing country.', 'give' ),
456
		);
457
		$required_fields['card_state']      = array(
458
			'error_id'      => 'invalid_state',
459
			'error_message' => esc_html__( 'Please enter billing state / province.', 'give' ),
460
		);
461
	}
462
463
	/**
464
	 * Filters the donation form required field.
465
	 *
466
	 * @since 1.7
467
	 */
468
	$required_fields = apply_filters( 'give_donation_form_required_fields', $required_fields, $form_id );
469
470
	return $required_fields;
471
472
}
473
474
/**
475
 * Check if the Billing Address is required
476
 *
477
 * @since  1.0.1
478
 *
479
 * @param string $payment_mode
480
 *
481
 * @return mixed|void
482
 */
483
function give_require_billing_address( $payment_mode ) {
484
485
	$return = false;
486
487
	if ( isset( $_POST['billing_country'] ) || did_action( "give_{$payment_mode}_cc_form" ) || did_action( 'give_cc_form' ) ) {
488
		$return = true;
489
	}
490
491
	// Let payment gateways and other extensions determine if address fields should be required.
492
	return apply_filters( 'give_require_billing_address', $return );
493
494
}
495
496
/**
497
 * Donation Form Validate Logged In User
498
 *
499
 * @access      private
500
 * @since       1.0
501
 * @return      array
502
 */
503
function give_purchase_form_validate_logged_in_user() {
504
	global $user_ID;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
505
506
	$form_id = isset( $_POST['give-form-id'] ) ? $_POST['give-form-id'] : '';
507
508
	// Start empty array to collect valid user data.
509
	$valid_user_data = array(
510
		// Assume there will be errors.
511
		'user_id' => - 1,
512
	);
513
514
	// Verify there is a user_ID.
515
	if ( $user_ID > 0 ) {
516
		// Get the logged in user data.
517
		$user_data = get_userdata( $user_ID );
518
519
		// Loop through required fields and show error messages.
520
		foreach ( give_get_required_fields( $form_id ) as $field_name => $value ) {
521
			if ( in_array( $value, give_get_required_fields( $form_id ) ) && empty( $_POST[ $field_name ] ) ) {
522
				give_set_error( $value['error_id'], $value['error_message'] );
523
			}
524
		}
525
526
		// Verify data.
527
		if ( $user_data ) {
528
			// Collected logged in user data.
529
			$valid_user_data = array(
530
				'user_id'    => $user_ID,
531
				'user_email' => isset( $_POST['give_email'] ) ? sanitize_email( $_POST['give_email'] ) : $user_data->user_email,
532
				'user_first' => isset( $_POST['give_first'] ) && ! empty( $_POST['give_first'] ) ? sanitize_text_field( $_POST['give_first'] ) : $user_data->first_name,
533
				'user_last'  => isset( $_POST['give_last'] ) && ! empty( $_POST['give_last'] ) ? sanitize_text_field( $_POST['give_last'] ) : $user_data->last_name,
534
			);
535
536
			if ( ! is_email( $valid_user_data['user_email'] ) ) {
537
				give_set_error( 'email_invalid', esc_html__( 'Invalid email.', 'give' ) );
538
			}
539
		} else {
540
			// Set invalid user error.
541
			give_set_error( 'invalid_user', esc_html__( 'The user information is invalid.', 'give' ) );
542
		}
543
	}
544
545
	// Return user data.
546
	return $valid_user_data;
547
}
548
549
/**
550
 * Donate Form Validate New User
551
 *
552
 * @access      private
553
 * @since       1.0
554
 * @return      array
555
 */
556
function give_purchase_form_validate_new_user() {
557
	// Default user data.
558
	$default_user_data = array(
559
		'give-form-id'           => '',
560
		'user_id'                => - 1, // Assume there will be errors.
561
		'user_first'             => '',
562
		'user_last'              => '',
563
		'give_user_login'        => false,
564
		'give_email'             => false,
565
		'give_user_pass'         => false,
566
		'give_user_pass_confirm' => false,
567
	);
568
569
	// Get user data.
570
	$user_data            = wp_parse_args( array_map( 'trim', give_clean( $_POST ) ), $default_user_data );
571
	$registering_new_user = false;
572
	$form_id              = absint( $user_data['give-form-id'] );
573
574
	// Start an empty array to collect valid user data.
575
	$valid_user_data = array(
576
		// Assume there will be errors.
577
		'user_id'    => - 1,
578
579
		// Get first name.
580
		'user_first' => $user_data['give_first'],
581
582
		// Get last name.
583
		'user_last'  => $user_data['give_last'],
584
	);
585
586
	// Loop through required fields and show error messages.
587
	foreach ( give_get_required_fields( $form_id ) as $field_name => $value ) {
588
		if ( in_array( $value, give_get_required_fields( $form_id ) ) && empty( $_POST[ $field_name ] ) ) {
589
			give_set_error( $value['error_id'], $value['error_message'] );
590
		}
591
	}
592
593
	// Check if we have an username to register.
594
	if ( give_validate_username( $user_data['give_user_login'] ) ) {
595
		$registering_new_user          = true;
596
		$valid_user_data['user_login'] = $user_data['give_user_login'];
597
	}
598
599
	// Check if we have an email to verify.
600
	if ( give_validate_user_email( $user_data['give_email'], $registering_new_user ) ) {
601
		$valid_user_data['user_email'] = $user_data['give_email'];
602
	}
603
604
	// Check password.
605
	if ( give_validate_user_password( $user_data['give_user_pass'], $user_data['give_user_pass_confirm'], $registering_new_user ) ) {
606
		// All is good to go.
607
		$valid_user_data['user_pass'] = $user_data['give_user_pass'];
608
	}
609
610
	return $valid_user_data;
611
}
612
613
/**
614
 * Donation Form Validate User Login
615
 *
616
 * @access      private
617
 * @since       1.0
618
 * @return      array
619
 */
620
function give_purchase_form_validate_user_login() {
621
622
	// Start an array to collect valid user data.
623
	$valid_user_data = array(
624
		// Assume there will be errors
625
		'user_id' => - 1,
626
	);
627
628
	// Username.
629
	if ( ! isset( $_POST['give_user_login'] ) || $_POST['give_user_login'] == '' ) {
630
		give_set_error( 'must_log_in', esc_html__( 'You must register or login to complete your donation.', 'give' ) );
631
632
		return $valid_user_data;
633
	}
634
635
	// Get the user by login.
636
	$user_data = get_user_by( 'login', strip_tags( $_POST['give_user_login'] ) );
637
638
	// Check if user exists.
639
	if ( $user_data ) {
640
		// Get password.
641
		$user_pass = isset( $_POST['give_user_pass'] ) ? $_POST['give_user_pass'] : false;
642
643
		// Check user_pass.
644
		if ( $user_pass ) {
645
			// Check if password is valid.
646
			if ( ! wp_check_password( $user_pass, $user_data->user_pass, $user_data->ID ) ) {
647
				// Incorrect password.
648
				give_set_error(
649
					'password_incorrect',
650
					sprintf(
651
						'%1$s <a href="%2$s">%3$s</a>',
652
						esc_html__( 'The password you entered is incorrect.', 'give' ),
653
						wp_lostpassword_url( "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]" ),
654
						esc_html__( 'Reset Password', 'give' )
655
					)
656
				);
657
				// All is correct.
658
			} else {
659
				// Repopulate the valid user data array.
660
				$valid_user_data = array(
661
					'user_id'    => $user_data->ID,
662
					'user_login' => $user_data->user_login,
663
					'user_email' => $user_data->user_email,
664
					'user_first' => $user_data->first_name,
665
					'user_last'  => $user_data->last_name,
666
					'user_pass'  => $user_pass,
667
				);
668
			}
669
		} else {
670
			// Empty password.
671
			give_set_error( 'password_empty', esc_html__( 'Enter a password.', 'give' ) );
672
		}
673
	} else {
674
		// No username.
675
		give_set_error( 'username_incorrect', esc_html__( 'The username you entered does not exist.', 'give' ) );
676
	}
677
678
	return $valid_user_data;
679
}
680
681
/**
682
 * Donation Form Validate Guest User
683
 *
684
 * @access  private
685
 * @since   1.0
686
 * @return  array
687
 */
688
function give_purchase_form_validate_guest_user() {
689
690
	$form_id = isset( $_POST['give-form-id'] ) ? $_POST['give-form-id'] : '';
691
692
	// Start an array to collect valid user data.
693
	$valid_user_data = array(
694
		// Set a default id for guests.
695
		'user_id' => 0,
696
	);
697
698
	// Show error message if user must be logged in.
699
	if ( give_logged_in_only( $form_id ) ) {
700
		give_set_error( 'logged_in_only', esc_html__( 'You must be logged in to donate.', 'give' ) );
701
	}
702
703
	// Get the guest email.
704
	$guest_email = isset( $_POST['give_email'] ) ? $_POST['give_email'] : false;
705
706
	// Check email.
707
	if ( $guest_email && strlen( $guest_email ) > 0 ) {
708
		// Validate email.
709
		if ( ! is_email( $guest_email ) ) {
710
			// Invalid email.
711
			give_set_error( 'email_invalid', esc_html__( 'Invalid email.', 'give' ) );
712
		} else {
713
			// All is good to go.
714
			$valid_user_data['user_email'] = $guest_email;
715
716
			// Get user_id from donor if exist.
717
			$donor = new Give_Customer( $guest_email );
718
			if ( $donor->id && $donor->user_id ) {
719
				$valid_user_data['user_id'] = $donor->user_id;
720
			}
721
		}
722
	} else {
723
		// No email.
724
		give_set_error( 'email_empty', esc_html__( 'Enter an email.', 'give' ) );
725
	}
726
727
	// Loop through required fields and show error messages.
728
	foreach ( give_get_required_fields( $form_id ) as $field_name => $value ) {
729
		if ( in_array( $value, give_get_required_fields( $form_id ) ) && empty( $_POST[ $field_name ] ) ) {
730
			give_set_error( $value['error_id'], $value['error_message'] );
731
		}
732
	}
733
734
	return $valid_user_data;
735
}
736
737
/**
738
 * Register And Login New User
739
 *
740
 * @param array $user_data
741
 *
742
 * @access  private
743
 * @since   1.0
744
 * @return  integer
745
 */
746
function give_register_and_login_new_user( $user_data = array() ) {
747
	// Verify the array.
748
	if ( empty( $user_data ) ) {
749
		return - 1;
750
	}
751
752
	if ( give_get_errors() ) {
753
		return - 1;
754
	}
755
756
	$user_args = apply_filters( 'give_insert_user_args', array(
757
		'user_login'      => isset( $user_data['user_login'] ) ? $user_data['user_login'] : '',
758
		'user_pass'       => isset( $user_data['user_pass'] ) ? $user_data['user_pass'] : '',
759
		'user_email'      => isset( $user_data['user_email'] ) ? $user_data['user_email'] : '',
760
		'first_name'      => isset( $user_data['user_first'] ) ? $user_data['user_first'] : '',
761
		'last_name'       => isset( $user_data['user_last'] ) ? $user_data['user_last'] : '',
762
		'user_registered' => date( 'Y-m-d H:i:s' ),
763
		'role'            => get_option( 'default_role' ),
764
	), $user_data );
765
766
	// Insert new user.
767
	$user_id = wp_insert_user( $user_args );
768
769
	// Validate inserted user.
770
	if ( is_wp_error( $user_id ) ) {
771
		return - 1;
772
	}
773
774
	// Allow themes and plugins to filter the user data.
775
	$user_data = apply_filters( 'give_insert_user_data', $user_data, $user_args );
776
777
	/**
778
	 * Fires after inserting user.
779
	 *
780
	 * @since 1.0
781
	 *
782
	 * @param int   $user_id   User id.
783
	 * @param array $user_data Array containing user data.
784
	 */
785
	do_action( 'give_insert_user', $user_id, $user_data );
786
787
	// Login new user.
788
	give_log_user_in( $user_id, $user_data['user_login'], $user_data['user_pass'] );
789
790
	// Return user id.
791
	return $user_id;
792
}
793
794
/**
795
 * Get Donation Form User
796
 *
797
 * @param array $valid_data
798
 *
799
 * @access  private
800
 * @since   1.0
801
 * @return  array
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|array<string,array|false>?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
802
 */
803
function give_get_purchase_form_user( $valid_data = array() ) {
804
805
	// Initialize user.
806
	$user    = false;
807
	$is_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
808
809
	if ( $is_ajax ) {
810
		// Do not create or login the user during the ajax submission (check for errors only).
811
		return true;
812
	} elseif ( is_user_logged_in() ) {
813
		// Set the valid user as the logged in collected data.
814
		$user = $valid_data['logged_in_user'];
815
	} elseif ( $valid_data['need_new_user'] === true || $valid_data['need_user_login'] === true ) {
816
		// New user registration.
817
		if ( $valid_data['need_new_user'] === true ) {
818
			// Set user.
819
			$user = $valid_data['new_user_data'];
820
			// Register and login new user.
821
			$user['user_id'] = give_register_and_login_new_user( $user );
822
			// User login
823
		} elseif ( $valid_data['need_user_login'] === true && ! $is_ajax ) {
824
825
			/*
826
			 * The login form is now processed in the give_process_purchase_login() function.
827
			 * This is still here for backwards compatibility.
828
			 * This also allows the old login process to still work if a user removes the checkout login submit button.
829
			 *
830
			 * 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.
831
			 */
832
833
			// Set user.
834
			$user = $valid_data['login_user_data'];
835
			// Login user.
836
			give_log_user_in( $user['user_id'], $user['user_login'], $user['user_pass'] );
837
		}
838
	}
839
840
	// Check guest checkout.
841
	if ( false === $user && false === give_logged_in_only( $_POST['give-form-id'] ) ) {
842
		// Set user
843
		$user = $valid_data['guest_user_data'];
844
	}
845
846
	// Verify we have an user.
847
	if ( false === $user || empty( $user ) ) {
848
		// Return false.
849
		return false;
850
	}
851
852
	// Get user first name.
853
	if ( ! isset( $user['user_first'] ) || strlen( trim( $user['user_first'] ) ) < 1 ) {
854
		$user['user_first'] = isset( $_POST['give_first'] ) ? strip_tags( trim( $_POST['give_first'] ) ) : '';
855
	}
856
857
	// Get user last name.
858
	if ( ! isset( $user['user_last'] ) || strlen( trim( $user['user_last'] ) ) < 1 ) {
859
		$user['user_last'] = isset( $_POST['give_last'] ) ? strip_tags( trim( $_POST['give_last'] ) ) : '';
860
	}
861
862
	// Get the user's billing address details.
863
	$user['address']            = array();
864
	$user['address']['line1']   = ! empty( $_POST['card_address'] ) ? sanitize_text_field( $_POST['card_address'] ) : false;
865
	$user['address']['line2']   = ! empty( $_POST['card_address_2'] ) ? sanitize_text_field( $_POST['card_address_2'] ) : false;
866
	$user['address']['city']    = ! empty( $_POST['card_city'] ) ? sanitize_text_field( $_POST['card_city'] ) : false;
867
	$user['address']['state']   = ! empty( $_POST['card_state'] ) ? sanitize_text_field( $_POST['card_state'] ) : false;
868
	$user['address']['country'] = ! empty( $_POST['billing_country'] ) ? sanitize_text_field( $_POST['billing_country'] ) : false;
869
	$user['address']['zip']     = ! empty( $_POST['card_zip'] ) ? sanitize_text_field( $_POST['card_zip'] ) : false;
870
871
	if ( empty( $user['address']['country'] ) ) {
872
		$user['address'] = false;
873
	} // Country will always be set if address fields are present.
874
875
	if ( ! empty( $user['user_id'] ) && $user['user_id'] > 0 && ! empty( $user['address'] ) ) {
876
		// Store the address in the user's meta so the donation form can be pre-populated with it on return purchases.
877
		update_user_meta( $user['user_id'], '_give_user_address', $user['address'] );
878
	}
879
880
	// Return valid user.
881
	return $user;
882
}
883
884
/**
885
 * Validates the credit card info
886
 *
887
 * @access  private
888
 * @since   1.0
889
 * @return  array
890
 */
891
function give_purchase_form_validate_cc() {
892
893
	$card_data = give_get_purchase_cc_info();
894
895
	// Validate the card zip.
896
	if ( ! empty( $card_data['card_zip'] ) ) {
897
		if ( ! give_purchase_form_validate_cc_zip( $card_data['card_zip'], $card_data['card_country'] ) ) {
898
			give_set_error( 'invalid_cc_zip', esc_html__( 'The zip / postal code you entered for your billing address is invalid.', 'give' ) );
899
		}
900
	}
901
902
	// Ensure no spaces.
903
	if ( ! empty( $card_data['card_number'] ) ) {
904
		$card_data['card_number'] = str_replace( '+', '', $card_data['card_number'] ); // no "+" signs
905
		$card_data['card_number'] = str_replace( ' ', '', $card_data['card_number'] ); // No spaces
906
	}
907
908
	// This should validate card numbers at some point too.
909
	return $card_data;
910
}
911
912
/**
913
 * Get Credit Card Info
914
 *
915
 * @access  private
916
 * @since   1.0
917
 * @return  array
918
 */
919
function give_get_purchase_cc_info() {
920
	$cc_info                   = array();
921
	$cc_info['card_name']      = isset( $_POST['card_name'] ) ? sanitize_text_field( $_POST['card_name'] ) : '';
922
	$cc_info['card_number']    = isset( $_POST['card_number'] ) ? sanitize_text_field( $_POST['card_number'] ) : '';
923
	$cc_info['card_cvc']       = isset( $_POST['card_cvc'] ) ? sanitize_text_field( $_POST['card_cvc'] ) : '';
924
	$cc_info['card_exp_month'] = isset( $_POST['card_exp_month'] ) ? sanitize_text_field( $_POST['card_exp_month'] ) : '';
925
	$cc_info['card_exp_year']  = isset( $_POST['card_exp_year'] ) ? sanitize_text_field( $_POST['card_exp_year'] ) : '';
926
	$cc_info['card_address']   = isset( $_POST['card_address'] ) ? sanitize_text_field( $_POST['card_address'] ) : '';
927
	$cc_info['card_address_2'] = isset( $_POST['card_address_2'] ) ? sanitize_text_field( $_POST['card_address_2'] ) : '';
928
	$cc_info['card_city']      = isset( $_POST['card_city'] ) ? sanitize_text_field( $_POST['card_city'] ) : '';
929
	$cc_info['card_state']     = isset( $_POST['card_state'] ) ? sanitize_text_field( $_POST['card_state'] ) : '';
930
	$cc_info['card_country']   = isset( $_POST['billing_country'] ) ? sanitize_text_field( $_POST['billing_country'] ) : '';
931
	$cc_info['card_zip']       = isset( $_POST['card_zip'] ) ? sanitize_text_field( $_POST['card_zip'] ) : '';
932
933
	// Return cc info
934
	return $cc_info;
935
}
936
937
/**
938
 * Validate zip code based on country code
939
 *
940
 * @since  1.0
941
 *
942
 * @param int    $zip
943
 * @param string $country_code
944
 *
945
 * @return bool|mixed|void
946
 */
947
function give_purchase_form_validate_cc_zip( $zip = 0, $country_code = '' ) {
948
	$ret = false;
949
950
	if ( empty( $zip ) || empty( $country_code ) ) {
951
		return $ret;
952
	}
953
954
	$country_code = strtoupper( $country_code );
955
956
	$zip_regex = array(
957
		'AD' => 'AD\d{3}',
958
		'AM' => '(37)?\d{4}',
959
		'AR' => '^([A-Z]{1}\d{4}[A-Z]{3}|[A-Z]{1}\d{4}|\d{4})$',
960
		'AS' => '96799',
961
		'AT' => '\d{4}',
962
		'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})$',
963
		'AX' => '22\d{3}',
964
		'AZ' => '\d{4}',
965
		'BA' => '\d{5}',
966
		'BB' => '(BB\d{5})?',
967
		'BD' => '\d{4}',
968
		'BE' => '^[1-9]{1}[0-9]{3}$',
969
		'BG' => '\d{4}',
970
		'BH' => '((1[0-2]|[2-9])\d{2})?',
971
		'BM' => '[A-Z]{2}[ ]?[A-Z0-9]{2}',
972
		'BN' => '[A-Z]{2}[ ]?\d{4}',
973
		'BR' => '\d{5}[\-]?\d{3}',
974
		'BY' => '\d{6}',
975
		'CA' => '^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$',
976
		'CC' => '6799',
977
		'CH' => '^[1-9][0-9][0-9][0-9]$',
978
		'CK' => '\d{4}',
979
		'CL' => '\d{7}',
980
		'CN' => '\d{6}',
981
		'CR' => '\d{4,5}|\d{3}-\d{4}',
982
		'CS' => '\d{5}',
983
		'CV' => '\d{4}',
984
		'CX' => '6798',
985
		'CY' => '\d{4}',
986
		'CZ' => '\d{3}[ ]?\d{2}',
987
		'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',
988
		'DK' => '^([D-d][K-k])?( |-)?[1-9]{1}[0-9]{3}$',
989
		'DO' => '\d{5}',
990
		'DZ' => '\d{5}',
991
		'EC' => '([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?',
992
		'EE' => '\d{5}',
993
		'EG' => '\d{5}',
994
		'ES' => '^([1-9]{2}|[0-9][1-9]|[1-9][0-9])[0-9]{3}$',
995
		'ET' => '\d{4}',
996
		'FI' => '\d{5}',
997
		'FK' => 'FIQQ 1ZZ',
998
		'FM' => '(9694[1-4])([ \-]\d{4})?',
999
		'FO' => '\d{3}',
1000
		'FR' => '^(F-)?((2[A|B])|[0-9]{2})[0-9]{3}$',
1001
		'GE' => '\d{4}',
1002
		'GF' => '9[78]3\d{2}',
1003
		'GL' => '39\d{2}',
1004
		'GN' => '\d{3}',
1005
		'GP' => '9[78][01]\d{2}',
1006
		'GR' => '\d{3}[ ]?\d{2}',
1007
		'GS' => 'SIQQ 1ZZ',
1008
		'GT' => '\d{5}',
1009
		'GU' => '969[123]\d([ \-]\d{4})?',
1010
		'GW' => '\d{4}',
1011
		'HM' => '\d{4}',
1012
		'HN' => '(?:\d{5})?',
1013
		'HR' => '\d{5}',
1014
		'HT' => '\d{4}',
1015
		'HU' => '\d{4}',
1016
		'ID' => '\d{5}',
1017
		'IE' => '((D|DUBLIN)?([1-9]|6[wW]|1[0-8]|2[024]))?',
1018
		'IL' => '\d{5}',
1019
		'IN' => '^[1-9][0-9][0-9][0-9][0-9][0-9]$', // india
1020
		'IO' => 'BBND 1ZZ',
1021
		'IQ' => '\d{5}',
1022
		'IS' => '\d{3}',
1023
		'IT' => '^(V-|I-)?[0-9]{5}$',
1024
		'JO' => '\d{5}',
1025
		'JP' => '\d{3}-\d{4}',
1026
		'KE' => '\d{5}',
1027
		'KG' => '\d{6}',
1028
		'KH' => '\d{5}',
1029
		'KR' => '\d{3}[\-]\d{3}',
1030
		'KW' => '\d{5}',
1031
		'KZ' => '\d{6}',
1032
		'LA' => '\d{5}',
1033
		'LB' => '(\d{4}([ ]?\d{4})?)?',
1034
		'LI' => '(948[5-9])|(949[0-7])',
1035
		'LK' => '\d{5}',
1036
		'LR' => '\d{4}',
1037
		'LS' => '\d{3}',
1038
		'LT' => '\d{5}',
1039
		'LU' => '\d{4}',
1040
		'LV' => '\d{4}',
1041
		'MA' => '\d{5}',
1042
		'MC' => '980\d{2}',
1043
		'MD' => '\d{4}',
1044
		'ME' => '8\d{4}',
1045
		'MG' => '\d{3}',
1046
		'MH' => '969[67]\d([ \-]\d{4})?',
1047
		'MK' => '\d{4}',
1048
		'MN' => '\d{6}',
1049
		'MP' => '9695[012]([ \-]\d{4})?',
1050
		'MQ' => '9[78]2\d{2}',
1051
		'MT' => '[A-Z]{3}[ ]?\d{2,4}',
1052
		'MU' => '(\d{3}[A-Z]{2}\d{3})?',
1053
		'MV' => '\d{5}',
1054
		'MX' => '\d{5}',
1055
		'MY' => '\d{5}',
1056
		'NC' => '988\d{2}',
1057
		'NE' => '\d{4}',
1058
		'NF' => '2899',
1059
		'NG' => '(\d{6})?',
1060
		'NI' => '((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?',
1061
		'NL' => '^[1-9][0-9]{3}\s?([a-zA-Z]{2})?$',
1062
		'NO' => '\d{4}',
1063
		'NP' => '\d{5}',
1064
		'NZ' => '\d{4}',
1065
		'OM' => '(PC )?\d{3}',
1066
		'PF' => '987\d{2}',
1067
		'PG' => '\d{3}',
1068
		'PH' => '\d{4}',
1069
		'PK' => '\d{5}',
1070
		'PL' => '\d{2}-\d{3}',
1071
		'PM' => '9[78]5\d{2}',
1072
		'PN' => 'PCRN 1ZZ',
1073
		'PR' => '00[679]\d{2}([ \-]\d{4})?',
1074
		'PT' => '\d{4}([\-]\d{3})?',
1075
		'PW' => '96940',
1076
		'PY' => '\d{4}',
1077
		'RE' => '9[78]4\d{2}',
1078
		'RO' => '\d{6}',
1079
		'RS' => '\d{5}',
1080
		'RU' => '\d{6}',
1081
		'SA' => '\d{5}',
1082
		'SE' => '^(s-|S-){0,1}[0-9]{3}\s?[0-9]{2}$',
1083
		'SG' => '\d{6}',
1084
		'SH' => '(ASCN|STHL) 1ZZ',
1085
		'SI' => '\d{4}',
1086
		'SJ' => '\d{4}',
1087
		'SK' => '\d{3}[ ]?\d{2}',
1088
		'SM' => '4789\d',
1089
		'SN' => '\d{5}',
1090
		'SO' => '\d{5}',
1091
		'SZ' => '[HLMS]\d{3}',
1092
		'TC' => 'TKCA 1ZZ',
1093
		'TH' => '\d{5}',
1094
		'TJ' => '\d{6}',
1095
		'TM' => '\d{6}',
1096
		'TN' => '\d{4}',
1097
		'TR' => '\d{5}',
1098
		'TW' => '\d{3}(\d{2})?',
1099
		'UA' => '\d{5}',
1100
		'UK' => '^(GIR|[A-Z]\d[A-Z\d]??|[A-Z]{2}\d[A-Z\d]??)[ ]??(\d[A-Z]{2})$',
1101
		'US' => '^\d{5}([\-]?\d{4})?$',
1102
		'UY' => '\d{5}',
1103
		'UZ' => '\d{6}',
1104
		'VA' => '00120',
1105
		'VE' => '\d{4}',
1106
		'VI' => '008(([0-4]\d)|(5[01]))([ \-]\d{4})?',
1107
		'WF' => '986\d{2}',
1108
		'YT' => '976\d{2}',
1109
		'YU' => '\d{5}',
1110
		'ZA' => '\d{4}',
1111
		'ZM' => '\d{5}',
1112
	);
1113
1114
	if ( ! isset( $zip_regex[ $country_code ] ) || preg_match( '/' . $zip_regex[ $country_code ] . '/i', $zip ) ) {
1115
		$ret = true;
1116
	}
1117
1118
	return apply_filters( 'give_is_zip_valid', $ret, $zip, $country_code );
1119
}
1120
1121
1122
/**
1123
 * Auto set correct donation level id on basis of amount.
1124
 *
1125
 * 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.
1126
 *
1127
 * @param array $valid_data
1128
 * @param array $data
1129
 *
1130
 * @return bool
1131
 */
1132
function give_validate_multi_donation_form_level( $valid_data, $data ) {
0 ignored issues
show
Unused Code introduced by
The parameter $valid_data is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1133
	/* @var Give_Donate_Form $form */
1134
	$form = new Give_Donate_Form( $data['give-form-id'] );
1135
1136
	$donation_level_matched = false;
1137
1138
	if ( $form->is_multi_type_donation_form() ) {
1139
1140
		// Bailout.
1141
		if ( ! ( $variable_prices = $form->get_prices() ) ) {
1142
			return false;
1143
		}
1144
1145
		// Sanitize donation amount.
1146
		$data['give-amount'] = give_sanitize_amount( $data['give-amount'] );
1147
1148
		// Get number of decimals.
1149
		$default_decimals = give_get_price_decimals();
1150
1151
		if ( $data['give-amount'] === give_sanitize_amount( give_get_price_option_amount( $data['give-form-id'], $data['give-price-id'] ), $default_decimals ) ) {
1152
			return true;
1153
		}
1154
1155
		// Find correct donation level from all donation levels.
1156
		foreach ( $variable_prices as $variable_price ) {
1157
			// Sanitize level amount.
1158
			$variable_price['_give_amount'] = give_sanitize_amount( $variable_price['_give_amount'], $default_decimals );
1159
1160
			// Set first match donation level ID.
1161
			if ( $data['give-amount'] === $variable_price['_give_amount'] ) {
1162
				$_POST['give-price-id'] = $variable_price['_give_id']['level_id'];
1163
				$donation_level_matched = true;
1164
				break;
1165
			}
1166
		}
1167
1168
		// If donation amount is not find in donation levels then check if form has custom donation feature enable or not.
1169
		// If yes then set price id to custom if amount is greater then custom minimum amount (if any).
1170
		if (
1171
			! $donation_level_matched
1172
			&& ( give_is_setting_enabled( get_post_meta( $data['give-form-id'], '_give_custom_amount', true ) ) )
1173
		) {
1174
			// Sanitize custom minimum amount.
1175
			$custom_minimum_amount = give_sanitize_amount( get_post_meta( $data['give-form-id'], '_give_custom_amount_minimum', true ), $default_decimals );
1176
1177
			if ( $data['give-amount'] >= $custom_minimum_amount ) {
1178
				$_POST['give-price-id'] = 'custom';
1179
				$donation_level_matched = true;
1180
			}
1181
		}
1182
	}
1183
1184
	return ( $donation_level_matched ? true : false );
1185
}
1186
1187
add_action( 'give_checkout_error_checks', 'give_validate_multi_donation_form_level', 10, 2 );
1188