user-functions.php ➔ give_count_donations_of_donor()   A
last analyzed

Complexity

Conditions 6
Paths 16

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 16
nop 1
dl 0
loc 16
rs 9.1111
c 0
b 0
f 0
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, GiveWP
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
 * @param int    $user       User ID or email address.
25
 * @param int    $number     Number of donations to retrieve.
26
 * @param bool   $pagination Enable/Disable Pagination.
27
 * @param string $status     Donation Status.
28
 *
29
 * @since  1.0
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
	if ( empty( $user ) ) {
36
		$user = get_current_user_id();
37
	}
38
39
	if ( 0 === $user && ! Give()->email_access->token_exists ) {
40
		return false;
41
	}
42
43
	$status = ( 'complete' === $status ) ? 'publish' : $status;
44
	$paged = 1;
45
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
		'user'    => $user,
56
		'number'  => $number,
57
		'status'  => $status,
58
		'orderby' => 'date',
59
	) );
60
61
	if ( $pagination ) {
62
		$args['page'] = $paged;
63
	} else {
64
		$args['nopaging'] = true;
65
	}
66
67
	$by_user_id = is_numeric( $user ) ? true : false;
68
	$donor   = new Give_Donor( $user, $by_user_id );
69
70
	if ( ! empty( $donor->payment_ids ) ) {
71
72
		unset( $args['user'] );
73
		$args['post__in'] = array_map( 'absint', explode( ',', $donor->payment_ids ) );
74
75
	}
76
77
	$donations = give_get_payments( apply_filters( 'give_get_users_donations_args', $args ) );
78
79
	// No donations.
80
	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
	}
83
84
	return $donations;
85
}
86
87
/**
88
 * Get Users Donations
89
 *
90
 * Returns a list of unique donation forms given to by a specific user.
91
 *
92
 * @param int    $user   User ID or email address
93
 * @param string $status Donation Status.
94
 *
95
 * @since 1.0
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
		return false;
106
	}
107
108
	$by_user_id = is_numeric( $user ) ? true : false;
109
110
	$donor = new Give_Donor( $user, $by_user_id );
111
112
	if ( empty( $donor->payment_ids ) ) {
113
		return false;
114
	}
115
116
	// Get all the items donated.
117
	$payment_ids    = array_reverse( explode( ',', $donor->payment_ids ) );
118
	$limit_payments = apply_filters( 'give_users_completed_donations_payments', 50 );
119
120
	if ( ! empty( $limit_payments ) ) {
121
		$payment_ids = array_slice( $payment_ids, 0, $limit_payments );
122
		Give_Payments_Query::update_meta_cache( $payment_ids );
123
	}
124
125
	$donation_data = array();
126
	foreach ( $payment_ids as $payment_id ) {
127
		$donation_data[] = give_get_payment_meta( $payment_id );
128
	}
129
130
	if ( empty( $donation_data ) ) {
131
		return false;
132
	}
133
134
	// Grab only the post ids "form_id" of the forms donated on this order.
135
	$completed_donations_ids = array();
136
	foreach ( $donation_data as $donation_meta ) {
137
		$completed_donations_ids[] = isset( $donation_meta['form_id'] ) ? $donation_meta['form_id'] : '';
138
	}
139
140
	if ( empty( $completed_donations_ids ) ) {
141
		return false;
142
	}
143
144
	// Only include each donation once.
145
	$form_ids = array_unique( $completed_donations_ids );
146
147
	// Make sure we still have some products and a first item.
148
	if ( empty( $form_ids ) || ! isset( $form_ids[0] ) ) {
149
		return false;
150
	}
151
152
	$post_type = get_post_type( $form_ids[0] );
153
154
	$args = apply_filters( 'give_get_users_completed_donations_args', array(
155
		'include'        => $form_ids,
156
		'post_type'      => $post_type,
157
		'posts_per_page' => - 1,
158
	) );
159
160
	return apply_filters( 'give_users_completed_donations_list', get_posts( $args ) );
161
}
162
163
164
/**
165
 * Has donations
166
 *
167
 * Checks to see if a user has donated to at least one form.
168
 *
169
 * @param int $user_id The ID of the user to check.
170
 *
171
 * @access public
172
 * @since  1.0
173
 *
174
 * @return bool True if has donated, false other wise.
175
 */
