Test Failed
Push — master ( f5256c...25a383 )
by Devin
07:02
created

process-donation.php ➔ give_get_required_fields()   D

Complexity

Conditions 14
Paths 126

Size

Total Lines 100

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
nc 126
nop 1
dl 0
loc 100
rs 4.84
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
2
/**
3
 * Process Donation
4
 *
5
 * @package     Give
6
 * @subpackage  Functions
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.0
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Process Donation Form
19
 *
20
 * Handles the donation form process.
21
 *
22
 * @access private
23
 * @since  1.0
24
 *
25
 * @throws ReflectionException Exception Handling.
26
 *
27
 * @return mixed
28
 */
29
function give_process_donation_form() {
30
31
	// Sanitize Posted Data.
32
	$post_data  = give_clean( $_POST ); // WPCS: input var ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
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 );
0 ignored issues
show
Bug introduced by
It seems like $valid_data defined by give_donation_form_validate_fields() on line 60 can also be of type boolean; however, give_get_donation_form_user() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
82
83
	if ( false === $valid_data || give_get_errors() || ! $user ) {
84
		if ( $is_ajax ) {
85
			/**
86
			 * Fires when AJAX sends back errors from the donation form.
87
			 *
88
			 * @since 1.0
89
			 */
90
			do_action( 'give_ajax_donation_errors' );
91
			give_die();
92
		} else {
93
			return false;
94
		}
95
	}
96
97
	// If AJAX send back success to proceed with form submission.
98
	if ( $is_ajax ) {
99
		echo 'success';
100
		give_die();
101
	}
102
103
	/**
104
	 * Fires action after donation form field validated.
105
	 *
106
	 * @since 2.2.0
107
	 */
108
	do_action( 'give_process_donation_after_validation' );
109
110
	// Setup user information.
111
	$user_info = array(
112
		'id'         => $user['user_id'],
113
		'title'      => $user['user_title'],
114
		'email'      => $user['user_email'],
115
		'first_name' => $user['user_first'],
116
		'last_name'  => $user['user_last'],
117
		'address'    => $user['address'],
118
	);
119
120
	$auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
121
122
	// Donation form ID.
123
	$form_id = isset( $post_data['give-form-id'] ) ? absint( $post_data['give-form-id'] ) : 0;
124
125
	$price = isset( $post_data['give-amount'] ) ?
126
		(float) apply_filters( 'give_donation_total', give_maybe_sanitize_amount( $post_data['give-amount'], array( 'currency' => give_get_currency( $form_id ) ) ) ) :
127
		'0.00';
128
	$purchase_key = strtolower( md5( $user['user_email'] . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'give', true ) ) );
129
130
	// Setup donation information.
131
	$donation_data = array(
132
		'price'         => $price,
133
		'purchase_key'  => $purchase_key,
134
		'user_email'    => $user['user_email'],
135
		'date'          => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
136
		'user_info'     => stripslashes_deep( $user_info ),
137
		'post_data'     => $post_data,
138
		'gateway'       => $valid_data['gateway'],
139
		'card_info'     => $valid_data['cc_info'],
140
	);
141
142
	// Add the user data for hooks.
143
	$valid_data['user'] = $user;
144
145
	/**
146
	 * Fires before donation form gateway.
147
	 *
148
	 * Allow you to hook to donation form before the gateway.
149
	 *
150
	 * @since 1.0
151
	 *
152
	 * @param array      $post_data  Array of variables passed via the HTTP POST.
153
	 * @param array      $user_info  Array containing basic user information.
154
	 * @param bool|array $valid_data Validate fields.
155
	 */
156
	do_action( 'give_checkout_before_gateway', $post_data, $user_info, $valid_data );
157
158
	// Sanity check for price.
159
	if ( ! $donation_data['price'] ) {
160
		// Revert to manual.
161
		$donation_data['gateway'] = 'manual';
162
		$_POST['give-gateway']    = 'manual';
163
	}
164
165
	/**
166
	 * Allow the donation data to be modified before it is sent to the gateway.
167
	 *
168
	 * @since 1.7
169
	 */
170
	$donation_data = apply_filters( 'give_donation_data_before_gateway', $donation_data, $valid_data );
171
172
	// Setup the data we're storing in the donation session.
173
	$session_data = $donation_data;
174
175
	// Make sure credit card numbers are never stored in sessions.
176
	unset( $session_data['card_info']['card_number'] );
177
	unset( $session_data['post_data']['card_number'] );
178
179
	// Used for showing data to non logged-in users after donation, and for other plugins needing donation data.
180
	give_set_purchase_session( $session_data );
181
182
	// Send info to the gateway for payment processing.
183
	give_send_to_gateway( $donation_data['gateway'], $donation_data );
184
	give_die();
185
}
186
187
add_action( 'give_purchase', 'give_process_donation_form' );
188
add_action( 'wp_ajax_give_process_donation', 'give_process_donation_form' );
189
add_action( 'wp_ajax_nopriv_give_process_donation', 'give_process_donation_form' );
190
191
/**
192
 * Verify that when a logged in user makes a donation that the email address used doesn't belong to a different customer.
193
 *
194
 * @since  1.7
195
 *
196
 * @param  array $valid_data Validated data submitted for the donation.
197
 *
198
 * @return void
199
 */
200
function give_check_logged_in_user_for_existing_email( $valid_data ) {
201
202
	// Verify that the email address belongs to this customer.
203
	if ( is_user_logged_in() ) {
204
205
		$submitted_email = $valid_data['logged_in_user']['user_email'];
206
		$donor           = new Give_Donor( get_current_user_id(), true );
207
208
		// If this email address is not registered with this customer, see if it belongs to any other customer.
209
		if (
210
			$submitted_email !== $donor->email
211
			&& ( is_array( $donor->emails ) && ! in_array( $submitted_email, $donor->emails, true ) )
212
		) {
213
			$found_donor = new Give_Donor( $submitted_email );
214
215
			if ( $found_donor->id > 0 ) {
216
				give_set_error(
217
					'give-customer-email-exists',
218
					sprintf(
219
						/* translators: 1. Donor Email, 2. Submitted Email */
220
						__( 'You are logged in as %1$s, and are submitting a donation as %2$s, which is an existing donor. To ensure that the email address is tied to the correct donor, please submit this donation from a logged-out browser, or choose another email address.', 'give' ),
221
						$donor->email,
222
						$submitted_email
223
					)
224
				);
225
			}
226
		}
227
	}
228
}
229
230
add_action( 'give_checkout_error_checks', 'give_check_logged_in_user_for_existing_email', 10, 1 );
231
232
/**
233
 * Process the checkout login form
234
 *
235
 * @access private
236
 * @since  1.0
237
 *
238
 * @return void
239
 */
