Completed
Pull Request — master (#1832)
by Devin
04:50
created

user-functions.php ➔ give_get_users_donations()   D

Complexity

Conditions 12
Paths 258

Size

Total Lines 53
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 15.5229

Importance

Changes 0
Metric Value
cc 12
eloc 30
nc 258
nop 4
dl 0
loc 53
ccs 22
cts 31
cp 0.7097
crap 15.5229
rs 4.6615
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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

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

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

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

Loading history...
2
/**
3
 * 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;
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_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 && ( give_donor_email_exists( $email ) || email_exists( $email ) ) ) {
363
		// Check if email exists.
364
		give_set_error( 'email_used', __( 'The email address provided is already active for another user.', 'give' ) );
365
		$valid = false;
366
	}
367
368
	/**
369
	 * Filter the email validation result.
370
	 *
371
	 * @since 1.8
372
	 *
373
	 * @param bool   $valid
374
	 * @param string $email
375
	 * @param bool   $registering_new_user
376
	 */
377
	$valid = (bool) apply_filters( 'give_validate_user_email', $valid, $email, $registering_new_user );
378
379
	return $valid;
380
}
381
382
/**
383
 * Validate password.
384
 *
385
 * @since 1.8
386
 *
387
 * @param string $password
388
 * @param string $confirm_password
389
 * @param bool   $registering_new_user
390
 *
391
 * @return bool
392
 */
393
function give_validate_user_password( $password = '', $confirm_password = '', $registering_new_user = false ) {
394
	$valid = true;
395
396
	// Passwords Validation For New Donors Only
397
	if ( $registering_new_user ) {
398
		// Password or confirmation missing.
399
		if ( ! $password ) {
400
			// The password is invalid.
401
			give_set_error( 'password_empty', __( 'Enter a password.', 'give' ) );
402
			$valid = false;
403
		} elseif ( ! $confirm_password ) {
404
			// Confirmation password is invalid.
405
			give_set_error( 'confirmation_empty', __( 'Enter the password confirmation.', 'give' ) );
406
			$valid = false;
407
		}
408
	}
409
	// Passwords Validation For New Donors as well as Existing Donors
410
	if( $password || $confirm_password ) {
411
		if ( strlen( $password ) < 6 || strlen( $confirm_password ) < 6 ) {
412
			// Seems Weak Password
413
			give_set_error( 'password_weak', __( 'Passwords should have atleast 6 characters.', 'give' ) );
414
			$valid = false;
415
		}
416
		if ( $password && $confirm_password ) {
417
			// Verify confirmation matches.
418
			if ( $password != $confirm_password ) {
419
				// Passwords do not match
420
				give_set_error( 'password_mismatch', __( 'Passwords you entered do not match. Please try again.', 'give' ) );
421
				$valid = false;
422
			}
423
		}
424
	}
425
426
	/**
427
	 * Filter the password validation result.
428
	 *
429
	 * @since 1.8
430
	 *
431
	 * @param bool   $valid
432
	 * @param string $password
433
	 * @param string $confirm_password
434
	 * @param bool   $registering_new_user
435
	 */
436
	$valid = (bool) apply_filters( 'give_validate_user_email', $valid, $password, $confirm_password, $registering_new_user );
437
438
	return $valid;
439
}
440
441
442
/**
443
 * Looks up donations by email that match the registering user.
444
 *
445
 * This is for users that donated as a guest and then came back and created an account.
446
 *
447
 * @access      public
448
 * @since       1.0
449
 *
450
 * @param       int $user_id The new user's ID.
451
 *
452
 * @return      void
453
 */
454
function give_add_past_donations_to_new_user( $user_id ) {
455
456
	$email = get_the_author_meta( 'user_email', $user_id );
457
458
	$payments = give_get_payments( array(
459
		's' => $email,
460
	) );
461
462
	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...
463
		foreach ( $payments as $payment ) {
464
			if ( intval( give_get_payment_user_id( $payment->ID ) ) > 0 ) {
465
				continue;
466
			} // End if().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
467
468
			$meta                    = give_get_payment_meta( $payment->ID );
469
			$meta['user_info']       = maybe_unserialize( $meta['user_info'] );
470
			$meta['user_info']['id'] = $user_id;
471
472
			// Store the updated user ID in the payment meta.
473
			give_update_payment_meta( $payment->ID, '_give_payment_meta', $meta );
474
			give_update_payment_meta( $payment->ID, '_give_payment_user_id', $user_id );
475
		}
476
	}
477
478
}
479
480
add_action( 'user_register', 'give_add_past_donations_to_new_user' );
481
482
483
/**
484
 * Counts the total number of donors.
485
 *
486
 * @access        public
487
 * @since         1.0
488
 *
489
 * @return        int The total number of donors.
490
 */
491
function give_count_total_donors() {
492
	return Give()->donors->count();
493
}
494
495
496
/**
497
 * Returns the saved address for a donor
498
 *
499
 * @access        public
500
 * @since         1.0
501
 *
502
 * @param         int $user_id The donor ID.x
503
 *
504
 * @return        array The donor's address, if any
505
 */
506
function give_get_donor_address( $user_id = 0 ) {
507
	if ( empty( $user_id ) ) {
508
		$user_id = get_current_user_id();
509
	}
510
511
	$address = get_user_meta( $user_id, '_give_user_address', true );
512
513
	if ( ! isset( $address['line1'] ) ) {
514
		$address['line1'] = '';
515
	}
516
517
	if ( ! isset( $address['line2'] ) ) {
518
		$address['line2'] = '';
519
	}
520
521
	if ( ! isset( $address['city'] ) ) {
522
		$address['city'] = '';
523
	}
524
525
	if ( ! isset( $address['zip'] ) ) {
526
		$address['zip'] = '';
527
	}
528
529
	if ( ! isset( $address['country'] ) ) {
530
		$address['country'] = '';
531
	}
532
533
	if ( ! isset( $address['state'] ) ) {
534
		$address['state'] = '';
535
	}
536
537
	return $address;
538
}
539
540
/**
541
 * Give New User Notification
542
 *
543
 * Sends the new user notification email when a user registers within the donation form
544
 *
545
 * @access        public
546
 * @since         1.0
547
 *
548
 * @param int   $user_id
549
 * @param array $user_data
550
 *
551
 * @return        void
552
 */
553
function give_new_user_notification( $user_id = 0, $user_data = array() ) {
554
555
	if ( empty( $user_id ) || empty( $user_data ) ) {
556
		return;
557
	}
558
	$blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
559
560
561
	// New User Registration: Email sends to the site admin.
562
	$emails = Give()->emails;
563
	$emails->__set( 'heading', esc_html__( 'New User Registration', 'give' ) );
564
565
	/* translators: %s: site name */
566
	$message = sprintf( esc_attr__( 'A new user has registered on %s:', 'give' ), $blogname ) . "\r\n\r\n";
567
	/* translators: %s: user login */
568
	$message .= '<strong>' . esc_attr__( 'Username:', 'give' ) . '</strong> ' . $user_data['user_login'] . "\r\n";
569
	/* translators: %s: user email */
570
	$message .= '<strong>' . esc_attr__( 'E-mail:', 'give' ) . '</strong> ' . $user_data['user_email']  . "\r\n\r\n";
571
572
	$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";
573
574
	$emails->send(
575
		get_option( 'admin_email' ),
576
		sprintf(
577
			/* translators: %s: site name */
578
			esc_attr__( '[%s] New User Registration', 'give' ),
579
			$blogname
580
		),
581
		$message
582
	);
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
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string?

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

Loading history...
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 );
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