176
function give_has_donations( $user_id = null ) {
177
	if ( empty( $user_id ) ) {
178
		$user_id = get_current_user_id();
179
	}
180
181
	if ( give_get_users_donations( $user_id, 1 ) ) {
182
		return true; // User has at least one donation.
183
	}
184
185
	// User has never donated anything.
186
	return false;
187
}
188
189
190
/**
191
 * Get Donation Status for User.
192
 *
193
 * Retrieves the donation count and the total amount spent for a specific user.
194
 *
195
 * @param int|string $user The ID or email of the donor to retrieve stats for.
196
 *
197
 * @access public
198
 * @since  1.0
199
 *
200
 * @return array
201
 */
202
function give_get_donation_stats_by_user( $user = '' ) {
203
204
	$field = '';
205
206
	if ( is_email( $user ) ) {
207
		$field = 'email';
208
	} elseif ( is_numeric( $user ) ) {
209
		$field = 'user_id';
210
	}
211
212
	$stats    = array();
213
	$donor = Give()->donors->get_donor_by( $field, $user );
214
215
	if ( $donor ) {
216
		$donor = new Give_Donor( $donor->id );
217
		$stats['purchases']   = absint( $donor->purchase_count );
218
		$stats['total_spent'] = give_maybe_sanitize_amount( $donor->get_total_donation_amount() );
219
	}
220
221
	/**
222
	 * Filter the donation stats.
223
	 *
224
	 * @since 1.7
225
	 */
226
	$stats = (array) apply_filters( 'give_donation_stats_by_user', $stats, $user );
227
228
	return $stats;
229
}
230
231
232
/**
233
 * Count number of donations of a donor.
234
 *
235
 * Returns total number of donations a donor has made.
236
 *
237
 * @param int|string $user The ID or email of the donor.
238
 *
239
 * @access public
240
 * @since  1.0
241
 *
242
 * @return int The total number of donations.
243
 */
244
function give_count_donations_of_donor( $user = null ) {
245
246
	// Logged in?
247
	if ( empty( $user ) ) {
248
		$user = get_current_user_id();
249
	}
250
251
	// Email access?
252
	if ( empty( $user ) && Give()->email_access->token_email ) {
253
		$user = Give()->email_access->token_email;
254
	}
255
256
	$stats = ! empty( $user ) ? give_get_donation_stats_by_user( $user ) : false;
257
258
	return isset( $stats['purchases'] ) ? $stats['purchases'] : 0;
259
}
260
261
/**
262
 * Calculates the total amount spent by a user.
263
 *
264
 * @param int|string $user The ID or email of the donor.
265
 *
266
 * @access public
267
 * @since  1.0
268
 *
269
 * @return float The total amount the user has spent
270
 */
271
function give_donation_total_of_user( $user = null ) {
272
273
	$stats = give_get_donation_stats_by_user( $user );
274
275
	return $stats['total_spent'];
276
}
277
278
279
/**
280
 * Validate a potential username.
281
 *
282
 * @param string $username The username to validate.
283
 * @param int    $form_id  Donation Form ID.
284
 *
285
 * @since 1.0
286
 *
287
 * @return bool
288
 */
