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