240
function give_process_form_login() {
241
242
	$is_ajax   = ! empty( $_POST['give_ajax'] ) ? give_clean( $_POST['give_ajax'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
243
	$referrer  = wp_get_referer();
244
	$user_data = give_donation_form_validate_user_login();
245
246
	if ( give_get_errors() || $user_data['user_id'] < 1 ) {
247
		if ( $is_ajax ) {
248
			/**
249
			 * Fires when AJAX sends back errors from the donation form.
250
			 *
251
			 * @since 1.0
252
			 */
253
			ob_start();
254
			do_action( 'give_ajax_donation_errors' );
255
			$message = ob_get_contents();
256
			ob_end_clean();
257
			wp_send_json_error( $message );
258
		} else {
259
			wp_safe_redirect( $referrer );
260
			exit;
261
		}
262
	}
263
264
	give_log_user_in( $user_data['user_id'], $user_data['user_login'], $user_data['user_pass'] );
265
266
	if ( $is_ajax ) {
267
		$message = Give()->notices->print_frontend_notice(
268
			sprintf(
269
				/* translators: %s: user first name */
270
				esc_html__( 'Welcome %s! You have successfully logged into your account.', 'give' ),
271
				( ! empty( $user_data['user_first'] ) ) ? $user_data['user_first'] : $user_data['user_login']
272
			),
273
			false,
274
			'success'
275
		);
276
277
		wp_send_json_success( $message );
278
	} else {
279
		wp_safe_redirect( $referrer );
280
	}
281
}
282
283
add_action( 'wp_ajax_give_process_donation_login', 'give_process_form_login' );
284
add_action( 'wp_ajax_nopriv_give_process_donation_login', 'give_process_form_login' );
285
286
/**
287
 * Donation Form Validate Fields.
288
 *
289
 * @access private
290
 * @since  1.0
291
 *
292
 * @return bool|array
293
 */
294
function give_donation_form_validate_fields() {
295
296
	$post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
297
298
	// Validate Honeypot First.
299
	if ( ! empty( $post_data['give-honeypot'] ) ) {
300
		give_set_error( 'invalid_honeypot', esc_html__( 'Honeypot field detected. Go away bad bot!', 'give' ) );
301
	}
302
303
	// Check spam detect.
304
	if (
305
		isset( $post_data['action'] ) &&
306
		give_is_setting_enabled( give_get_option( 'akismet_spam_protection' ) ) &&
307
		give_is_spam_donation()
308
	) {
309
		give_set_error( 'spam_donation', __( 'This donation has been flagged as spam. Please try again.', 'give' ) );
310
	}
311
312
	// Start an array to collect valid data.
313
	$valid_data = array(
314
		'gateway'          => give_donation_form_validate_gateway(), // Gateway fallback (amount is validated here).
315
		'need_new_user'    => false,     // New user flag.
316
		'need_user_login'  => false,     // Login user flag.
317
		'logged_user_data' => array(),   // Logged user collected data.
318
		'new_user_data'    => array(),   // New user collected data.
319
		'login_user_data'  => array(),   // Login user collected data.
320
		'guest_user_data'  => array(),   // Guest user collected data.
321
		'cc_info'          => give_donation_form_validate_cc(), // Credit card info.
322
	);
323
324
	$form_id = intval( $post_data['give-form-id'] );
325
326
	// Validate agree to terms.
327
	if ( give_is_terms_enabled( $form_id ) ) {
328
		give_donation_form_validate_agree_to_terms();
329
	}
330
331
	if ( is_user_logged_in() ) {
332
333
		// Collect logged in user data.
334
		$valid_data['logged_in_user'] = give_donation_form_validate_logged_in_user();
335
	} elseif (
336
		isset( $post_data['give-purchase-var'] ) &&
337
		'needs-to-register' === $post_data['give-purchase-var'] &&
338
		! empty( $post_data['give_create_account'] )
339
	) {
340
341
		// Set new user registration as required.
342
		$valid_data['need_new_user'] = true;
343
344
		// Validate new user data.
345
		$valid_data['new_user_data'] = give_donation_form_validate_new_user();
346
	} elseif (
347
		isset( $post_data['give-purchase-var'] ) &&
348
		'needs-to-login' === $post_data['give-purchase-var']
349
	) {
350
351
		// Set user login as required.
352
		$valid_data['need_user_login'] = true;
353
354
		// Validate users login info.
355
		$valid_data['login_user_data'] = give_donation_form_validate_user_login();
356
	} else {
357
358
		// Not registering or logging in, so setup guest user data.
359
		$valid_data['guest_user_data'] = give_donation_form_validate_guest_user();
360
	}
361
362
	// Return collected data.
363
	return $valid_data;
364
}
365
366
/**
367
 * Detect spam donation.
368
 *
369
 * @since 1.8.14
370
 *
371
 * @return bool|mixed
372
 */
373
function give_is_spam_donation() {
374
	$spam = false;
375
376
	$user_agent = (string) isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
0 ignored issues
show
introduced by
Due to using Batcache, server side based client related logic will not work, use JS instead.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
377
378
	if ( strlen( $user_agent ) < 2 ) {
379
		$spam = true;
380
	}
381
382
	// Allow developer to customized Akismet spam detect API call and it's response.
383
	return apply_filters( 'give_spam', $spam );
384
}
385
386
/**
387
 * Donation Form Validate Gateway
388
 *
389
 * Validate the gateway and donation amount.
390
 *
391
 * @access private
392
 * @since  1.0
393
 *
394
 * @return string
395
 */
396
function give_donation_form_validate_gateway() {
397
398
	$post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
399
	$form_id   = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
400
	$amount    = ! empty( $post_data['give-amount'] ) ? give_maybe_sanitize_amount( $post_data['give-amount'] ) : 0;
401
	$gateway   = ! empty( $post_data['give-gateway'] ) ? $post_data['give-gateway'] : 0;
402
403
	// Bailout, if payment gateway is not submitted with donation form data.
404
	if ( empty( $gateway ) ) {
405
406
		give_set_error( 'empty_gateway', __( 'The donation form will process with a valid payment gateway.', 'give' ) );
407
408
	} elseif ( ! give_is_gateway_active( $gateway ) ) {
409
410
		give_set_error( 'invalid_gateway', __( 'The selected payment gateway is not enabled.', 'give' ) );
411
412
	} elseif ( empty( $amount ) ) {
413
414
		give_set_error( 'invalid_donation_amount', __( 'Please insert a valid donation amount.', 'give' ) );
415
416
	} elseif ( ! give_verify_minimum_price( 'minimum' ) ) {
417
418
		give_set_error(
419
			'invalid_donation_minimum',
420
			sprintf(
421
				/* translators: %s: minimum donation amount */
422
				__( 'This form has a minimum donation amount of %s.', 'give' ),
423
				give_currency_filter(
424
					give_format_amount( give_get_form_minimum_price( $form_id ),
0 ignored issues
show
Documentation introduced by
give_get_form_minimum_price($form_id) is of type false|double, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
425
						array(
426
							'sanitize' => false,
427
						)
428
					)
429
				)
430
			)
431
		);
432
	} elseif ( ! give_verify_minimum_price( 'maximum' ) ) {
433
434
		give_set_error(
435
			'invalid_donation_maximum',
436
			sprintf(
437
				/* translators: %s: Maximum donation amount */
438
				__( 'This form has a maximum donation amount of %s.', 'give' ),
439
				give_currency_filter(
440
					give_format_amount( give_get_form_maximum_price( $form_id ),
0 ignored issues
show
Documentation introduced by
give_get_form_maximum_price($form_id) is of type false|double, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
441
						array(
442
							'sanitize' => false,
443
						)
444
					)
445
				)
446
			)
447
		);
448
	} // End if().
449
450
	return $gateway;
451
452
}
453
454
/**
455
 * Donation Form Validate Minimum or Maximum Donation Amount
456
 *
457
 * @access private
458
 * @since  1.3.6
459
 * @since  2.1 Added support for give maximum amount.
460
 * @since  2.1.3 Added new filter to modify the return value.
461
 *
462
 * @param string $amount_range Which amount needs to verify? minimum or maximum.
463
 *
464
 * @return bool
465
 */
466
function give_verify_minimum_price( $amount_range = 'minimum' ) {
467
468
	$post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
469
	$form_id   = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
470
	$amount    = ! empty( $post_data['give-amount'] ) ? give_maybe_sanitize_amount( $post_data['give-amount'], array( 'currency' => give_get_currency( $form_id ) ) ) : 0;
471
	$price_id  = isset( $post_data['give-price-id'] ) ? absint( $post_data['give-price-id'] ) : '';
472
473
	$variable_prices = give_has_variable_prices( $form_id );
474
	$price_ids       = array_map( 'absint', give_get_variable_price_ids( $form_id ) );
475
	$verified_stat   = false;
476
477
	if ( $variable_prices && in_array( $price_id, $price_ids, true ) ) {
478
479
		$price_level_amount = give_get_price_option_amount( $form_id, $price_id );
480
481
		if ( $price_level_amount == $amount ) {
482
			$verified_stat = true;
483
		}
484
	}
485
486
	if ( ! $verified_stat ) {
487
		switch ( $amount_range ) {
488
			case 'minimum' :
489
				$verified_stat = ( give_get_form_minimum_price( $form_id ) > $amount ) ? false : true;
490
				break;
491
			case 'maximum' :
492
				$verified_stat = ( give_get_form_maximum_price( $form_id ) < $amount ) ? false : true;
493
				break;
494
		}
495
	}
496
497
	/**
498
	 * Filter the verify amount
499
	 *
500
	 * @since 2.1.3
501
	 *
502
	 * @param bool    $verified_stat Was verification passed or not?
503
	 * @param string  $amount_range  Type of the amount.
504
	 * @param integer $form_id       Give Donation Form ID.
505
	 */
506
	return apply_filters( 'give_verify_minimum_maximum_price', $verified_stat, $amount_range, $form_id );
507
}
508
509
/**
510
 * Donation form validate agree to "Terms and Conditions".
511
 *
512
 * @access private
513
 * @since  1.0
514
 *
515
 * @return void
516
 */
517
function give_donation_form_validate_agree_to_terms() {
518
519
	$agree_to_terms = ! empty( $_POST['give_agree_to_terms'] ) ? give_clean( $_POST['give_agree_to_terms'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
520
521
	// Proceed only, if donor agreed to terms.
522
	if ( ! $agree_to_terms ) {
523
524
		// User did not agree.
525
		give_set_error( 'agree_to_terms', apply_filters( 'give_agree_to_terms_text', __( 'You must agree to the terms and conditions.', 'give' ) ) );
526
	}
527
}
528
529
/**
530
 * Donation Form Required Fields.
531
 *
532
 * @access private
533
 * @since  1.0
534
 *
535
 * @param  int $form_id Donation Form ID.
536
 *
537
 * @return array
538
 */
539
function give_get_required_fields( $form_id ) {
540
541
	$payment_mode = give_get_chosen_gateway( $form_id );
542
543
	$required_fields = array(
544
		'give_email' => array(
545
			'error_id'      => 'invalid_email',
546
			'error_message' => __( 'Please enter a valid email address.', 'give' ),
547
		),
548
		'give_first' => array(
549
			'error_id'      => 'invalid_first_name',
550
			'error_message' => __( 'Please enter your first name.', 'give' ),
551
		),
552
	);
553
554
	$name_title_prefix = give_is_name_title_prefix_required( $form_id );
555
	if ( $name_title_prefix ) {
556
		$required_fields['give_title'] = array(
557
			'error_id'      => 'invalid_title',
558
			'error_message' => __( 'Please enter your title.', 'give' ),
559
		);
560
	}
561
562
	$require_address = give_require_billing_address( $payment_mode );
563
564
	if ( $require_address ) {
565
		$required_fields['card_address']    = array(
566
			'error_id'      => 'invalid_card_address',
567
			'error_message' => __( 'Please enter your primary billing address.', 'give' ),
568
		);
569
		$required_fields['card_zip']        = array(
570
			'error_id'      => 'invalid_zip_code',
571
			'error_message' => __( 'Please enter your zip / postal code.', 'give' ),
572
		);
573
		$required_fields['card_city']       = array(
574
			'error_id'      => 'invalid_city',
575
			'error_message' => __( 'Please enter your billing city.', 'give' ),
576
		);
577
		$required_fields['billing_country'] = array(
578
			'error_id'      => 'invalid_country',
579
			'error_message' => __( 'Please select your billing country.', 'give' ),
580
		);
581
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
582
583
		$required_fields['card_state'] = array(
584
			'error_id'      => 'invalid_state',
585
			'error_message' => __( 'Please enter billing state / province / County.', 'give' ),
586
		);
587
588
		$country = ! empty( $_POST['billing_country'] ) ? give_clean( $_POST['billing_country'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
589
590
		// Check if billing country already exists.
591
		if ( $country ) {
592
593
			// Get the country list that does not required any states init.
594
			$states_country = give_states_not_required_country_list();
595
596
			// Check if states is empty or not.
597
			if ( array_key_exists( $country, $states_country ) ) {
598
				// If states is empty remove the required fields of state in billing cart.
599
				unset( $required_fields['card_state'] );
600
			}
601
		}
602
	} // End if().
603
604
	if ( give_is_company_field_enabled( $form_id ) ) {
605
		$form_option    = give_get_meta( $form_id, '_give_company_field', true );
606
		$global_setting = give_get_option( 'company_field' );
607
608
		$is_company_field_required = false;
609
610
		if ( ! empty( $form_option ) && give_is_setting_enabled( $form_option, array( 'required' ) ) ) {
0 ignored issues
show
Documentation introduced by
array('required') is of type array<integer,string,{"0":"string"}>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
611
			$is_company_field_required = true;
612
613
		} elseif ( 'global' === $form_option && give_is_setting_enabled( $global_setting, array( 'required' ) ) ) {
0 ignored issues
show
Documentation introduced by
array('required') is of type array<integer,string,{"0":"string"}>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
614
			$is_company_field_required = true;
615
616
		} elseif ( empty( $form_option ) && give_is_setting_enabled( $global_setting, array( 'required' ) ) ) {
0 ignored issues
show
Documentation introduced by
array('required') is of type array<integer,string,{"0":"string"}>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
617
			$is_company_field_required = true;
618
619
		}
620
621
		if ( $is_company_field_required ) {
622
			$required_fields['give_company_name'] = array(
623
				'error_id'      => 'invalid_company',
624
				'error_message' => __( 'Please enter Company Name.', 'give' ),
625
			);
626
		}
627
	}
628
629
	/**
630
	 * Filters the donation form required field.
631
	 *
632
	 * @since 1.7
633
	 */
634
	$required_fields = apply_filters( 'give_donation_form_required_fields', $required_fields, $form_id );
635
636
	return $required_fields;
637
638
}
639
640
/**
641
 * Check if the Billing Address is required
642
 *
643
 * @since  1.0.1
644
 *
645
 * @param string $payment_mode Payment Mode.
646
 *
647
 * @return bool
648
 */
649
function give_require_billing_address( $payment_mode ) {
650
651
	$return          = false;
652
	$billing_country = ! empty( $_POST['billing_country'] ) ? give_clean( $_POST['billing_country'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
653
654
	if ( $billing_country || did_action( "give_{$payment_mode}_cc_form" ) || did_action( 'give_cc_form' ) ) {
655
		$return = true;
656
	}
657
658
	// Let payment gateways and other extensions determine if address fields should be required.
659
	return apply_filters( 'give_require_billing_address', $return );
660
661
}
662
663
/**
664
 * Donation Form Validate Logged In User.
665
 *
666
 * @access private
667
 * @since  1.0
668
 *
669
 * @return array
670
 */
671
function give_donation_form_validate_logged_in_user() {
672
673
	$post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
674
	$user_id   = get_current_user_id();
675
	$form_id   = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
676
677
	// Start empty array to collect valid user data.
678
	$valid_user_data = array(
679
680
		// Assume there will be errors.
681
		'user_id' => - 1,
682
	);
683
684
	// Proceed on;y, if valid $user_id found.
685
	if ( $user_id > 0 ) {
686
687
		// Get the logged in user data.
688
		$user_data = get_userdata( $user_id );
689
690
		// Validate Required Form Fields.
691
		give_validate_required_form_fields( $form_id );
692
693
		// Verify data.
694
		if ( is_object( $user_data ) && $user_data->ID > 0 ) {
695
696
			// Collected logged in user data.
697
			$valid_user_data = array(
698
				'user_id'    => $user_id,
699
				'user_email' => ! empty( $post_data['give_email'] ) ? sanitize_email( $post_data['give_email'] ) : $user_data->user_email,
700
				'user_first' => ! empty( $post_data['give_first'] ) ? $post_data['give_first'] : $user_data->first_name,
701
				'user_last'  => ! empty( $post_data['give_last'] ) ? $post_data['give_last'] : $user_data->last_name,
702
			);
703
704
			// Validate essential form fields.
705
			give_donation_form_validate_name_fields( $post_data );
0 ignored issues
show
Bug introduced by
It seems like $post_data defined by give_clean($_POST) on line 673 can also be of type string; however, give_donation_form_validate_name_fields() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
706
707
			if ( ! is_email( $valid_user_data['user_email'] ) ) {
708
				give_set_error( 'email_invalid', esc_html__( 'Invalid email.', 'give' ) );
709
			}
710
		} else {
711
712
			// Set invalid user information error.
713
			give_set_error( 'invalid_user', esc_html__( 'The user information is invalid.', 'give' ) );
714
		}
715
	}
716
717
	// Return user data.
718
	return $valid_user_data;
719
}
720
721
/**
722
 * Donate Form Validate New User
723
 *
724
 * @access private
725
 * @since  1.0
726
 *
727
 * @return array
728
 */
729
function give_donation_form_validate_new_user() {
730
	// Default user data.
731
	$auto_generated_password = wp_generate_password();
732
	$default_user_data       = array(
733
		'give-form-id'           => '',
734
		'user_id'                => - 1, // Assume there will be errors.
735
		'user_first'             => '',
736
		'user_last'              => '',
737
		'give_user_login'        => false,
738
		'give_email'             => false,
739
		'give_user_pass'         => $auto_generated_password,
740
		'give_user_pass_confirm' => $auto_generated_password,
741
	);
742
743
	// Get data.
744
	$post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
745
	$user_data = wp_parse_args( $post_data, $default_user_data );
746
747
	$form_id = absint( $user_data['give-form-id'] );
748
	$nonce   = ! empty( $post_data['give-form-user-register-hash'] ) ? $post_data['give-form-user-register-hash'] : '';
749
750
	// Validate user creation nonce.
751
	if ( ! wp_verify_nonce( $nonce, "give_form_create_user_nonce_{$form_id}" ) ) {
752
		give_set_error( 'invalid_nonce', __( 'Nonce verification has failed.', 'give' ) );
753
	}
754
755
	$registering_new_user = false;
756
757
	give_donation_form_validate_name_fields( $user_data );
758
759
	// Start an empty array to collect valid user data.
760
	$valid_user_data = array(
761
762
		// Assume there will be errors.
763
		'user_id'    => - 1,
764
765
		// Get first name.
766
		'user_first' => $user_data['give_first'],
767
768
		// Get last name.
769
		'user_last'  => $user_data['give_last'],
770
771
		// Get Password.
772
		'user_pass'  => $user_data['give_user_pass'],
773
	);
774
775
	// Validate Required Form Fields.
776
	give_validate_required_form_fields( $form_id );
777
778
	// Set Email as Username.
779
	$valid_user_data['user_login'] = $user_data['give_email'];
780
781
	// Check if we have an email to verify.
782
	if ( give_validate_user_email( $user_data['give_email'], $registering_new_user ) ) {
783
		$valid_user_data['user_email'] = $user_data['give_email'];
784
	}
785
786
	return $valid_user_data;
787
}
788
789
/**
790
 * Donation Form Validate User Login
791
 *
792
 * @access private
793
 * @since  1.0
794
 *
795
 * @return array
796
 */
797
function give_donation_form_validate_user_login() {
798
799
	$post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
800
801
	// Start an array to collect valid user data.
802
	$valid_user_data = array(
803
804
		// Assume there will be errors.
805
		'user_id' => - 1,
806
	);
807
808
	// Bailout, if Username is empty.
809
	if ( empty( $post_data['give_user_login'] ) ) {
810
		give_set_error( 'must_log_in', __( 'You must register or login to complete your donation.', 'give' ) );
811
812
		return $valid_user_data;
813
	}
814
815
	// Get the user by login.
816
	$user_data = get_user_by( 'login', strip_tags( $post_data['give_user_login'] ) );
817
818
	// Check if user exists.
819
	if ( $user_data ) {
820
821
		// Get password.
822
		$user_pass = ! empty( $post_data['give_user_pass'] ) ? $post_data['give_user_pass'] : false;
823
824
		// Check user_pass.
825
		if ( $user_pass ) {
826
827
			// Check if password is valid.
828
			if ( ! wp_check_password( $user_pass, $user_data->user_pass, $user_data->ID ) ) {
829
830
				$current_page_url = site_url() . '/' . get_page_uri();
831
832
				// Incorrect password.
833
				give_set_error(
834
					'password_incorrect',
835
					sprintf(
836
						'%1$s <a href="%2$s">%3$s</a>',
837
						__( 'The password you entered is incorrect.', 'give' ),
838
						wp_lostpassword_url( $current_page_url ),
839
						__( 'Reset Password', 'give' )
840
					)
841
				);
842
843
			} else {
844
845
				// Repopulate the valid user data array.
846
				$valid_user_data = array(
847
					'user_id'    => $user_data->ID,
848
					'user_login' => $user_data->user_login,
849
					'user_email' => $user_data->user_email,
850
					'user_first' => $user_data->first_name,
851
					'user_last'  => $user_data->last_name,
852
					'user_pass'  => $user_pass,
853
				);
854
			}
855
		} else {
856
			// Empty password.
857
			give_set_error( 'password_empty', __( 'Enter a password.', 'give' ) );
858
		}
859
	} else {
860
		// No username.
861
		give_set_error( 'username_incorrect', __( 'The username you entered does not exist.', 'give' ) );
862
	} // End if().
863
864
	return $valid_user_data;
865
}
866
867
/**
868
 * Donation Form Validate Guest User
869
 *
870
 * @access private
871
 * @since  1.0
872
 *
873
 * @return array
874
 */
875
function give_donation_form_validate_guest_user() {
876
877
	$post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
878
	$form_id   = ! empty( $post_data['give-form-id'] ) ? $post_data['give-form-id'] : 0;
879
880
	// Start an array to collect valid user data.
881
	$valid_user_data = array(
882
		// Set a default id for guests.
883
		'user_id' => 0,
884
	);
885
886
	// Validate name fields.
887
	give_donation_form_validate_name_fields( $post_data );
0 ignored issues
show
Bug introduced by
It seems like $post_data defined by give_clean($_POST) on line 877 can also be of type string; however, give_donation_form_validate_name_fields() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
888
889
	// Validate Required Form Fields.
890
	give_validate_required_form_fields( $form_id );
891
892
	// Get the guest email.
893
	$guest_email = ! empty( $post_data['give_email'] ) ? $post_data['give_email'] : false;
894
895
	// Check email.
896
	if ( $guest_email && strlen( $guest_email ) > 0 ) {
897
898
		// Validate email.
899
		if ( ! is_email( $guest_email ) ) {
900
901
			// Invalid email.
902
			give_set_error( 'email_invalid', __( 'Invalid email.', 'give' ) );
903
904
		} else {
905
906
			// All is good to go.
907
			$valid_user_data['user_email'] = $guest_email;
908
909
			// Get user_id from donor if exist.
910
			$donor = new Give_Donor( $guest_email );
911
912
			if ( $donor->id && $donor->user_id ) {
913
				$valid_user_data['user_id'] = $donor->user_id;
914
			}
915
		}
916
	} else {
917
		// No email.
918
		give_set_error( 'email_empty', __( 'Enter an email.', 'give' ) );
919
	}
920
921
	return $valid_user_data;
922
}
923
924
/**
925
 * Register And Login New User
926
 *
927
 * @param array $user_data User Data.
928
 *
929
 * @access  private
930
 * @since   1.0
931
 *
932
 * @return  integer
933
 */
934
function give_register_and_login_new_user( $user_data = array() ) {
935
	// Verify the array.
936
	if ( empty( $user_data ) ) {
937
		return - 1;
938
	}
939
940
	if ( give_get_errors() ) {
941
		return - 1;
942
	}
943
944
	$user_args = apply_filters( 'give_insert_user_args', array(
945
		'user_login'      => isset( $user_data['user_login'] ) ? $user_data['user_login'] : '',
946
		'user_pass'       => isset( $user_data['user_pass'] ) ? $user_data['user_pass'] : '',
947
		'user_email'      => isset( $user_data['user_email'] ) ? $user_data['user_email'] : '',
948
		'first_name'      => isset( $user_data['user_first'] ) ? $user_data['user_first'] : '',
949
		'last_name'       => isset( $user_data['user_last'] ) ? $user_data['user_last'] : '',
950
		'user_registered' => date( 'Y-m-d H:i:s' ),
951
		'role'            => give_get_option( 'donor_default_user_role', 'give_donor' ),
952
	), $user_data );
953
954
	// Insert new user.
955
	$user_id = wp_insert_user( $user_args );
956
957
	// Validate inserted user.
958
	if ( is_wp_error( $user_id ) ) {
959
		return - 1;
960
	}
961
962
	// Allow themes and plugins to filter the user data.
963
	$user_data = apply_filters( 'give_insert_user_data', $user_data, $user_args );
964
965
	/**
966
	 * Fires after inserting user.
967
	 *
968
	 * @since 1.0
969
	 *
970
	 * @param int $user_id User id.
971
	 * @param array $user_data Array containing user data.
972
	 */
973
	do_action( 'give_insert_user', $user_id, $user_data );
974
975
	/**
976
	 * Filter allow user to alter if user when to login or not when user is register for the first time.
977
	 *
978
	 * @since 1.8.13
979
	 *
980
	 * return bool True if login with registration and False if only want to register.
981
	 */
982
	if ( true === (bool) apply_filters( 'give_log_user_in_on_register', true ) ) {
983
		// Login new user.
984
		give_log_user_in( $user_id, $user_data['user_login'], $user_data['user_pass'] );
985
	}
986
987
	// Return user id.
988
	return $user_id;
989
}
990
991
/**
992
 * Get Donation Form User
993
 *
994
 * @param array $valid_data Valid Data.
995
 *
996
 * @access  private
997
 * @since   1.0
998
 *
999
 * @return  array|bool
1000
 */
1001
function give_get_donation_form_user( $valid_data = array() ) {
1002
1003
	// Initialize user.
1004
	$user      = false;
1005
	$is_ajax   = defined( 'DOING_AJAX' ) && DOING_AJAX;
1006
	$post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
1007
1008
	if ( $is_ajax ) {
1009
1010
		// Do not create or login the user during the ajax submission (check for errors only).
1011
		return true;
1012
	} elseif ( is_user_logged_in() ) {
1013
1014
		// Set the valid user as the logged in collected data.
1015
		$user = $valid_data['logged_in_user'];
1016
	} elseif ( true === $valid_data['need_new_user'] || true === $valid_data['need_user_login'] ) {
1017
1018
		// New user registration.
1019
		if ( true === $valid_data['need_new_user'] ) {
1020
1021
			// Set user.
1022
			$user = $valid_data['new_user_data'];
1023
1024
			// Register and login new user.
1025
			$user['user_id'] = give_register_and_login_new_user( $user );
1026
1027
		} elseif ( true === $valid_data['need_user_login'] && ! $is_ajax ) {
1028
1029
			/**
1030
			 * The login form is now processed in the give_process_donation_login() function.
1031
			 * This is still here for backwards compatibility.
1032
			 * This also allows the old login process to still work if a user removes the checkout login submit button.
1033
			 *
1034
			 * This also ensures that the donor is logged in correctly if they click "Donation" instead of submitting the login form, meaning the donor is logged in during the donation process.
1035
			 */
1036
			$user = $valid_data['login_user_data'];
1037
1038
			// Login user.
1039
			give_log_user_in( $user['user_id'], $user['user_login'], $user['user_pass'] );
1040
		}
1041
	} // End if().
1042
1043
	// Check guest checkout.
1044
	if ( false === $user && false === give_logged_in_only( $post_data['give-form-id'] ) ) {
1045
1046
		// Set user.
1047
		$user = $valid_data['guest_user_data'];
1048
	}
1049
1050
	// Verify we have an user.
1051
	if ( false === $user || empty( $user ) ) {
1052
		return false;
1053
	}
1054
1055
	// Get user first name.
1056 View Code Duplication
	if ( ! isset( $user['user_first'] ) || strlen( trim( $user['user_first'] ) ) < 1 ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1057
		$user['user_first'] = isset( $post_data['give_first'] ) ? strip_tags( trim( $post_data['give_first'] ) ) : '';
1058
	}
1059
1060
	// Get user last name.
1061 View Code Duplication
	if ( ! isset( $user['user_last'] ) || strlen( trim( $user['user_last'] ) ) < 1 ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1062
		$user['user_last'] = isset( $post_data['give_last'] ) ? strip_tags( trim( $post_data['give_last'] ) ) : '';
1063
	}
1064
1065
	// Add Title Prefix to user information.
1066 View Code Duplication
	if ( empty( $user['user_title'] ) || strlen( trim( $user['user_title'] ) ) < 1 ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1067
		$user['user_title'] = ! empty( $post_data['give_title'] ) ? strip_tags( trim( $post_data['give_title'] ) ) : '';
1068
	}
1069
1070
	// Get the user's billing address details.
1071
	$user['address']            = array();
1072
	$user['address']['line1']   = ! empty( $post_data['card_address'] ) ? $post_data['card_address'] : false;
1073
	$user['address']['line2']   = ! empty( $post_data['card_address_2'] ) ? $post_data['card_address_2'] : false;
1074
	$user['address']['city']    = ! empty( $post_data['card_city'] ) ? $post_data['card_city'] : false;
1075
	$user['address']['state']   = ! empty( $post_data['card_state'] ) ? $post_data['card_state'] : false;
1076
	$user['address']['zip']     = ! empty( $post_data['card_zip'] ) ? $post_data['card_zip'] : false;
1077
	$user['address']['country'] = ! empty( $post_data['billing_country'] ) ? $post_data['billing_country'] : false;
1078
1079
	if ( empty( $user['address']['country'] ) ) {
1080
		$user['address'] = false;
1081
	} // End if().
1082
1083
	// Return valid user.
1084
	return $user;
1085
}
1086
1087
/**
1088
 * Validates the credit card info.
1089
 *
1090
 * @access  private
1091
 * @since   1.0
1092
 *
1093
 * @return  array
1094
 */
1095
function give_donation_form_validate_cc() {
1096
1097
	$card_data = give_get_donation_cc_info();
1098
1099
	// Validate the card zip.
1100
	if ( ! empty( $card_data['card_zip'] ) ) {
1101
		if ( ! give_donation_form_validate_cc_zip( $card_data['card_zip'], $card_data['card_country'] ) ) {
1102
			give_set_error( 'invalid_cc_zip', __( 'The zip / postal code you entered for your billing address is invalid.', 'give' ) );
1103
		}
1104
	}
1105
1106
	// Ensure no spaces.
1107
	if ( ! empty( $card_data['card_number'] ) ) {
1108
		$card_data['card_number'] = str_replace( '+', '', $card_data['card_number'] ); // no "+" signs.
1109
		$card_data['card_number'] = str_replace( ' ', '', $card_data['card_number'] ); // No spaces.
1110
	}
1111
1112
	// This should validate card numbers at some point too.
1113
	return $card_data;
1114
}
1115
1116
/**
1117
 * Get credit card info.
1118
 *
1119
 * @access private
1120
 * @since  1.0
1121
 *
1122
 * @return array
1123
 */
1124
function give_get_donation_cc_info() {
1125
1126
	// Sanitize the values submitted with donation form.
1127
	$post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
1128
1129
	$cc_info                   = array();
1130
	$cc_info['card_name']      = ! empty( $post_data['card_name'] ) ? $post_data['card_name'] : '';
1131
	$cc_info['card_number']    = ! empty( $post_data['card_number'] ) ? $post_data['card_number'] : '';
1132
	$cc_info['card_cvc']       = ! empty( $post_data['card_cvc'] ) ? $post_data['card_cvc'] : '';
1133
	$cc_info['card_exp_month'] = ! empty( $post_data['card_exp_month'] ) ? $post_data['card_exp_month'] : '';
1134
	$cc_info['card_exp_year']  = ! empty( $post_data['card_exp_year'] ) ? $post_data['card_exp_year'] : '';
1135
	$cc_info['card_address']   = ! empty( $post_data['card_address'] ) ? $post_data['card_address'] : '';
1136
	$cc_info['card_address_2'] = ! empty( $post_data['card_address_2'] ) ? $post_data['card_address_2'] : '';
1137
	$cc_info['card_city']      = ! empty( $post_data['card_city'] ) ? $post_data['card_city'] : '';
1138
	$cc_info['card_state']     = ! empty( $post_data['card_state'] ) ? $post_data['card_state'] : '';
1139
	$cc_info['card_country']   = ! empty( $post_data['billing_country'] ) ? $post_data['billing_country'] : '';
1140
	$cc_info['card_zip']       = ! empty( $post_data['card_zip'] ) ? $post_data['card_zip'] : '';
1141
1142
	// Return cc info.
1143
	return $cc_info;
1144
}
1145
1146
/**
1147
 * Validate zip code based on country code
1148
 *
1149
 * @since  1.0
1150
 *
1151
 * @param int    $zip          ZIP Code.
1152
 * @param string $country_code Country Code.
1153
 *
1154
 * @return bool|mixed
1155
 */
1156
function give_donation_form_validate_cc_zip( $zip = 0, $country_code = '' ) {
1157
	$ret = false;
1158
1159
	if ( empty( $zip ) || empty( $country_code ) ) {
1160
		return $ret;
1161
	}
1162
1163
	$country_code = strtoupper( $country_code );
1164
1165
	$zip_regex = array(
1166
		'AD' => 'AD\d{3}',
1167
		'AM' => '(37)?\d{4}',
1168
		'AR' => '^([A-Z]{1}\d{4}[A-Z]{3}|[A-Z]{1}\d{4}|\d{4})$',
1169
		'AS' => '96799',
1170
		'AT' => '\d{4}',
1171
		'AU' => '^(0[289][0-9]{2})|([1345689][0-9]{3})|(2[0-8][0-9]{2})|(290[0-9])|(291[0-4])|(7[0-4][0-9]{2})|(7[8-9][0-9]{2})$',
1172
		'AX' => '22\d{3}',
1173
		'AZ' => '\d{4}',
1174
		'BA' => '\d{5}',
1175
		'BB' => '(BB\d{5})?',
1176
		'BD' => '\d{4}',
1177
		'BE' => '^[1-9]{1}[0-9]{3}$',
1178
		'BG' => '\d{4}',
1179
		'BH' => '((1[0-2]|[2-9])\d{2})?',
1180
		'BM' => '[A-Z]{2}[ ]?[A-Z0-9]{2}',
1181
		'BN' => '[A-Z]{2}[ ]?\d{4}',
1182
		'BR' => '\d{5}[\-]?\d{3}',
1183
		'BY' => '\d{6}',
1184
		'CA' => '^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$',
1185
		'CC' => '6799',
1186
		'CH' => '^[1-9][0-9][0-9][0-9]$',
1187
		'CK' => '\d{4}',
1188
		'CL' => '\d{7}',
1189
		'CN' => '\d{6}',
1190
		'CR' => '\d{4,5}|\d{3}-\d{4}',
1191
		'CS' => '\d{5}',
1192
		'CV' => '\d{4}',
1193
		'CX' => '6798',
1194
		'CY' => '\d{4}',
1195
		'CZ' => '\d{3}[ ]?\d{2}',
1196
		'DE' => '\b((?:0[1-46-9]\d{3})|(?:[1-357-9]\d{4})|(?:[4][0-24-9]\d{3})|(?:[6][013-9]\d{3}))\b',
1197
		'DK' => '^([D-d][K-k])?( |-)?[1-9]{1}[0-9]{3}$',
1198
		'DO' => '\d{5}',
1199
		'DZ' => '\d{5}',
1200
		'EC' => '([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?',
1201
		'EE' => '\d{5}',
1202
		'EG' => '\d{5}',
1203
		'ES' => '^([1-9]{2}|[0-9][1-9]|[1-9][0-9])[0-9]{3}$',
1204
		'ET' => '\d{4}',
1205
		'FI' => '\d{5}',
1206
		'FK' => 'FIQQ 1ZZ',
1207
		'FM' => '(9694[1-4])([ \-]\d{4})?',
1208
		'FO' => '\d{3}',
1209
		'FR' => '^(F-)?((2[A|B])|[0-9]{2})[0-9]{3}$',
1210
		'GE' => '\d{4}',
1211
		'GF' => '9[78]3\d{2}',
1212
		'GL' => '39\d{2}',
1213
		'GN' => '\d{3}',
1214
		'GP' => '9[78][01]\d{2}',
1215
		'GR' => '\d{3}[ ]?\d{2}',
1216
		'GS' => 'SIQQ 1ZZ',
1217
		'GT' => '\d{5}',
1218
		'GU' => '969[123]\d([ \-]\d{4})?',
1219
		'GW' => '\d{4}',
1220
		'HM' => '\d{4}',
1221
		'HN' => '(?:\d{5})?',
1222
		'HR' => '\d{5}',
1223
		'HT' => '\d{4}',
1224
		'HU' => '\d{4}',
1225
		'ID' => '\d{5}',
1226
		'IE' => '((D|DUBLIN)?([1-9]|6[wW]|1[0-8]|2[024]))?',
1227
		'IL' => '\d{5}',
1228
		'IN' => '^[1-9][0-9][0-9][0-9][0-9][0-9]$', // India.
1229
		'IO' => 'BBND 1ZZ',
1230
		'IQ' => '\d{5}',
1231
		'IS' => '\d{3}',
1232
		'IT' => '^(V-|I-)?[0-9]{5}$',
1233
		'JO' => '\d{5}',
1234
		'JP' => '\d{3}-\d{4}',
1235
		'KE' => '\d{5}',
1236
		'KG' => '\d{6}',
1237
		'KH' => '\d{5}',
1238
		'KR' => '\d{3}[\-]\d{3}',
1239
		'KW' => '\d{5}',
1240
		'KZ' => '\d{6}',
1241
		'LA' => '\d{5}',
1242
		'LB' => '(\d{4}([ ]?\d{4})?)?',
1243
		'LI' => '(948[5-9])|(949[0-7])',
1244
		'LK' => '\d{5}',
1245
		'LR' => '\d{4}',
1246
		'LS' => '\d{3}',
1247
		'LT' => '\d{5}',
1248
		'LU' => '\d{4}',
1249
		'LV' => '\d{4}',
1250
		'MA' => '\d{5}',
1251
		'MC' => '980\d{2}',
1252
		'MD' => '\d{4}',
1253
		'ME' => '8\d{4}',
1254
		'MG' => '\d{3}',
1255
		'MH' => '969[67]\d([ \-]\d{4})?',
1256
		'MK' => '\d{4}',
1257
		'MN' => '\d{6}',
1258
		'MP' => '9695[012]([ \-]\d{4})?',
1259
		'MQ' => '9[78]2\d{2}',
1260
		'MT' => '[A-Z]{3}[ ]?\d{2,4}',
1261
		'MU' => '(\d{3}[A-Z]{2}\d{3})?',
1262
		'MV' => '\d{5}',
1263
		'MX' => '\d{5}',
1264
		'MY' => '\d{5}',
1265
		'NC' => '988\d{2}',
1266
		'NE' => '\d{4}',
1267
		'NF' => '2899',
1268
		'NG' => '(\d{6})?',
1269
		'NI' => '((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?',
1270
		'NL' => '^[1-9][0-9]{3}\s?([a-zA-Z]{2})?$',
1271
		'NO' => '\d{4}',
1272
		'NP' => '\d{5}',
1273
		'NZ' => '\d{4}',
1274
		'OM' => '(PC )?\d{3}',
1275
		'PF' => '987\d{2}',
1276
		'PG' => '\d{3}',
1277
		'PH' => '\d{4}',
1278
		'PK' => '\d{5}',
1279
		'PL' => '\d{2}-\d{3}',
1280
		'PM' => '9[78]5\d{2}',
1281
		'PN' => 'PCRN 1ZZ',
1282
		'PR' => '00[679]\d{2}([ \-]\d{4})?',
1283
		'PT' => '\d{4}([\-]\d{3})?',
1284
		'PW' => '96940',
1285
		'PY' => '\d{4}',
1286
		'RE' => '9[78]4\d{2}',
1287
		'RO' => '\d{6}',
1288
		'RS' => '\d{5}',
1289
		'RU' => '\d{6}',
1290
		'SA' => '\d{5}',
1291
		'SE' => '^(s-|S-){0,1}[0-9]{3}\s?[0-9]{2}$',
1292
		'SG' => '\d{6}',
1293
		'SH' => '(ASCN|STHL) 1ZZ',
1294
		'SI' => '\d{4}',
1295
		'SJ' => '\d{4}',
1296
		'SK' => '\d{3}[ ]?\d{2}',
1297
		'SM' => '4789\d',
1298
		'SN' => '\d{5}',
1299
		'SO' => '\d{5}',
1300
		'SZ' => '[HLMS]\d{3}',
1301
		'TC' => 'TKCA 1ZZ',
1302
		'TH' => '\d{5}',
1303
		'TJ' => '\d{6}',
1304
		'TM' => '\d{6}',
1305
		'TN' => '\d{4}',
1306
		'TR' => '\d{5}',
1307
		'TW' => '\d{3}(\d{2})?',
1308
		'UA' => '\d{5}',
1309
		'UK' => '^(GIR|[A-Z]\d[A-Z\d]??|[A-Z]{2}\d[A-Z\d]??)[ ]??(\d[A-Z]{2})$',
1310
		'US' => '^\d{5}([\-]?\d{4})?$',
1311
		'UY' => '\d{5}',
1312
		'UZ' => '\d{6}',
1313
		'VA' => '00120',
1314
		'VE' => '\d{4}',
1315
		'VI' => '008(([0-4]\d)|(5[01]))([ \-]\d{4})?',
1316
		'WF' => '986\d{2}',
1317
		'YT' => '976\d{2}',
1318
		'YU' => '\d{5}',
1319
		'ZA' => '\d{4}',
1320
		'ZM' => '\d{5}',
1321
	);
1322
1323
	if ( ! isset( $zip_regex[ $country_code ] ) || preg_match( '/' . $zip_regex[ $country_code ] . '/i', $zip ) ) {
1324
		$ret = true;
1325
	}
1326
1327
	return apply_filters( 'give_is_zip_valid', $ret, $zip, $country_code );
1328
}
1329
1330
/**
1331
 * Validate donation amount and auto set correct donation level id on basis of amount.
1332
 *
1333
 * Note: If amount does not match to donation level amount then level id will be auto select to first match level id on basis of amount.
1334
 *
1335
 * @param array $valid_data List of Valid Data.
1336
 *
1337
 * @return bool
1338
 */
1339
function give_validate_donation_amount( $valid_data ) {
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...
1340
1341
	$post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
1342
1343
	/* @var Give_Donate_Form $form */
1344
	$form = new Give_Donate_Form( $post_data['give-form-id'] );
1345
1346
	// Get the form currency.
1347
	$form_currency = give_get_currency( $post_data['give-form-id'] );
1348
1349
	$donation_level_matched = false;
1350
1351
	if ( $form->is_set_type_donation_form() ) {
1352
1353
		// Sanitize donation amount.
1354
		$post_data['give-amount'] = give_maybe_sanitize_amount( $post_data['give-amount'], array( 'currency' => $form_currency ) );
1355
1356
		// Backward compatibility.
1357
		if ( $form->is_custom_price( $post_data['give-amount'] ) ) {
1358
			$post_data['give-price-id'] = 'custom';
1359
		}
1360
1361
		$donation_level_matched = true;
1362
1363
	} elseif ( $form->is_multi_type_donation_form() ) {
1364
1365
		$variable_prices = $form->get_prices();
1366
1367
		// Bailout.
1368
		if ( ! $variable_prices ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $variable_prices of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1369
			return false;
1370
		}
1371
1372
		// Sanitize donation amount.
1373
		$post_data['give-amount']     = give_maybe_sanitize_amount( $post_data['give-amount'], array( 'currency' => $form_currency ) );
1374
		$variable_price_option_amount = give_maybe_sanitize_amount( give_get_price_option_amount( $post_data['give-form-id'], $post_data['give-price-id'] ), array( 'currency' => $form_currency ) );
1375
		$new_price_id                 = '';
1376
1377
		if ( $post_data['give-amount'] === $variable_price_option_amount ) {
1378
			return true;
1379
		}
1380
1381
		if ( $form->is_custom_price( $post_data['give-amount'] ) ) {
1382
			$new_price_id = 'custom';
1383
		} else {
1384
1385
			// Find correct donation level from all donation levels.
1386
			foreach ( $variable_prices as $variable_price ) {
1387
1388
				// Sanitize level amount.
1389
				$variable_price['_give_amount'] = give_maybe_sanitize_amount( $variable_price['_give_amount'] );
1390
1391
				// Set first match donation level ID.
1392
				if ( $post_data['give-amount'] === $variable_price['_give_amount'] ) {
1393
					$new_price_id = $variable_price['_give_id']['level_id'];
1394
					break;
1395
				}
1396
			}
1397
		}
1398
1399
		// If donation amount is not find in donation levels then check if form has custom donation feature enable or not.
1400
		// If yes then set price id to custom if amount is greater then custom minimum amount (if any).
1401
		if ( $post_data['give-price-id'] === $new_price_id ) {
1402
			$donation_level_matched = true;
1403
		}
1404
	} // End if().
1405
1406
	if ( ! $donation_level_matched ) {
1407
		give_set_error(
1408
			'invalid_donation_amount',
1409
			sprintf(
1410
			/* translators: %s: invalid donation amount */
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 16 spaces, but found 12.
Loading history...
1411
				__( 'Donation amount %s is invalid.', 'give' ),
1412
				give_currency_filter(
1413
					give_format_amount( $post_data['give-amount'], array( 'sanitize' => false, ) )
1414
				)
1415
			)
1416
		);
1417
	}
1418
}
1419
1420
add_action( 'give_checkout_error_checks', 'give_validate_donation_amount', 10, 1 );
1421
1422
/**
1423
 * Validate Required Form Fields.
1424
 *
1425
 * @param int $form_id Form ID.
1426
 *
1427
 * @since 2.0
1428
 */
1429
function give_validate_required_form_fields( $form_id ) {
1430
1431
	// Sanitize values submitted with donation form.
1432
	$post_data = give_clean( $_POST ); // WPCS: input var ok, sanitization ok, CSRF ok.
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
1433
1434
	// Loop through required fields and show error messages.
1435
	foreach ( give_get_required_fields( $form_id ) as $field_name => $value ) {
1436
1437
		// Clean Up Data of the input fields.
1438
		$field_value = $post_data[ $field_name ];
1439
1440
		// Check whether the required field is empty, then show the error message.
1441
		if ( in_array( $value, give_get_required_fields( $form_id ), true ) && empty( $field_value ) ) {
1442
			give_set_error( $value['error_id'], $value['error_message'] );
1443
		}
1444
	}
1445
}
1446
1447
/**
1448
 * Validates and checks if name fields are valid or not.
1449
 *
1450
 * @param array $post_data List of post data.
1451
 *
1452
 * @since 2.1
1453
 *
1454
 * @return void
1455
 */
1456
function give_donation_form_validate_name_fields( $post_data ) {
1457
1458
	$is_alpha_first_name = ( ! is_email( $post_data['give_first'] ) && ! preg_match( '~[0-9]~', $post_data['give_first'] ) );
1459
	$is_alpha_last_name  = ( ! is_email( $post_data['give_last'] ) && ! preg_match( '~[0-9]~', $post_data['give_last'] ) );
1460
1461
	if ( ! $is_alpha_first_name || ( ! empty( $post_data['give_last'] ) && ! $is_alpha_last_name ) ) {
1462
		give_set_error( 'invalid_name', esc_html__( 'The First Name and Last Name fields cannot contain an email address or numbers.', 'give' ) );
1463
	}
1464
}
1465