Test Failed
Pull Request — master (#2054)
by Devin
05:04
created

user-functions.php ➔ give_validate_user_email()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 36
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 14
nc 5
nop 2
dl 0
loc 36
rs 6.7272
c 0
b 0
f 0
ccs 0
cts 19
cp 0
crap 56
1
<?php
2
/**
3
 * User Functions
4
 *
5
 * Functions related to users / donors
6
 *
7
 * @package     Give
8
 * @subpackage  Functions
9
 * @copyright   Copyright (c) 2016, WordImpress
10
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
11
 * @since       1.0
12
 */
13
14
// Exit if accessed directly.
15
if ( ! defined( 'ABSPATH' ) ) {
16
	exit;
17
}
18
19
/**
20
 * Get Users Donations
21
 *
22
 * Retrieves a list of all donations by a specific user.
23
 *
24
 * @since  1.0
25
 *
26
 * @param int    $user   User ID or email address.
27
 * @param int    $number Number of donations to retrieve.
28
 * @param bool   $pagination
29
 * @param string $status
30
 *
31
 * @return bool|array List of all user donations.
32
 */
33
function give_get_users_donations( $user = 0, $number = 20, $pagination = false, $status = 'complete' ) {
34
35 1
	if ( empty( $user ) ) {
36 1
		$user = get_current_user_id();
37 1
	}
38
39 1
	if ( 0 === $user && ! Give()->email_access->token_exists ) {
40 1
		return false;
41
	}
42
43 1
	$status = $status === 'complete' ? 'publish' : $status;
44
	$paged = 1;
45 1
46
	if ( $pagination ) {
47
		if ( get_query_var( 'paged' ) ) {
48
			$paged = get_query_var( 'paged' );
49
		} elseif ( get_query_var( 'page' ) ) {
50
			$paged = get_query_var( 'page' );
51
		}
52
	}
53
54
	$args = apply_filters( 'give_get_users_donations_args', array(
55 1
		'user'    => $user,
56 1
		'number'  => $number,
57 1
		'status'  => $status,
58 1
		'orderby' => 'date',
59
	) );
60 1
61
	if ( $pagination ) {
62 1
		$args['page'] = $paged;
63
	} else {
64
		$args['nopaging'] = true;
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set nopaging to true ever.
Loading history...
65
	}
66
67
	$by_user_id = is_numeric( $user ) ? true : false;
68 1
	$donor   = new Give_Donor( $user, $by_user_id );
69
70
	if ( ! empty( $donor->payment_ids ) ) {
71
72 1
		unset( $args['user'] );
73 1
		$args['post__in'] = array_map( 'absint', explode( ',', $donor->payment_ids ) );
74
75 1
	}
76
77 1
	$donations = give_get_payments( apply_filters( 'give_get_users_donations_args', $args ) );
78 1
79
	// No donations
80 1
	if ( ! $donations ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $donations 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...
81
		return false;
82 1
	}
83
84
	return $donations;
85 1
}
86
87
/**
88
 * Get Users Donations
89 1
 *
90
 * Returns a list of unique donation forms given to by a specific user.
91
 *
92
 * @since  1.0
93
 *
94
 * @param int    $user User ID or email address
95
 * @param string $status
96
 *
97
 * @return bool|object List of unique forms donated by user
98
 */
99
function give_get_users_completed_donations( $user = 0, $status = 'complete' ) {
0 ignored issues
show
Unused Code introduced by
The parameter $status 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...
100
	if ( empty( $user ) ) {
101
		$user = get_current_user_id();
102
	}
103
104
	if ( empty( $user ) ) {
105 1
		return false;
106
	}
107
108
	$by_user_id = is_numeric( $user ) ? true : false;
109 1
110
	$donor = new Give_Donor( $user, $by_user_id );
111
112
	if ( empty( $donor->payment_ids ) ) {
113 1
		return false;
114
	}
115 1
116
	// Get all the items donated.
117 1
	$payment_ids    = array_reverse( explode( ',', $donor->payment_ids ) );
118
	$limit_payments = apply_filters( 'give_users_completed_donations_payments', 50 );
119
	if ( ! empty( $limit_payments ) ) {
120
		$payment_ids = array_slice( $payment_ids, 0, $limit_payments );
121
	}
122 1
	$donation_data = array();
123 1
	foreach ( $payment_ids as $payment_id ) {
124 1
		$donation_data[] = give_get_payment_meta( $payment_id );
125 1
	}
126 1
127 1
	if ( empty( $donation_data ) ) {
128 1
		return false;
129 1
	}
130 1
131
	// Grab only the post ids "form_id" of the forms donated on this order
132 1
	$completed_donations_ids = array();
133
	foreach ( $donation_data as $donation_meta ) {
134
		$completed_donations_ids[] = isset( $donation_meta['form_id'] ) ? $donation_meta['form_id'] : '';
135
	}
136
137 32
	if ( empty( $completed_donations_ids ) ) {
138 1
		return false;
139 1
	}
140 1
141
	// Only include each donation once
142 1
	$form_ids = array_unique( $completed_donations_ids );
143
144
	// Make sure we still have some products and a first item
145
	if ( empty( $form_ids ) || ! isset( $form_ids[0] ) ) {
146
		return false;
147 1
	}
148
149
	$post_type = get_post_type( $form_ids[0] );
150 1
151
	$args = apply_filters( 'give_get_users_completed_donations_args', array(
152
		'include'        => $form_ids,
153
		'post_type'      => $post_type,
154 1
		'posts_per_page' => - 1,
155
	) );
156 1
157 1
	return apply_filters( 'give_users_completed_donations_list', get_posts( $args ) );
158 1
}
159
160 1
161
/**
162 1
 * Has donations
163
 *
164
 * Checks to see if a user has donated to at least one form.
165
 *
166
 * @access      public
167
 * @since       1.0
168
 *
169
 * @param       int $user_id The ID of the user to check.
170
 *
171
 * @return      bool True if has donated, false other wise.
172
 */
173
function give_has_donations( $user_id = null ) {
174
	if ( empty( $user_id ) ) {
175
		$user_id = get_current_user_id();
176
	}
177
178
	if ( give_get_users_donations( $user_id, 1 ) ) {
179 1
		return true; // User has at least one donation.
180
	}
181
182
	// User has never donated anything.
183 1
	return false;
184 1
}
185
186
187
/**
188
 * Get Donation Status for User.
189
 *
190
 * Retrieves the donation count and the total amount spent for a specific user.
191
 *
192
 * @access      public
193
 * @since       1.0
194
 *
195
 * @param       int|string $user The ID or email of the donor to retrieve stats for.
196
 *
197
 * @return      array
198
 */
199
function give_get_donation_stats_by_user( $user = '' ) {
200
201
	$field = '';
202
203
	if ( is_email( $user ) ) {
204
		$field = 'email';
205 5
	} elseif ( is_numeric( $user ) ) {
206
		$field = 'user_id';
207
	}
208
209 5
	$stats    = array();
210
	$donor = Give()->donors->get_donor_by( $field, $user );
211 5
212
	if ( $donor ) {
213 5
		$donor = new Give_Donor( $donor->id );
214
		$stats['purchases']   = absint( $donor->purchase_count );
215 5
		$stats['total_spent'] = give_maybe_sanitize_amount( $donor->purchase_value );
216 5
	}
217
218 5
	/**
219
	 * Filter the donation stats.
220 5
	 *
221
	 * @since 1.7
222 5
	 */
223 5
	$stats = (array) apply_filters( 'give_donation_stats_by_user', $stats, $user );
224
225 5
	return $stats;
226
}
227
228 5
229
/**
230
 * Count number of donations of a donor.
231
 *
232
 * Returns total number of donations a donor has made.
233
 *
234
 * @access      public
235
 * @since       1.0
236
 *
237
 * @param       int|string $user The ID or email of the donor.
238
 *
239
 * @return      int The total number of donations.
240
 */
241
function give_count_donations_of_donor( $user = null ) {
242
243
	// Logged in?
244
	if ( empty( $user ) ) {
245
		$user = get_current_user_id();
246
	}
247 3
248 1
	// Email access?
249 1
	if ( empty( $user ) && Give()->email_access->token_email ) {
250
		$user = Give()->email_access->token_email;
251
	}
252 3
253
	$stats = ! empty( $user ) ? give_get_donation_stats_by_user( $user ) : false;
254
255
	return isset( $stats['purchases'] ) ? $stats['purchases'] : 0;
256
}
257 3
258
/**
259 3
 * Calculates the total amount spent by a user.
260
 *
261
 * @access      public
262
 * @since       1.0
263
 *
264
 * @param       int|string $user The ID or email of the donor.
265
 *
266
 * @return      float The total amount the user has spent
267
 */
268
function give_donation_total_of_user( $user = null ) {
269
270
	$stats = give_get_donation_stats_by_user( $user );
271
272
	return $stats['total_spent'];
273
}
274 3
275
276 3
/**
277
 * Validate a potential username.
278
 *
279
 * @since 1.0
280
 *
281
 * @param string $username The username to validate.
282
 * @param int    $form_id
283
 *
284
 * @return bool
285
 */
286
function give_validate_username( $username, $form_id = 0 ) {
287
	$valid = true;
288
289
	// Validate username.
290
	if ( ! empty( $username ) ) {
291 1
292 1
		// Sanitize username.
293
		$sanitized_user_name = sanitize_user( $username, false );
294 1
295
		// We have an user name, check if it already exists.
296
		if ( username_exists( $username ) ) {
297
			// Username already registered.
298
			give_set_error( 'username_unavailable', __( 'Username already taken.', 'give' ) );
299
			$valid = false;
300
301
			// Check if it's valid.
302
		} elseif ( $sanitized_user_name !== $username ) {
303
			// Invalid username.
304
			if ( is_multisite() ) {
305
				give_set_error( 'username_invalid', __( 'Invalid username. Only lowercase letters (a-z) and numbers are allowed.', 'give' ) );
306
				$valid = false;
307
			} else {
308
				give_set_error( 'username_invalid', __( 'Invalid username.', 'give' ) );
309
				$valid = false;
310
			}
311
		}
312
	} else {
313 32
		// Username is empty.
314
		give_set_error( 'username_empty', __( 'Enter a username.', 'give' ) );
315 32
		$valid = false;
316
317 32
		// Check if guest checkout is disable for form.
318
		if ( $form_id && give_logged_in_only( $form_id ) ) {
319
			give_set_error( 'registration_required', __( 'You must register or login to complete your donation.', 'give' ) );
320
			$valid = false;
321
		}
322
	}
323
324
	/**
325
	 * Filter the username validation result.
326
	 *
327
	 * @since 1.8
328
	 *
329
	 * @param bool   $valid
330
	 * @param string $username
331
	 * @param bool   $form_id
332
	 */
333
	$valid = (bool) apply_filters( 'give_validate_username', $valid, $username, $form_id );
334 32
335
	return $valid;
336
}
337
338
339
/**
340
 * Validate user email.
341
 *
342
 * @since 1.8
343
 *
344
 * @param string $email                User email.
345
 * @param bool   $registering_new_user Flag to check user register or not.
346
 *
347
 * @return bool
348
 */
349
function give_validate_user_email( $email, $registering_new_user = false ) {
350
	$valid = true;
351
352
	if ( empty( $email ) ) {
353
		// No email.
354
		give_set_error( 'email_empty', __( 'Enter an email.', 'give' ) );
355
		$valid = false;
356
357
	} elseif ( ! is_email( $email ) ) {
358
		// Validate email.
359
		give_set_error( 'email_invalid', __( 'Invalid email.', 'give' ) );
360
		$valid = false;
361
362
	} elseif ( $registering_new_user ) {
363
364
		// If donor email is not primary
365
		if ( ! email_exists( $email ) && give_donor_email_exists( $email ) && give_is_additional_email( $email ) ) {
366
			// Check if email exists.
367
			give_set_error( 'email_used', __( 'The email address provided is already active for another user.', 'give' ) );
368
			$valid = false;
369
		}
370
	}
371
372
	/**
373
	 * Filter the email validation result.
374
	 *
375
	 * @since 1.8
376
	 *
377
	 * @param bool   $valid
378
	 * @param string $email
379
	 * @param bool   $registering_new_user
380
	 */
381
	$valid = (bool) apply_filters( 'give_validate_user_email', $valid, $email, $registering_new_user );
382
383
	return $valid;
384
}
385
386
/**
387
 * Validate password.
388
 *
389
 * @since 1.8
390
 *
391
 * @param string $password
392
 * @param string $confirm_password
393
 * @param bool   $registering_new_user
394
 *
395
 * @return bool
396
 */
397
function give_validate_user_password( $password = '', $confirm_password = '', $registering_new_user = false ) {
398
	$valid = true;
399
400
	// Passwords Validation For New Donors Only
401
	if ( $registering_new_user ) {
402
		// Password or confirmation missing.
403
		if ( ! $password ) {
404
			// The password is invalid.
405
			give_set_error( 'password_empty', __( 'Enter a password.', 'give' ) );
406
			$valid = false;
407
		} elseif ( ! $confirm_password ) {
408
			// Confirmation password is invalid.
409
			give_set_error( 'confirmation_empty', __( 'Enter the password confirmation.', 'give' ) );
410
			$valid = false;
411
		}
412
	}
413
	// Passwords Validation For New Donors as well as Existing Donors
414
	if ( $password || $confirm_password ) {
415
		if ( strlen( $password ) < 6 || strlen( $confirm_password ) < 6 ) {
416
			// Seems Weak Password
417
			give_set_error( 'password_weak', __( 'Passwords should have at least 6 characters.', 'give' ) );
418
			$valid = false;
419
		}
420
		if ( $password && $confirm_password ) {
421
			// Verify confirmation matches.
422
			if ( $password != $confirm_password ) {
423
				// Passwords do not match
424
				give_set_error( 'password_mismatch', __( 'Passwords you entered do not match. Please try again.', 'give' ) );
425
				$valid = false;
426
			}
427
		}
428
	}
429
430
	/**
431
	 * Filter the password validation result.
432
	 *
433
	 * @since 1.8
434
	 *
435
	 * @param bool   $valid
436
	 * @param string $password
437
	 * @param string $confirm_password
438
	 * @param bool   $registering_new_user
439
	 */
440
	$valid = (bool) apply_filters( 'give_validate_user_email', $valid, $password, $confirm_password, $registering_new_user );
441
442
	return $valid;
443
}
444
445
446
/**
447
 * Looks up donations by email that match the registering user.
448
 *
449
 * This is for users that donated as a guest and then came back and created an account.
450
 *
451
 * @access      public
452
 * @since       1.0
453
 *
454
 * @param       int $user_id The new user's ID.
455
 *
456
 * @return      void
457
 */
458
function give_add_past_donations_to_new_user( $user_id ) {
459
460
	$email = get_the_author_meta( 'user_email', $user_id );
461
462
	$payments = give_get_payments( array(
463
		's' => $email,
464
	) );
465
466
	if ( $payments ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $payments 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...
467
		foreach ( $payments as $payment ) {
468
			/* @var $payment \Give_Payment */
469
470
			if ( intval( give_get_payment_user_id( $payment->ID ) ) > 0 ) {
471
				continue;
472
			}
473
474
			$payment->user_id = $user_id;
475
			$payment->save();
476
477
		}
478
	}
479
480
}
481
482
add_action( 'user_register', 'give_add_past_donations_to_new_user' );
483
484
485
/**
486
 * Counts the total number of donors.
487
 *
488
 * @access        public
489
 * @since         1.0
490
 *
491
 * @return        int The total number of donors.
492
 */
493
function give_count_total_donors() {
494
	return Give()->donors->count();
495
}
496
497
498
/**
499
 * Returns the saved address for a donor
500
 *
501
 * @access        public
502
 * @since         1.0
503
 *
504
 * @param         int $user_id The donor ID.x
505
 *
506
 * @return        array The donor's address, if any
507
 */
508
function give_get_donor_address( $user_id = 0 ) {
509
	if ( empty( $user_id ) ) {
510
		$user_id = get_current_user_id();
511
	}
512
513
	$address = get_user_meta( $user_id, '_give_user_address', true );
0 ignored issues
show
introduced by
get_user_meta() usage is highly discouraged, check VIP documentation on "Working with wp_users"
Loading history...
514
515
	if ( ! isset( $address['line1'] ) ) {
516
		$address['line1'] = '';
517
	}
518
519
	if ( ! isset( $address['line2'] ) ) {
520
		$address['line2'] = '';
521
	}
522
523
	if ( ! isset( $address['city'] ) ) {
524
		$address['city'] = '';
525
	}
526
527
	if ( ! isset( $address['zip'] ) ) {
528
		$address['zip'] = '';
529
	}
530
531
	if ( ! isset( $address['country'] ) ) {
532
		$address['country'] = '';
533
	}
534
535
	if ( ! isset( $address['state'] ) ) {
536
		$address['state'] = '';
537
	}
538
539
	return $address;
540
}
541
542
/**
543
 * Give New User Notification
544
 *
545
 * Sends the new user notification email when a user registers within the donation form
546
 *
547
 * @access        public
548
 * @since         1.0
549
 *
550
 * @param int   $user_id
551
 * @param array $user_data
552
 *
553
 * @return        void
554
 */
555
function give_new_user_notification( $user_id = 0, $user_data = array() ) {
556
557
	if ( empty( $user_id ) || empty( $user_data ) ) {
558
		return;
559
	}
560
	$blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
561
562
	// New User Registration: Email sends to the site admin.
563
	$emails = Give()->emails;
564
	$emails->__set( 'heading', esc_html__( 'New User Registration', 'give' ) );
565
566
	/* translators: %s: site name */
567
	$message = sprintf( esc_attr__( 'A new user has registered on %s:', 'give' ), $blogname ) . "\r\n\r\n";
568
	/* translators: %s: user login */
569
	$message .= '<strong>' . esc_attr__( 'Username:', 'give' ) . '</strong> ' . $user_data['user_login'] . "\r\n";
570
	/* translators: %s: user email */
571
	$message .= '<strong>' . esc_attr__( 'E-mail:', 'give' ) . '</strong> ' . $user_data['user_email'] . "\r\n\r\n";
572
573
	$message .= '<a href="' . admin_url( 'user-edit.php?user_id=' . $user_id ) . '" target="_blank"> ' . esc_attr__( 'Click here to view &raquo;', 'give' ) . '</a>' . "\r\n";
574
575
	$emails->send(
576
		get_option( 'admin_email' ),
577
		sprintf(
578
			/* translators: %s: site name */
579
			esc_attr__( '[%s] New User Registration', 'give' ),
580
			$blogname
581
		),
582
		$message
583
	);
584
585
	// Account Information: Email sends to donor who registered.
586
	$emails->__set( 'heading', esc_html__( 'Account Information', 'give' ) );
587
588
	$message = sprintf( esc_attr__( 'The following email contains your account information for %s:', 'give' ), $blogname ) . "\r\n\r\n";
589
590
	/* translators: %s: user login */
591
	$message .= '<strong>' . esc_attr__( 'Username:', 'give' ) . '</strong> ' . $user_data['user_login'] . "\r\n";
592
	/* translators: %s: password */
593
	$message .= '<strong>' . esc_attr__( 'Password:', 'give' ) . '</strong> ' . esc_attr__( '[Password entered during donation]', 'give' ) . "\r\n\r\n";
594
595
	$message .= '<a href="' . wp_login_url() . '" target="_blank"> ' . esc_attr__( 'Click here to login &raquo;', 'give' ) . '</a>' . "\r\n";
596
597
	$emails->send(
598
		$user_data['user_email'],
599
		sprintf(
600
			/* translators: %s: site name */
601
			esc_attr__( '[%s] Your username and password', 'give' ),
602
			$blogname
603
		),
604
		$message
605
	);
606
607
}
608
609
add_action( 'give_insert_user', 'give_new_user_notification', 10, 2 );
610
611
612
/**
613
 * Get Donor Name By
614
 *
615
 * Retrieves the donor name based on the id and the name of the user or donation.
616
 *
617
 * @access      public
618
 * @since       1.8.9
619
 *
620
 * @param       int    $id     The ID of donation or donor
621
 * @param       string $from   From will be a string to be passed as donation or donor
622
 *
623
 * @return      string
624
 */
625
function give_get_donor_name_by( $id = 0, $from = 'donation' ) {
626
627
	// ID shouldn't be empty
628
	if ( empty( $id ) ) {
629
		return;
630
	}
631
632
	$name = '';
633
634
	switch ( $from ) {
635
636
		case 'donation':
637
638
			$user_info = give_get_payment_meta_user_info( $id );
639
			$name = $user_info['first_name'] . ' ' . $user_info['last_name'];
640
641
		break;
642
643
		case 'donor':
644
645
			$donor = new Give_Donor( $id );
0 ignored issues
show
Documentation introduced by
$id is of type integer, but the function expects a boolean.

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...
646
			$name = $donor->name;
647
648
		break;
649
650
	}
651
652
	return trim( $name );
653
654
}
655
656
/**
657
 * Checks whether the given donor email exists in users as well as additional_email of donors.
658
 *
659
 * @since 1.8.9
660
 *
661
 * @param  string $email Donor Email.
662
 * @return boolean  The user's ID on success, and false on failure.
663
 */
664
function give_donor_email_exists( $email ) {
665
	if ( Give()->donors->get_donor_by( 'email', $email ) ) {
666
		return true;
667
	}
668
	return false;
669
}
670
671
/**
672
 * This function will check whether the donor email is primary or additional.
673
 *
674
 * @param $email Donor Email.
675
 *
676
 * @since 1.8.13
677
 *
678
 * @return bool
679
 */
680
function give_is_additional_email( $email ) {
681
	global $wpdb;
682
	$meta_table  = Give()->donor_meta->table_name;
683
	$donor_id = $wpdb->get_var( $wpdb->prepare( "SELECT customer_id FROM {$meta_table} WHERE meta_key = 'additional_email' AND meta_value = %s LIMIT 1", $email ) );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
684
685
	if ( empty( $donor_id ) ) {
686
		return false;
687
	}
688
	return true;
689
}
690