289
function give_validate_username( $username, $form_id = 0 ) {
290
	$valid = true;
291
292
	// Validate username.
293
	if ( ! empty( $username ) ) {
294
295
		// Sanitize username.
296
		$sanitized_user_name = sanitize_user( $username, false );
297
298
		// We have an user name, check if it already exists.
299
		if ( username_exists( $username ) ) {
300
			// Username already registered.
301
			give_set_error( 'username_unavailable', __( 'Username already taken.', 'give' ) );
302
			$valid = false;
303
304
			// Check if it's valid.
305
		} elseif ( $sanitized_user_name !== $username ) {
306
			// Invalid username.
307
			if ( is_multisite() ) {
308
				give_set_error( 'username_invalid', __( 'Invalid username. Only lowercase letters (a-z) and numbers are allowed.', 'give' ) );
309
				$valid = false;
310
			} else {
311
				give_set_error( 'username_invalid', __( 'Invalid username.', 'give' ) );
312
				$valid = false;
313
			}
314
		}
315
	} else {
316
		// Username is empty.
317
		give_set_error( 'username_empty', __( 'Enter a username.', 'give' ) );
318
		$valid = false;
319
320
		// Check if guest checkout is disable for form.
321
		if ( $form_id && give_logged_in_only( $form_id ) ) {
322
			give_set_error( 'registration_required', __( 'You must register or login to complete your donation.', 'give' ) );
323
			$valid = false;
324
		}
325
	}
326
327
	/**
328
	 * Filter the username validation result.
329
	 *
330
	 * @param bool   $valid    Username is valid or not.
331
	 * @param string $username Username to check.
332
	 * @param bool   $form_id  Donation Form ID.
333
	 *
334
	 * @since 1.8
335
	 */
336
	$valid = (bool) apply_filters( 'give_validate_username', $valid, $username, $form_id );
337
338
	return $valid;
339
}
340
341
342
/**
343
 * Validate user email.
344
 *
345
 * @param string $email                User email.
346
 * @param bool   $registering_new_user Flag to check user register or not.
347
 *
348
 * @since 1.8
349
 *
350
 * @return bool
351
 */
352
function give_validate_user_email( $email, $registering_new_user = false ) {
353
	$valid = true;
354
355
	if ( empty( $email ) ) {
356
		// No email.
357
		give_set_error( 'email_empty', __( 'Enter an email.', 'give' ) );
358
		$valid = false;
359
360
	} elseif ( email_exists( $email ) ) {
361
		// Email already exists.
362
		give_set_error( 'email_exists', __( 'Email already exists.', 'give' ) );
363
		$valid = false;
364
365
	} elseif ( ! is_email( $email ) ) {
366
		// Validate email.
367
		give_set_error( 'email_invalid', __( 'Invalid email.', 'give' ) );
368
		$valid = false;
369
370
	} elseif ( $registering_new_user ) {
371
372
		// If donor email is not primary.
373
		if ( ! email_exists( $email ) && give_donor_email_exists( $email ) && give_is_additional_email( $email ) ) {
374
			// Check if email exists.
375
			give_set_error( 'email_used', __( 'The email address provided is already active for another user.', 'give' ) );
376
			$valid = false;
377
		}
378
	}
379
380
	/**
381
	 * Filter the email validation result.
382
	 *
383
	 * @param bool   $valid                Email is valid or not.
384
	 * @param string $email                Email to check.
385
	 * @param bool   $registering_new_user Registering New or Existing User.
386
	 *
387
	 * @since 1.8
388
	 */
389
	$valid = (bool) apply_filters( 'give_validate_user_email', $valid, $email, $registering_new_user );
390
391
	return $valid;
392
}
393
394
/**
395
 * Validate password.
396
 *
397
 * @param string $password             Password to Validate.
398
 * @param string $confirm_password     Password to Confirm Validation.
399
 * @param bool   $registering_new_user Registering New or Existing User.
400
 *
401
 * @since 1.8
402
 *
403
 * @return bool
404
 */
405
function give_validate_user_password( $password = '', $confirm_password = '', $registering_new_user = false ) {
406
	$valid = true;
407
408
	// Passwords Validation For New Donors Only.
409
	if ( $registering_new_user ) {
410
		// Password or confirmation missing.
411
		if ( ! $password ) {
412
			// The password is invalid.
413
			give_set_error( 'password_empty', __( 'Enter a password.', 'give' ) );
414
			$valid = false;
415
		} elseif ( ! $confirm_password ) {
416
			// Confirmation password is invalid.
417
			give_set_error( 'confirmation_empty', __( 'Enter the password confirmation.', 'give' ) );
418
			$valid = false;
419
		}
420
	}
421
	// Passwords Validation For New Donors as well as Existing Donors.
422
	if ( $password || $confirm_password ) {
423
		if ( strlen( $password ) < 6 || strlen( $confirm_password ) < 6 ) {
424
			// Seems Weak Password.
425
			give_set_error( 'password_weak', __( 'Passwords should have at least 6 characters.', 'give' ) );
426
			$valid = false;
427
		}
428
		if ( $password && $confirm_password ) {
429
			// Verify confirmation matches.
430
			if ( $password !== $confirm_password ) {
431
				// Passwords do not match.
432
				give_set_error( 'password_mismatch', __( 'Passwords you entered do not match. Please try again.', 'give' ) );
433
				$valid = false;
434
			}
435
		}
436
	}
437
438
	/**
439
	 * Filter the password validation result.
440
	 *
441
	 * @param bool   $valid                Password is Valid or not.
442
	 * @param string $password             Password to check validation.
443
	 * @param string $confirm_password     Password to confirm validation.
444
	 * @param bool   $registering_new_user Registering New or Existing User.
445
	 *
446
	 * @since 1.8
447
	 */
448
	$valid = (bool) apply_filters( 'give_validate_user_email', $valid, $password, $confirm_password, $registering_new_user );
449
450
	return $valid;
451
}
452
453
/**
454
 * Counts the total number of donors.
455
 *
456
 * @access public
457
 * @since  1.0
458
 *
459
 * @return int The total number of donors.
460
 */
461
function give_count_total_donors() {
462
	return Give()->donors->count();
463
}
464
465
/**
466
 * Returns the saved address for a donor
467
 *
468
 * @access public
469
 * @since  1.0
470
 *
471
 * @param int/null $donor_id Donor ID.
0 ignored issues
show
Documentation introduced by
The doc-type int/null could not be parsed: Unknown type name "int/null" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
472
 * @param array $args         {
473
 *
474
 * @type bool   $by_user_id   Flag to validate find donor by donor ID or user ID
475
 * @type string $address_type Optional. Which type of donor address this function will return.
476
 * }
477
 *
478
 * @return array The donor's address, if any
479
 */
480
function give_get_donor_address( $donor_id = null, $args = array() ) {
481
	$default_args = array(
482
		'by_user_id'   => false,
483
		'address_type' => 'billing',
484
	);
485
486
	$default_address = array(
487
		'line1'   => '',
488
		'line2'   => '',
489
		'city'    => '',
490
		'state'   => '',
491
		'country' => '',
492
		'zip'     => '',
493
	);
494
495
	$address = array();
496
	$args    = wp_parse_args( $args, $default_args );
497
498
	// Set user id if donor is empty.
499
	if ( empty( $donor_id ) ) {
500
		$donor_id           = get_current_user_id();
501
		$args['by_user_id'] = true;
502
	}
503
504
	// Backward compatibility.
505 View Code Duplication
	if ( ! give_has_upgrade_completed( 'v20_upgrades_user_address' ) && $by_user_id ) {
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...
506
		return wp_parse_args(
507
			(array) get_user_meta( $donor_id, '_give_user_address', true ),
508
			$default_address
509
		);
510
	}
511
512
	$donor = new Give_Donor( $donor_id, (bool) $args['by_user_id'] );
513
514
	if (
515
		! $donor->id ||
516
		empty( $donor->address ) ||
517
		! array_key_exists( $args['address_type'], $donor->address )
518
	) {
519
		return $default_address;
520
	}
521
522
	switch ( true ) {
523
		case is_string( end( $donor->address[ $args['address_type'] ] ) ):
524
			$address = wp_parse_args( $donor->address[ $args['address_type'] ], $default_address );
525
			break;
526
527 View Code Duplication
		case is_array( end( $donor->address[ $args['address_type'] ] ) ):
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...
528
			$address = wp_parse_args( array_shift( $donor->address[ $args['address_type'] ] ), $default_address );
529
			break;
530
	}
531
532
	return $address;
533
}
534
535
/**
536
 * Give New User Notification
537
 *
538
 * Sends the new user notification email when a user registers within the donation form
539
 *
540
 * @param int   $donation_id   Donation ID.
541
 * @param array $donation_data An Array of Donation Data.
542
 *
543
 * @access public
544
 * @since  1.0
545
 *
546
 * @return void
547
 */
548
function give_new_user_notification( $donation_id = 0, $donation_data = array() ) {
549
	// Bailout.
550
	if (
551
		empty( $donation_id )
552
		|| empty( $donation_data )
553
		|| ! isset( $_POST['give_create_account'] )
554
		|| 'on' !== give_clean( $_POST['give_create_account'] )
555
	) {
556
		return;
557
	}
558
559
	// For backward compatibility
560
	$user = get_user_by( 'ID', $donation_data['user_info']['id'] );
561
562
	$donation_data['user_info'] = array_merge(
563
		$donation_data['user_info'],
564
		array(
565
			'user_id'    => $donation_data['user_info']['id'],
566
			'user_first' => $donation_data['user_info']['first_name'],
567
			'user_last'  => $donation_data['user_info']['last_name'],
568
			'user_email' => $donation_data['user_info']['email'],
569
			'user_login' => $user->user_login,
570
		)
571
	);
572
573
	do_action( 'give_new-donor-register_email_notification', $donation_data['user_info']['id'], $donation_data['user_info'], $donation_id );
574
	do_action( 'give_donor-register_email_notification', $donation_data['user_info']['id'], $donation_data['user_info'], $donation_id );
575
}
576
577
add_action( 'give_insert_payment', 'give_new_user_notification', 10, 2 );
578
579
580
/**
581
 * Get Donor Name By
582
 *
583
 * Retrieves the donor name based on the id and the name of the user or donation
584
 *
585
 * @param int    $id   The ID of donation or donor.
586
 * @param string $from From will be a string to be passed as donation or donor.
587
 *
588
 * @access public
589
 * @since  1.8.9
590
 *
591
 * @return string
592
 */
593
function give_get_donor_name_by( $id = 0, $from = 'donation' ) {
594
595
	// ID shouldn't be empty.
596
	if ( empty( $id ) ) {
597
		return '';
598
	}
599
600
	$name         = '';
601
	$title_prefix = '';
602
603
	switch ( $from ) {
604
605
		case 'donation':
606
			$title_prefix  = give_get_meta( $id, '_give_payment_donor_title_prefix', true );
607
			$first_name    = give_get_meta( $id, '_give_donor_billing_first_name', true );
608
			$last_name     = give_get_meta( $id, '_give_donor_billing_last_name', true );
609
610
			$name = "{$first_name} {$last_name}";
611
612
			break;
613
614
		case 'donor':
615
			$name         = Give()->donors->get_column( 'name', $id );
616
			$title_prefix = Give()->donor_meta->get_meta( $id, '_give_donor_title_prefix', true );
617
618
			break;
619
620
	}
621
622
	// If title prefix is set then prepend it to name.
623
	$name = give_get_donor_name_with_title_prefixes( $title_prefix, $name );
624
625
	return $name;
626
627
}
628
629
/**
630
 * Checks whether the given donor email exists in users as well as additional_email of donors.
631
 *
632
 * @param string $email Donor Email.
633
 *
634
 * @since 1.8.9
635
 *
636
 * @return boolean  The user's ID on success, and false on failure.
637
 */
638
function give_donor_email_exists( $email ) {
639
	if ( Give()->donors->get_donor_by( 'email', $email ) ) {
640
		return true;
641
	}
642
	return false;
643
}
644
645
/**
646
 * This function will check whether the donor email is primary or additional.
647
 *
648
 * @param string $email Donor Email.
649
 *
650
 * @since 1.8.13
651
 *
652
 * @return bool
653
 */
654
function give_is_additional_email( $email ) {
655
	global $wpdb;
656
657
	$meta_table = Give()->donor_meta->table_name;
658
	$meta_type  = Give()->donor_meta->meta_type;
659
	$donor_id   = $wpdb->get_var( $wpdb->prepare( "SELECT {$meta_type}_id FROM {$meta_table} WHERE meta_key = 'additional_email' AND meta_value = %s LIMIT 1", $email ) );
660
661
	if ( empty( $donor_id ) ) {
662
		return false;
663
	}
664
665
	return true;
666
}
667