Test Failed
Push — issues/2610 ( 4e0645 )
by Ravinder
08:18
created

functions.php ➔ give_get_donation_form_title()   C

Complexity

Conditions 10
Paths 36

Size

Total Lines 71
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 41
nc 36
nop 2
dl 0
loc 71
rs 5.9513
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
 * Payment Functions
4
 *
5
 * @package     Give
6
 * @subpackage  Payments
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
 * Get Payments
19
 *
20
 * Retrieve payments from the database.
21
 *
22
 * Since 1.0, this function takes an array of arguments, instead of individual
23
 * parameters. All of the original parameters remain, but can be passed in any
24
 * order via the array.
25
 *
26
 * @since 1.0
27
 *
28
 * @param array $args     {
29
 *                        Optional. Array of arguments passed to payments query.
30
 *
31
 * @type int    $offset   The number of payments to offset before retrieval.
32
 *                            Default is 0.
33
 * @type int    $number   The number of payments to query for. Use -1 to request all
34
 *                            payments. Default is 20.
35
 * @type string $mode     Default is 'live'.
36
 * @type string $order    Designates ascending or descending order of payments.
37
 *                            Accepts 'ASC', 'DESC'. Default is 'DESC'.
38
 * @type string $orderby  Sort retrieved payments by parameter. Default is 'ID'.
39
 * @type string $status   The status of the payments. Default is 'any'.
40
 * @type string $user     User. Default is null.
41
 * @type string $meta_key Custom field key. Default is null.
42
 *
43
 * }
44
 *
45
 * @return array $payments Payments retrieved from the database
46
 */
47
function give_get_payments( $args = array() ) {
48
49
	// Fallback to post objects to ensure backwards compatibility.
50
	if ( ! isset( $args['output'] ) ) {
51
		$args['output'] = 'posts';
52
	}
53
54
	$args     = apply_filters( 'give_get_payments_args', $args );
55
	$payments = new Give_Payments_Query( $args );
56
57
	return $payments->get_payments();
58
}
59
60
/**
61
 * Retrieve payment by a given field
62
 *
63
 * @since  1.0
64
 *
65
 * @param  string $field The field to retrieve the payment with.
66
 * @param  mixed  $value The value for $field.
67
 *
68
 * @return mixed
69
 */
70
function give_get_payment_by( $field = '', $value = '' ) {
71
72
	if ( empty( $field ) || empty( $value ) ) {
73
		return false;
74
	}
75
76
	switch ( strtolower( $field ) ) {
77
78
		case 'id':
79
			$payment = new Give_Payment( $value );
80
			$id      = $payment->ID;
81
82
			if ( empty( $id ) ) {
83
				return false;
84
			}
85
86
			break;
87
88 View Code Duplication
		case 'key':
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...
89
			$payment = give_get_payments( array(
90
				'meta_key'       => '_give_payment_purchase_key',
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
91
				'meta_value'     => $value,
0 ignored issues
show
introduced by
Detected usage of meta_value, possible slow query.
Loading history...
92
				'posts_per_page' => 1,
93
				'fields'         => 'ids',
94
			) );
95
96
			if ( $payment ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $payment 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...
97
				$payment = new Give_Payment( $payment[0] );
98
			}
99
100
			break;
101
102 View Code Duplication
		case 'payment_number':
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...
103
			$payment = give_get_payments( array(
104
				'meta_key'       => '_give_payment_number',
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
105
				'meta_value'     => $value,
0 ignored issues
show
introduced by
Detected usage of meta_value, possible slow query.
Loading history...
106
				'posts_per_page' => 1,
107
				'fields'         => 'ids',
108
			) );
109
110
			if ( $payment ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $payment 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...
111
				$payment = new Give_Payment( $payment[0] );
112
			}
113
114
			break;
115
116
		default:
117
			return false;
118
	}// End switch().
119
120
	if ( $payment ) {
121
		return $payment;
122
	}
123
124
	return false;
125
}
126
127
/**
128
 * Insert Payment
129
 *
130
 * @since  1.0
131
 *
132
 * @param  array $payment_data Arguments passed.
133
 *
134
 * @return int|bool Payment ID if payment is inserted, false otherwise.
135
 */
136
function give_insert_payment( $payment_data = array() ) {
137
138
	if ( empty( $payment_data ) ) {
139
		return false;
140
	}
141
142
	/**
143
	 * Fire the filter on donation data before insert.
144
	 *
145
	 * @since 1.8.15
146
	 *
147
	 * @param array $payment_data Arguments passed.
148
	 */
149
	$payment_data = apply_filters( 'give_pre_insert_payment', $payment_data );
150
151
	$payment    = new Give_Payment();
152
	$gateway    = ! empty( $payment_data['gateway'] ) ? $payment_data['gateway'] : '';
153
	$gateway    = empty( $gateway ) && isset( $_POST['give-gateway'] ) ? $_POST['give-gateway'] : $gateway;
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...
154
	$form_id    = isset( $payment_data['give_form_id'] ) ? $payment_data['give_form_id'] : 0;
155
	$price_id   = give_get_payment_meta_price_id( $payment_data );
156
	$form_title = isset( $payment_data['give_form_title'] ) ? $payment_data['give_form_title'] : get_the_title( $form_id );
157
158
	// Set properties.
159
	$payment->total          = $payment_data['price'];
160
	$payment->status         = ! empty( $payment_data['status'] ) ? $payment_data['status'] : 'pending';
161
	$payment->currency       = ! empty( $payment_data['currency'] ) ? $payment_data['currency'] : give_get_currency( $payment_data['give_form_id'], $payment_data );
162
	$payment->user_info      = $payment_data['user_info'];
163
	$payment->gateway        = $gateway;
164
	$payment->form_title     = $form_title;
165
	$payment->form_id        = $form_id;
166
	$payment->price_id       = $price_id;
167
	$payment->donor_id       = ( ! empty( $payment_data['donor_id'] ) ? $payment_data['donor_id'] : '' );
168
	$payment->user_id        = $payment_data['user_info']['id'];
169
	$payment->email          = $payment_data['user_email'];
170
	$payment->first_name     = $payment_data['user_info']['first_name'];
171
	$payment->last_name      = $payment_data['user_info']['last_name'];
172
	$payment->email          = $payment_data['user_info']['email'];
173
	$payment->ip             = give_get_ip();
0 ignored issues
show
Documentation Bug introduced by
It seems like give_get_ip() can also be of type array. However, the property $ip is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
174
	$payment->key            = $payment_data['purchase_key'];
175
	$payment->mode           = ( ! empty( $payment_data['mode'] ) ? (string) $payment_data['mode'] : ( give_is_test_mode() ? 'test' : 'live' ) );
176
	$payment->parent_payment = ! empty( $payment_data['parent'] ) ? absint( $payment_data['parent'] ) : '';
177
178
	// Add the donation.
179
	$args = array(
180
		'price'    => $payment->total,
181
		'price_id' => $payment->price_id,
182
	);
183
184
	$payment->add_donation( $payment->form_id, $args );
185
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
186
187
	// Set date if present.
188
	if ( isset( $payment_data['post_date'] ) ) {
189
		$payment->date = $payment_data['post_date'];
190
	}
191
192
	// Handle sequential payments.
193
	if ( give_get_option( 'enable_sequential' ) ) {
194
		$number          = give_get_next_payment_number();
195
		$payment->number = give_format_payment_number( $number );
196
		update_option( 'give_last_payment_number', $number );
197
	}
198
199
	// Save payment.
200
	$payment->save();
201
202
	/**
203
	 * Fires while inserting payments.
204
	 *
205
	 * @since 1.0
206
	 *
207
	 * @param int   $payment_id   The payment ID.
208
	 * @param array $payment_data Arguments passed.
209
	 */
210
	do_action( 'give_insert_payment', $payment->ID, $payment_data );
211
212
	// Return payment ID upon success.
213
	if ( ! empty( $payment->ID ) ) {
214
		return $payment->ID;
215
	}
216
217
	// Return false if no payment was inserted.
218
	return false;
219
220
}
221
222
/**
223
 * Create payment.
224
 *
225
 * @param $payment_data
226
 *
227
 * @return bool|int
228
 */
229
function give_create_payment( $payment_data ) {
230
231
	$form_id  = intval( $payment_data['post_data']['give-form-id'] );
232
	$price_id = isset( $payment_data['post_data']['give-price-id'] ) ? $payment_data['post_data']['give-price-id'] : '';
233
234
	// Collect payment data.
235
	$insert_payment_data = array(
236
		'price'           => $payment_data['price'],
237
		'give_form_title' => $payment_data['post_data']['give-form-title'],
238
		'give_form_id'    => $form_id,
239
		'give_price_id'   => $price_id,
240
		'date'            => $payment_data['date'],
241
		'user_email'      => $payment_data['user_email'],
242
		'purchase_key'    => $payment_data['purchase_key'],
243
		'currency'        => give_get_currency( $form_id, $payment_data ),
244
		'user_info'       => $payment_data['user_info'],
245
		'status'          => 'pending',
246
		'gateway'         => 'paypal',
247
	);
248
249
	/**
250
	 * Filter the payment params.
251
	 *
252
	 * @since 1.8
253
	 *
254
	 * @param array $insert_payment_data
255
	 */
256
	$insert_payment_data = apply_filters( 'give_create_payment', $insert_payment_data );
257
258
	// Record the pending payment.
259
	return give_insert_payment( $insert_payment_data );
260
}
261
262
/**
263
 * Updates a payment status.
264
 *
265
 * @param  int    $payment_id Payment ID.
266
 * @param  string $new_status New Payment Status. Default is 'publish'.
267
 *
268
 * @since  1.0
269
 *
270
 * @return bool
271
 */
272
function give_update_payment_status( $payment_id, $new_status = 'publish' ) {
273
274
	$updated = false;
275
	$payment = new Give_Payment( $payment_id );
276
277
	if ( $payment && $payment->ID > 0 ) {
278
279
		$payment->status = $new_status;
280
		$updated         = $payment->save();
281
282
	}
283
284
	return $updated;
285
}
286
287
288
/**
289
 * Deletes a Donation
290
 *
291
 * @since  1.0
292
 *
293
 * @param  int  $payment_id   Payment ID (default: 0).
294
 * @param  bool $update_donor If we should update the donor stats (default:true).
295
 *
296
 * @return void
297
 */
298
function give_delete_donation( $payment_id = 0, $update_donor = true ) {
299
	$payment = new Give_Payment( $payment_id );
300
301
	// Bailout.
302
	if ( ! $payment->ID ) {
303
		return;
304
	}
305
306
	$amount   = give_donation_amount( $payment_id );
307
	$status   = $payment->post_status;
308
	$donor_id = give_get_payment_donor_id( $payment_id );
309
	$donor    = new Give_Donor( $donor_id );
0 ignored issues
show
Documentation introduced by
$donor_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...
310
311
	// Only undo donations that aren't these statuses.
312
	$dont_undo_statuses = apply_filters( 'give_undo_donation_statuses', array(
313
		'pending',
314
		'cancelled',
315
	) );
316
317
	if ( ! in_array( $status, $dont_undo_statuses ) ) {
318
		give_undo_donation( $payment_id );
319
	}
320
321
	// Only undo donations that aren't these statuses.
322
	$status_to_decrease_stats = apply_filters( 'give_decrease_donor_statuses', array( 'publish' ) );
323
324
	if ( in_array( $status, $status_to_decrease_stats ) ) {
325
326
		// Only decrease earnings if they haven't already been decreased (or were never increased for this payment).
327
		give_decrease_total_earnings( $amount );
328
329
		// @todo: Refresh only range related stat cache
330
		give_delete_donation_stats();
331
332
		if ( $donor->id && $update_donor ) {
333
334
			// Decrement the stats for the donor.
335
			$donor->decrease_donation_count();
336
			$donor->decrease_value( $amount );
337
338
		}
339
	}
340
341
	/**
342
	 * Fires before deleting payment.
343
	 *
344
	 * @param int $payment_id Payment ID.
345
	 *
346
	 * @since 1.0
347
	 */
348
	do_action( 'give_payment_delete', $payment_id );
349
350
	if ( $donor->id && $update_donor ) {
351
		// Remove the payment ID from the donor.
352
		$donor->remove_payment( $payment_id );
353
	}
354
355
	// Remove the payment.
356
	wp_delete_post( $payment_id, true );
357
358
	// Remove related sale log entries.
359
	Give()->logs->delete_logs( $payment_id );
360
361
	/**
362
	 * Fires after payment deleted.
363
	 *
364
	 * @param int $payment_id Payment ID.
365
	 *
366
	 * @since 1.0
367
	 */
368
	do_action( 'give_payment_deleted', $payment_id );
369
}
370
371
/**
372
 * Undo Donation
373
 *
374
 * Undoes a donation, including the decrease of donations and earning stats.
375
 * Used for when refunding or deleting a donation.
376
 *
377
 * @param  int $payment_id Payment ID.
378
 *
379
 * @since  1.0
380
 *
381
 * @return void
382
 */
383
function give_undo_donation( $payment_id ) {
384
385
	$payment = new Give_Payment( $payment_id );
386
387
	$maybe_decrease_earnings = apply_filters( 'give_decrease_earnings_on_undo', true, $payment, $payment->form_id );
388
	if ( true === $maybe_decrease_earnings ) {
389
		// Decrease earnings.
390
		give_decrease_form_earnings( $payment->form_id, $payment->total );
391
	}
392
393
	$maybe_decrease_donations = apply_filters( 'give_decrease_donations_on_undo', true, $payment, $payment->form_id );
394
	if ( true === $maybe_decrease_donations ) {
395
		// Decrease donation count.
396
		give_decrease_donation_count( $payment->form_id );
397
	}
398
399
}
400
401
402
/**
403
 * Count Payments
404
 *
405
 * Returns the total number of payments recorded.
406
 *
407
 * @param  array $args Arguments passed.
408
 *
409
 * @since  1.0
410
 *
411
 * @return object $stats Contains the number of payments per payment status.
412
 */
413
function give_count_payments( $args = array() ) {
414
	// Backward compatibility.
415
	if ( ! empty( $args['start-date'] ) ) {
416
		$args['start_date'] = $args['start-date'];
417
		unset( $args['start-date'] );
418
	}
419
420
	if ( ! empty( $args['end-date'] ) ) {
421
		$args['end_date'] = $args['end-date'];
422
		unset( $args['end-date'] );
423
	}
424
425
	if ( ! empty( $args['form_id'] ) ) {
426
		$args['give_forms'] = $args['form_id'];
427
		unset( $args['form_id'] );
428
	}
429
430
	// Extract all donations
431
	$args['number']      = - 1;
432
	$args['group_by']    = 'post_status';
433
	$args['count']       = 'true';
434
435
	$donations_obj   = new Give_Payments_Query( $args );
436
	$donations_count = $donations_obj->get_payment_by_group();
437
438
	/**
439
	 * Filter the payment counts group by status
440
	 *
441
	 * @since 1.0
442
	 */
443
	return (object) apply_filters( 'give_count_payments', $donations_count, $args, $donations_obj );
444
}
445
446
447
/**
448
 * Check For Existing Payment
449
 *
450
 * @param  int $payment_id Payment ID.
451
 *
452
 * @since  1.0
453
 *
454
 * @return bool $exists True if payment exists, false otherwise.
455
 */
456
function give_check_for_existing_payment( $payment_id ) {
457
	$exists  = false;
458
	$payment = new Give_Payment( $payment_id );
459
460
	if ( $payment_id === $payment->ID && 'publish' === $payment->status ) {
461
		$exists = true;
462
	}
463
464
	return $exists;
465
}
466
467
/**
468
 * Get Payment Status
469
 *
470
 * @param WP_Post|Give_Payment|int $payment      Payment object or payment ID.
471
 * @param bool                     $return_label Whether to return the translated status label instead of status value.
472
 *                                               Default false.
473
 *
474
 * @since 1.0
475
 *
476
 * @return bool|mixed True if payment status exists, false otherwise.
477
 */
478
function give_get_payment_status( $payment, $return_label = false ) {
479
480
	if ( is_numeric( $payment ) ) {
481
482
		$payment = new Give_Payment( $payment );
483
484
		if ( ! $payment->ID > 0 ) {
485
			return false;
486
		}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
487
488
	}
489
490
	if ( ! is_object( $payment ) || ! isset( $payment->post_status ) ) {
491
		return false;
492
	}
493
494
	$statuses = give_get_payment_statuses();
495
496
	if ( ! is_array( $statuses ) || empty( $statuses ) ) {
497
		return false;
498
	}
499
500
	// Get payment object if not already given.
501
	$payment = $payment instanceof Give_Payment ? $payment : new Give_Payment( $payment->ID );
502
503
	if ( array_key_exists( $payment->status, $statuses ) ) {
504
		if ( true === $return_label ) {
505
			// Return translated status label.
506
			return $statuses[ $payment->status ];
507
		} else {
508
			// Account that our 'publish' status is labeled 'Complete'
509
			$post_status = 'publish' === $payment->status ? 'Complete' : $payment->post_status;
510
511
			// Make sure we're matching cases, since they matter
512
			return array_search( strtolower( $post_status ), array_map( 'strtolower', $statuses ) );
513
		}
514
	}
515
516
	return false;
517
}
518
519
/**
520
 * Retrieves all available statuses for payments.
521
 *
522
 * @since  1.0
523
 *
524
 * @return array $payment_status All the available payment statuses.
525
 */
526
function give_get_payment_statuses() {
527
	$payment_statuses = array(
528
		'pending'     => __( 'Pending', 'give' ),
529
		'publish'     => __( 'Complete', 'give' ),
530
		'refunded'    => __( 'Refunded', 'give' ),
531
		'failed'      => __( 'Failed', 'give' ),
532
		'cancelled'   => __( 'Cancelled', 'give' ),
533
		'abandoned'   => __( 'Abandoned', 'give' ),
534
		'preapproval' => __( 'Pre-Approved', 'give' ),
535
		'processing'  => __( 'Processing', 'give' ),
536
		'revoked'     => __( 'Revoked', 'give' ),
537
	);
538
539
	return apply_filters( 'give_payment_statuses', $payment_statuses );
540
}
541
542
/**
543
 * Get Payment Status Keys
544
 *
545
 * Retrieves keys for all available statuses for payments
546
 *
547
 * @since 1.0
548
 *
549
 * @return array $payment_status All the available payment statuses.
550
 */
551
function give_get_payment_status_keys() {
552
	$statuses = array_keys( give_get_payment_statuses() );
553
	asort( $statuses );
554
555
	return array_values( $statuses );
556
}
557
558
/**
559
 * Get Earnings By Date
560
 *
561
 * @param int $day       Day number. Default is null.
562
 * @param int $month_num Month number. Default is null.
563
 * @param int $year      Year number. Default is null.
564
 * @param int $hour      Hour number. Default is null.
565
 *
566
 * @since 1.0
567
 *
568
 * @return int $earnings Earnings
569
 */
570
function give_get_earnings_by_date( $day = null, $month_num, $year = null, $hour = null ) {
571
	// This is getting deprecated soon. Use Give_Payment_Stats with the get_earnings() method instead.
572
573
	global $wpdb;
574
	$meta_table = __give_v20_bc_table_details( 'payment' );
0 ignored issues
show
Unused Code introduced by
$meta_table is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
575
576
	$args = array(
577
		'post_type'              => 'give_payment',
578
		'nopaging'               => true,
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set nopaging to true ever.
Loading history...
579
		'year'                   => $year,
580
		'monthnum'               => $month_num,
581
		'post_status'            => array( 'publish' ),
582
		'fields'                 => 'ids',
583
		'update_post_term_cache' => false,
584
	);
585
	if ( ! empty( $day ) ) {
586
		$args['day'] = $day;
587
	}
588
589
	if ( isset( $hour ) ) {
590
		$args['hour'] = $hour;
591
	}
592
593
	$args = apply_filters( 'give_get_earnings_by_date_args', $args );
594
	$key  = Give_Cache::get_key( 'give_stats', $args );
595
596 View Code Duplication
	if ( ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'give-refresh-reports' ) ) {
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...
597
		$earnings = false;
598
	} else {
599
		$earnings = Give_Cache::get( $key );
600
	}
601
602
	if ( false === $earnings ) {
603
		$donations = get_posts( $args );
604
		$earnings  = 0;
605
		if ( $donations ) {
606
			$donations      = implode( ',', $donations );
607
			$earning_totals = $wpdb->get_var( "SELECT SUM(meta_value) FROM $wpdb->postmeta WHERE meta_key = '_give_payment_total' AND post_id IN ({$donations})" );
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...
608
609
			/**
610
			 * Filter The earnings by dates.
611
			 *
612
			 * @since 1.8.17
613
			 *
614
			 * @param float $earning_totals Total earnings between the dates.
615
			 * @param array $donations      Donations lists.
616
			 * @param array $args           Donation query args.
617
			 */
618
			$earnings = apply_filters( 'give_get_earnings_by_date', $earning_totals, $donations, $args );
619
		}
620
		// Cache the results for one hour.
621
		Give_Cache::set( $key, $earnings, HOUR_IN_SECONDS );
622
	}
623
624
	return round( $earnings, 2 );
625
}
626
627
/**
628
 * Get Donations (sales) By Date
629
 *
630
 * @param int $day       Day number. Default is null.
631
 * @param int $month_num Month number. Default is null.
632
 * @param int $year      Year number. Default is null.
633
 * @param int $hour      Hour number. Default is null.
634
 *
635
 * @since 1.0
636
 *
637
 * @return int $count Sales
638
 */
639
function give_get_sales_by_date( $day = null, $month_num = null, $year = null, $hour = null ) {
640
641
	// This is getting deprecated soon. Use Give_Payment_Stats with the get_sales() method instead.
642
	$args = array(
643
		'post_type'              => 'give_payment',
644
		'nopaging'               => true,
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set nopaging to true ever.
Loading history...
645
		'year'                   => $year,
646
		'fields'                 => 'ids',
647
		'post_status'            => array( 'publish' ),
648
		'update_post_meta_cache' => false,
649
		'update_post_term_cache' => false,
650
	);
651
652
	$show_free = apply_filters( 'give_sales_by_date_show_free', true, $args );
653
654
	if ( false === $show_free ) {
655
		$args['meta_query'] = array(
0 ignored issues
show
introduced by
Detected usage of meta_query, possible slow query.
Loading history...
656
			array(
657
				'key'     => '_give_payment_total',
658
				'value'   => 0,
659
				'compare' => '>',
660
				'type'    => 'NUMERIC',
661
			),
662
		);
663
	}
664
665
	if ( ! empty( $month_num ) ) {
666
		$args['monthnum'] = $month_num;
667
	}
668
669
	if ( ! empty( $day ) ) {
670
		$args['day'] = $day;
671
	}
672
673
	if ( isset( $hour ) ) {
674
		$args['hour'] = $hour;
675
	}
676
677
	$args = apply_filters( 'give_get_sales_by_date_args', $args );
678
679
	$key = Give_Cache::get_key( 'give_stats', $args );
680
681 View Code Duplication
	if ( ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'give-refresh-reports' ) ) {
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...
682
		$count = false;
683
	} else {
684
		$count = Give_Cache::get( $key );
685
	}
686
687
	if ( false === $count ) {
688
		$donations = new WP_Query( $args );
689
		$count     = (int) $donations->post_count;
690
		// Cache the results for one hour.
691
		Give_Cache::set( $key, $count, HOUR_IN_SECONDS );
692
	}
693
694
	return $count;
695
}
696
697
/**
698
 * Checks whether a payment has been marked as complete.
699
 *
700
 * @param int $payment_id Payment ID to check against.
701
 *
702
 * @since 1.0
703
 *
704
 * @return bool $ret True if complete, false otherwise.
705
 */
706
function give_is_payment_complete( $payment_id ) {
707
	$payment = new Give_Payment( $payment_id );
708
709
	$ret = false;
710
711
	if ( $payment->ID > 0 ) {
712
713
		if ( (int) $payment_id === (int) $payment->ID && 'publish' == $payment->status ) {
714
			$ret = true;
715
		}
716
	}
717
718
	return apply_filters( 'give_is_payment_complete', $ret, $payment_id, $payment->post_status );
719
}
720
721
/**
722
 * Get Total Donations.
723
 *
724
 * @since 1.0
725
 *
726
 * @return int $count Total number of donations.
727
 */
728
function give_get_total_donations() {
729
730
	$payments = give_count_payments();
731
732
	return $payments->publish;
733
}
734
735
/**
736
 * Get Total Earnings
737
 *
738
 * @param bool $recalculate Recalculate earnings forcefully.
739
 *
740
 * @since 1.0
741
 *
742
 * @return float $total Total earnings.
743
 */
744
function give_get_total_earnings( $recalculate = false ) {
745
746
	$total      = get_option( 'give_earnings_total', 0 );
747
	$meta_table = __give_v20_bc_table_details( 'payment' );
748
749
	// Calculate total earnings.
750
	if ( ! $total || $recalculate ) {
751
		global $wpdb;
752
753
		$total = (float) 0;
754
755
		$args = apply_filters( 'give_get_total_earnings_args', array(
756
			'offset' => 0,
757
			'number' => - 1,
758
			'status' => array( 'publish' ),
759
			'fields' => 'ids',
760
		) );
761
762
		$payments = give_get_payments( $args );
763
		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...
764
765
			/**
766
			 * If performing a donation, we need to skip the very last payment in the database,
767
			 * since it calls give_increase_total_earnings() on completion,
768
			 * which results in duplicated earnings for the very first donation.
769
			 */
770
			if ( did_action( 'give_update_payment_status' ) ) {
771
				array_pop( $payments );
772
			}
773
774
			if ( ! empty( $payments ) ) {
775
				$payments = implode( ',', $payments );
776
				$total    += $wpdb->get_var( "SELECT SUM(meta_value) FROM {$meta_table['name']} WHERE meta_key = '_give_payment_total' AND {$meta_table['column']['id']} IN({$payments})" );
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...
777
			}
778
		}
779
780
		update_option( 'give_earnings_total', $total, 'no' );
781
	}
782
783
	if ( $total < 0 ) {
784
		$total = 0; // Don't ever show negative earnings.
785
	}
786
787
	return apply_filters( 'give_total_earnings', round( $total, give_get_price_decimals() ), $total );
788
}
789
790
/**
791
 * Increase the Total Earnings
792
 *
793
 * @param int $amount The amount you would like to increase the total earnings by. Default is 0.
794
 *
795
 * @since 1.0
796
 *
797
 * @return float $total Total earnings.
798
 */
799
function give_increase_total_earnings( $amount = 0 ) {
800
	$total = give_get_total_earnings();
801
	$total += $amount;
802
	update_option( 'give_earnings_total', $total );
803
804
	return $total;
805
}
806
807
/**
808
 * Decrease the Total Earnings
809
 *
810
 * @param int $amount The amount you would like to decrease the total earnings by.
811
 *
812
 * @since 1.0
813
 *
814
 * @return float $total Total earnings.
815
 */
816
function give_decrease_total_earnings( $amount = 0 ) {
817
	$total = give_get_total_earnings();
818
	$total -= $amount;
819
	if ( $total < 0 ) {
820
		$total = 0;
821
	}
822
	update_option( 'give_earnings_total', $total );
823
824
	return $total;
825
}
826
827
/**
828
 * Get Payment Meta for a specific Payment
829
 *
830
 * @param int    $payment_id Payment ID.
831
 * @param string $meta_key   The meta key to pull.
832
 * @param bool   $single     Pull single meta entry or as an object.
833
 *
834
 * @since 1.0
835
 *
836
 * @return mixed $meta Payment Meta.
837
 */
838
function give_get_payment_meta( $payment_id = 0, $meta_key = '_give_payment_meta', $single = true ) {
839
	$payment = new Give_Payment( $payment_id );
840
841
	return $payment->get_meta( $meta_key, $single );
842
}
843
844
/**
845
 * Update the meta for a payment
846
 *
847
 * @param  int    $payment_id Payment ID.
848
 * @param  string $meta_key   Meta key to update.
849
 * @param  string $meta_value Value to update to.
850
 * @param  string $prev_value Previous value.
851
 *
852
 * @return mixed Meta ID if successful, false if unsuccessful.
853
 */
854
function give_update_payment_meta( $payment_id = 0, $meta_key = '', $meta_value = '', $prev_value = '' ) {
855
	$payment = new Give_Payment( $payment_id );
856
857
	return $payment->update_meta( $meta_key, $meta_value, $prev_value );
858
}
859
860
/**
861
 * Get the user_info Key from Payment Meta
862
 *
863
 * @param int $payment_id Payment ID.
864
 *
865
 * @since 1.0
866
 *
867
 * @return array $user_info User Info Meta Values.
868
 */
869
function give_get_payment_meta_user_info( $payment_id ) {
870
	$payment = new Give_Payment( $payment_id );
871
872
	return $payment->user_info;
873
}
874
875
/**
876
 * Get the donations Key from Payment Meta
877
 *
878
 * Retrieves the form_id from a (Previously titled give_get_payment_meta_donations)
879
 *
880
 * @param int $payment_id Payment ID.
881
 *
882
 * @since 1.0
883
 *
884
 * @return int $form_id Form ID.
885
 */
886
function give_get_payment_form_id( $payment_id ) {
887
	$payment = new Give_Payment( $payment_id );
888
889
	return $payment->form_id;
890
}
891
892
/**
893
 * Get the user email associated with a payment
894
 *
895
 * @param int $payment_id Payment ID.
896
 *
897
 * @since 1.0
898
 *
899
 * @return string $email User email.
900
 */
901
function give_get_payment_user_email( $payment_id ) {
902
	$payment = new Give_Payment( $payment_id );
903
904
	return $payment->email;
905
}
906
907
/**
908
 * Is the payment provided associated with a user account
909
 *
910
 * @param int $payment_id The payment ID.
911
 *
912
 * @since 1.3
913
 *
914
 * @return bool $is_guest_payment If the payment is associated with a user (false) or not (true)
915
 */
916
function give_is_guest_payment( $payment_id ) {
917
	$payment_user_id  = give_get_payment_user_id( $payment_id );
918
	$is_guest_payment = ! empty( $payment_user_id ) && $payment_user_id > 0 ? false : true;
919
920
	return (bool) apply_filters( 'give_is_guest_payment', $is_guest_payment, $payment_id );
921
}
922
923
/**
924
 * Get the user ID associated with a payment
925
 *
926
 * @param int $payment_id Payment ID.
927
 *
928
 * @since 1.3
929
 *
930
 * @return int $user_id User ID.
931
 */
932
function give_get_payment_user_id( $payment_id ) {
933
	$payment = new Give_Payment( $payment_id );
934
935
	return $payment->user_id;
936
}
937
938
/**
939
 * Get the donor ID associated with a payment.
940
 *
941
 * @param int $payment_id Payment ID.
942
 *
943
 * @since 1.0
944
 *
945
 * @return int $payment->customer_id Donor ID.
946
 */
947
function give_get_payment_donor_id( $payment_id ) {
948
	$payment = new Give_Payment( $payment_id );
949
950
	return $payment->customer_id;
951
}
952
953
/**
954
 * Get the IP address used to make a donation
955
 *
956
 * @param int $payment_id Payment ID.
957
 *
958
 * @since 1.0
959
 *
960
 * @return string $ip User IP.
961
 */
962
function give_get_payment_user_ip( $payment_id ) {
963
	$payment = new Give_Payment( $payment_id );
964
965
	return $payment->ip;
966
}
967
968
/**
969
 * Get the date a payment was completed
970
 *
971
 * @param int $payment_id Payment ID.
972
 *
973
 * @since 1.0
974
 *
975
 * @return string $date The date the payment was completed.
976
 */
977
function give_get_payment_completed_date( $payment_id = 0 ) {
978
	$payment = new Give_Payment( $payment_id );
979
980
	return $payment->completed_date;
981
}
982
983
/**
984
 * Get the gateway associated with a payment
985
 *
986
 * @param int $payment_id Payment ID.
987
 *
988
 * @since 1.0
989
 *
990
 * @return string $gateway Gateway.
991
 */
992
function give_get_payment_gateway( $payment_id ) {
993
	$payment = new Give_Payment( $payment_id );
994
995
	return $payment->gateway;
996
}
997
998
/**
999
 * Get the currency code a payment was made in
1000
 *
1001
 * @param int $payment_id Payment ID.
1002
 *
1003
 * @since 1.0
1004
 *
1005
 * @return string $currency The currency code.
1006
 */
1007
function give_get_payment_currency_code( $payment_id = 0 ) {
1008
	$payment = new Give_Payment( $payment_id );
1009
1010
	return $payment->currency;
1011
}
1012
1013
/**
1014
 * Get the currency name a payment was made in
1015
 *
1016
 * @param int $payment_id Payment ID.
1017
 *
1018
 * @since 1.0
1019
 *
1020
 * @return string $currency The currency name.
1021
 */
1022
function give_get_payment_currency( $payment_id = 0 ) {
1023
	$currency = give_get_payment_currency_code( $payment_id );
1024
1025
	return apply_filters( 'give_payment_currency', give_get_currency_name( $currency ), $payment_id );
1026
}
1027
1028
/**
1029
 * Get the key for a donation
1030
 *
1031
 * @param int $payment_id Payment ID.
1032
 *
1033
 * @since 1.0
1034
 *
1035
 * @return string $key Donation key.
1036
 */
1037
function give_get_payment_key( $payment_id = 0 ) {
1038
	$payment = new Give_Payment( $payment_id );
1039
1040
	return $payment->key;
1041
}
1042
1043
/**
1044
 * Get the payment order number
1045
 *
1046
 * This will return the payment ID if sequential order numbers are not enabled or the order number does not exist
1047
 *
1048
 * @param int $payment_id Payment ID.
1049
 *
1050
 * @since 1.0
1051
 *
1052
 * @return string $number Payment order number.
1053
 */
1054
function give_get_payment_number( $payment_id = 0 ) {
1055
	$payment = new Give_Payment( $payment_id );
1056
1057
	return $payment->number;
1058
}
1059
1060
/**
1061
 * Formats the payment number with the prefix and postfix
1062
 *
1063
 * @param int $number The payment number to format.
1064
 *
1065
 * @since 1.3
1066
 *
1067
 * @return string      The formatted payment number.
1068
 */
1069
function give_format_payment_number( $number ) {
1070
1071
	if ( ! give_get_option( 'enable_sequential' ) ) {
1072
		return $number;
1073
	}
1074
1075
	if ( ! is_numeric( $number ) ) {
1076
		return $number;
1077
	}
1078
1079
	$prefix  = give_get_option( 'sequential_prefix' );
1080
	$number  = absint( $number );
1081
	$postfix = give_get_option( 'sequential_postfix' );
1082
1083
	$formatted_number = $prefix . $number . $postfix;
1084
1085
	return apply_filters( 'give_format_payment_number', $formatted_number, $prefix, $number, $postfix );
1086
}
1087
1088
/**
1089
 * Gets the next available order number
1090
 *
1091
 * This is used when inserting a new payment
1092
 *
1093
 * @since 1.0
1094
 *
1095
 * @return string $number The next available payment number.
1096
 */
1097
function give_get_next_payment_number() {
1098
1099
	if ( ! give_get_option( 'enable_sequential' ) ) {
1100
		return false;
1101
	}
1102
1103
	$number           = get_option( 'give_last_payment_number' );
1104
	$start            = give_get_option( 'sequential_start', 1 );
1105
	$increment_number = true;
1106
1107
	if ( false !== $number ) {
1108
1109
		if ( empty( $number ) ) {
1110
1111
			$number           = $start;
1112
			$increment_number = false;
1113
1114
		}
1115
	} else {
1116
1117
		// This case handles the first addition of the new option, as well as if it get's deleted for any reason.
1118
		$payments     = new Give_Payments_Query( array(
1119
			'number'  => 1,
1120
			'order'   => 'DESC',
1121
			'orderby' => 'ID',
1122
			'output'  => 'posts',
1123
			'fields'  => 'ids',
1124
		) );
1125
		$last_payment = $payments->get_payments();
1126
1127
		if ( ! empty( $last_payment ) ) {
1128
1129
			$number = give_get_payment_number( $last_payment[0] );
1130
1131
		}
1132
1133
		if ( ! empty( $number ) && $number !== (int) $last_payment[0] ) {
1134
1135
			$number = give_remove_payment_prefix_postfix( $number );
1136
1137
		} else {
1138
1139
			$number           = $start;
1140
			$increment_number = false;
1141
		}
1142
	}// End if().
1143
1144
	$increment_number = apply_filters( 'give_increment_payment_number', $increment_number, $number );
1145
1146
	if ( $increment_number ) {
1147
		$number ++;
1148
	}
1149
1150
	return apply_filters( 'give_get_next_payment_number', $number );
1151
}
1152
1153
/**
1154
 * Given a given a number, remove the pre/postfix
1155
 *
1156
 * @param string $number The formatted Current Number to increment.
1157
 *
1158
 * @since 1.3
1159
 *
1160
 * @return string The new Payment number without prefix and postfix.
1161
 */
1162
function give_remove_payment_prefix_postfix( $number ) {
1163
1164
	$prefix  = give_get_option( 'sequential_prefix' );
1165
	$postfix = give_get_option( 'sequential_postfix' );
1166
1167
	// Remove prefix.
1168
	$number = preg_replace( '/' . $prefix . '/', '', $number, 1 );
1169
1170
	// Remove the postfix.
1171
	$length      = strlen( $number );
1172
	$postfix_pos = strrpos( $number, $postfix );
1173
	if ( false !== $postfix_pos ) {
1174
		$number = substr_replace( $number, '', $postfix_pos, $length );
1175
	}
1176
1177
	// Ensure it's a whole number.
1178
	$number = intval( $number );
1179
1180
	return apply_filters( 'give_remove_payment_prefix_postfix', $number, $prefix, $postfix );
1181
1182
}
1183
1184
/**
1185
 * Get Donation Amount
1186
 *
1187
 * Get the fully formatted or unformatted donation amount which is sent through give_currency_filter()
1188
 * and give_format_amount() to format the amount correctly in case of formatted amount.
1189
 *
1190
 * @param int|Give_Payment $donation    Donation ID or Donation Object.
1191
 * @param bool|array       $format_args Currency Formatting Arguments.
1192
 *
1193
 * @since 1.0
1194
 * @since 1.8.17 Added filter and internally use functions.
1195
 *
1196
 * @return string $amount Fully formatted donation amount.
1197
 */
1198
function give_donation_amount( $donation, $format_args = array() ) {
1199
	/* @var Give_Payment $donation */
1200
	if ( ! ( $donation instanceof Give_Payment ) ) {
1201
		$donation = new Give_Payment( absint( $donation ) );
1202
	}
1203
1204
	$amount           = $donation->total;
1205
	$formatted_amount = $amount;
1206
1207
	if ( is_bool( $format_args ) ) {
1208
		$format_args = array(
1209
			'currency' => (bool) $format_args,
1210
			'amount'   => (bool) $format_args,
1211
		);
1212
	}
1213
1214
	$format_args = wp_parse_args(
1215
		$format_args,
1216
		array(
1217
			'currency' => false,
1218
			'amount'   => false,
1219
1220
			// Define context of donation amount, by default keep $type as blank.
1221
			// Pass as 'stats' to calculate donation report on basis of base amount for the Currency-Switcher Add-on.
1222
			// For Eg. In Currency-Switcher add on when donation has been made through
1223
			// different currency other than base currency, in that case for correct
1224
			//report calculation based on base currency we will need to return donation
1225
			// base amount and not the converted amount .
1226
			'type'     => '',
1227
		)
1228
	);
1229
1230
	if ( $format_args['amount'] || $format_args['currency'] ) {
1231
1232
		if ( $format_args['amount'] ) {
1233
1234
			$formatted_amount = give_format_amount(
1235
				$amount,
1236
				! is_array( $format_args['amount'] ) ?
1237
					array(
1238
						'sanitize' => false,
1239
						'currency' => $donation->currency,
1240
					) :
1241
					$format_args['amount']
1242
			);
1243
		}
1244
1245
		if ( $format_args['currency'] ) {
1246
			$formatted_amount = give_currency_filter(
1247
				$formatted_amount,
1248
				! is_array( $format_args['currency'] ) ?
1249
					array( 'currency_code' => $donation->currency ) :
1250
					$format_args['currency']
1251
			);
1252
		}
1253
	}
1254
1255
	/**
1256
	 * Filter Donation amount.
1257
	 *
1258
	 * @since 1.8.17
1259
	 *
1260
	 * @param string $formatted_amount Formatted/Un-formatted amount.
1261
	 * @param float  $amount           Donation amount.
1262
	 * @param int    $donation_id      Donation ID.
1263
	 * @param string $type             Donation amount type.
1264
	 */
1265
	return apply_filters( 'give_donation_amount', (string) $formatted_amount, $amount, $donation, $format_args );
1266
}
1267
1268
/**
1269
 * Payment Subtotal
1270
 *
1271
 * Retrieves subtotal for payment and then returns a full formatted amount. This
1272
 * function essentially calls give_get_payment_subtotal()
1273
 *
1274
 * @param int $payment_id Payment ID.
1275
 *
1276
 * @since 1.5
1277
 *
1278
 * @see   give_get_payment_subtotal()
1279
 *
1280
 * @return array Fully formatted payment subtotal.
1281
 */
1282
function give_payment_subtotal( $payment_id = 0 ) {
1283
	$subtotal = give_get_payment_subtotal( $payment_id );
1284
1285
	return give_currency_filter( give_format_amount( $subtotal, array( 'sanitize' => false ) ), array( 'currency_code' => give_get_payment_currency_code( $payment_id ) ) );
1286
}
1287
1288
/**
1289
 * Get Payment Subtotal
1290
 *
1291
 * Retrieves subtotal for payment and then returns a non formatted amount.
1292
 *
1293
 * @param int $payment_id Payment ID.
1294
 *
1295
 * @since 1.5
1296
 *
1297
 * @return float $subtotal Subtotal for payment (non formatted).
1298
 */
1299
function give_get_payment_subtotal( $payment_id = 0 ) {
1300
	$payment = new Give_Payment( $payment_id );
1301
1302
	return $payment->subtotal;
1303
}
1304
1305
/**
1306
 * Retrieves the donation ID
1307
 *
1308
 * @param int $payment_id Payment ID.
1309
 *
1310
 * @since  1.0
1311
 *
1312
 * @return string The donation ID.
1313
 */
1314
function give_get_payment_transaction_id( $payment_id = 0 ) {
1315
	$payment = new Give_Payment( $payment_id );
1316
1317
	return $payment->transaction_id;
1318
}
1319
1320
/**
1321
 * Sets a Transaction ID in post meta for the given Payment ID.
1322
 *
1323
 * @param int    $payment_id     Payment ID.
1324
 * @param string $transaction_id The transaction ID from the gateway.
1325
 *
1326
 * @since  1.0
1327
 *
1328
 * @return bool|mixed
1329
 */
1330
function give_set_payment_transaction_id( $payment_id = 0, $transaction_id = '' ) {
1331
1332
	if ( empty( $payment_id ) || empty( $transaction_id ) ) {
1333
		return false;
1334
	}
1335
1336
	$transaction_id = apply_filters( 'give_set_payment_transaction_id', $transaction_id, $payment_id );
1337
1338
	return give_update_payment_meta( $payment_id, '_give_payment_transaction_id', $transaction_id );
1339
}
1340
1341
/**
1342
 * Retrieve the donation ID based on the key
1343
 *
1344
 * @param string  $key  the key to search for.
1345
 *
1346
 * @since 1.0
1347
 * @global object $wpdb Used to query the database using the WordPress Database API.
1348
 *
1349
 * @return int $purchase Donation ID.
1350
 */
1351 View Code Duplication
function give_get_donation_id_by_key( $key ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in 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...
1352
	global $wpdb;
1353
1354
	$meta_table = __give_v20_bc_table_details( 'payment' );
1355
1356
	$purchase = $wpdb->get_var(
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...
1357
		$wpdb->prepare(
1358
			"
1359
				SELECT {$meta_table['column']['id']}
1360
				FROM {$meta_table['name']}
1361
				WHERE meta_key = '_give_payment_purchase_key'
1362
				AND meta_value = %s
1363
				ORDER BY {$meta_table['column']['id']} DESC
1364
				LIMIT 1
1365
				",
1366
			$key
1367
		)
1368
	);
1369
1370
	if ( $purchase != null ) {
1371
		return $purchase;
1372
	}
1373
1374
	return 0;
1375
}
1376
1377
1378
/**
1379
 * Retrieve the donation ID based on the transaction ID
1380
 *
1381
 * @param string  $key  The transaction ID to search for.
1382
 *
1383
 * @since 1.3
1384
 * @global object $wpdb Used to query the database using the WordPress Database API.
1385
 *
1386
 * @return int $purchase Donation ID.
1387
 */
1388 View Code Duplication
function give_get_purchase_id_by_transaction_id( $key ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in 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...
1389
	global $wpdb;
1390
	$meta_table = __give_v20_bc_table_details( 'payment' );
1391
1392
	$purchase = $wpdb->get_var( $wpdb->prepare( "SELECT {$meta_table['column']['id']} FROM {$meta_table['name']} WHERE meta_key = '_give_payment_transaction_id' AND meta_value = %s LIMIT 1", $key ) );
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...
1393
1394
	if ( $purchase != null ) {
1395
		return $purchase;
1396
	}
1397
1398
	return 0;
1399
}
1400
1401
/**
1402
 * Retrieve all notes attached to a donation
1403
 *
1404
 * @param int    $payment_id The donation ID to retrieve notes for.
1405
 * @param string $search     Search for notes that contain a search term.
1406
 *
1407
 * @since 1.0
1408
 *
1409
 * @return array $notes Donation Notes
1410
 */
1411
function give_get_payment_notes( $payment_id = 0, $search = '' ) {
1412
1413
	if ( empty( $payment_id ) && empty( $search ) ) {
1414
		return false;
1415
	}
1416
1417
	remove_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1418
	remove_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10 );
1419
1420
	$notes = get_comments( array(
1421
		'post_id' => $payment_id,
1422
		'order'   => 'ASC',
1423
		'search'  => $search,
1424
	) );
1425
1426
	add_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1427
	add_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10, 2 );
1428
1429
	return $notes;
1430
}
1431
1432
1433
/**
1434
 * Add a note to a payment
1435
 *
1436
 * @param int    $payment_id The payment ID to store a note for.
1437
 * @param string $note       The note to store.
1438
 *
1439
 * @since 1.0
1440
 *
1441
 * @return int The new note ID
1442
 */
1443
function give_insert_payment_note( $payment_id = 0, $note = '' ) {
1444
	if ( empty( $payment_id ) ) {
1445
		return false;
1446
	}
1447
1448
	/**
1449
	 * Fires before inserting payment note.
1450
	 *
1451
	 * @param int    $payment_id Payment ID.
1452
	 * @param string $note       The note.
1453
	 *
1454
	 * @since 1.0
1455
	 */
1456
	do_action( 'give_pre_insert_payment_note', $payment_id, $note );
1457
1458
	$note_id = wp_insert_comment( wp_filter_comment( array(
1459
		'comment_post_ID'      => $payment_id,
1460
		'comment_content'      => $note,
1461
		'user_id'              => is_admin() ? get_current_user_id() : 0,
1462
		'comment_date'         => current_time( 'mysql' ),
1463
		'comment_date_gmt'     => current_time( 'mysql', 1 ),
1464
		'comment_approved'     => 1,
1465
		'comment_parent'       => 0,
1466
		'comment_author'       => '',
1467
		'comment_author_IP'    => '',
1468
		'comment_author_url'   => '',
1469
		'comment_author_email' => '',
1470
		'comment_type'         => 'give_payment_note',
1471
1472
	) ) );
1473
1474
	/**
1475
	 * Fires after payment note inserted.
1476
	 *
1477
	 * @param int    $note_id    Note ID.
1478
	 * @param int    $payment_id Payment ID.
1479
	 * @param string $note       The note.
1480
	 *
1481
	 * @since 1.0
1482
	 */
1483
	do_action( 'give_insert_payment_note', $note_id, $payment_id, $note );
1484
1485
	return $note_id;
1486
}
1487
1488
/**
1489
 * Deletes a payment note
1490
 *
1491
 * @param int $comment_id The comment ID to delete.
1492
 * @param int $payment_id The payment ID the note is connected to.
1493
 *
1494
 * @since 1.0
1495
 *
1496
 * @return bool True on success, false otherwise.
1497
 */
1498
function give_delete_payment_note( $comment_id = 0, $payment_id = 0 ) {
1499
	if ( empty( $comment_id ) ) {
1500
		return false;
1501
	}
1502
1503
	/**
1504
	 * Fires before deleting donation note.
1505
	 *
1506
	 * @param int $comment_id Note ID.
1507
	 * @param int $payment_id Payment ID.
1508
	 *
1509
	 * @since 1.0
1510
	 */
1511
	do_action( 'give_pre_delete_payment_note', $comment_id, $payment_id );
1512
1513
	$ret = wp_delete_comment( $comment_id, true );
1514
1515
	/**
1516
	 * Fires after donation note deleted.
1517
	 *
1518
	 * @param int $comment_id Note ID.
1519
	 * @param int $payment_id Payment ID.
1520
	 *
1521
	 * @since 1.0
1522
	 */
1523
	do_action( 'give_post_delete_payment_note', $comment_id, $payment_id );
1524
1525
	return $ret;
1526
}
1527
1528
/**
1529
 * Gets the payment note HTML
1530
 *
1531
 * @param object|int $note       The comment object or ID.
1532
 * @param int        $payment_id The payment ID the note is connected to.
1533
 *
1534
 * @since 1.0
1535
 *
1536
 * @return string
1537
 */
1538
function give_get_payment_note_html( $note, $payment_id = 0 ) {
1539
1540
	if ( is_numeric( $note ) ) {
1541
		$note = get_comment( $note );
1542
	}
1543
1544
	if ( ! empty( $note->user_id ) ) {
1545
		$user = get_userdata( $note->user_id );
1546
		$user = $user->display_name;
1547
	} else {
1548
		$user = __( 'System', 'give' );
1549
	}
1550
1551
	$date_format = give_date_format() . ', ' . get_option( 'time_format' );
1552
1553
	$delete_note_url = wp_nonce_url( add_query_arg( array(
1554
		'give-action' => 'delete_payment_note',
1555
		'note_id'     => $note->comment_ID,
1556
		'payment_id'  => $payment_id,
1557
	) ), 'give_delete_payment_note_' . $note->comment_ID );
1558
1559
	$note_html = '<div class="give-payment-note" id="give-payment-note-' . $note->comment_ID . '">';
1560
	$note_html .= '<p>';
1561
	$note_html .= '<strong>' . $user . '</strong>&nbsp;&ndash;&nbsp;<span style="color:#aaa;font-style:italic;">' . date_i18n( $date_format, strtotime( $note->comment_date ) ) . '</span><br/>';
1562
	$note_html .= $note->comment_content;
1563
	$note_html .= '&nbsp;&ndash;&nbsp;<a href="' . esc_url( $delete_note_url ) . '" class="give-delete-payment-note" data-note-id="' . absint( $note->comment_ID ) . '" data-payment-id="' . absint( $payment_id ) . '" aria-label="' . __( 'Delete this donation note.', 'give' ) . '">' . __( 'Delete', 'give' ) . '</a>';
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw '__'
Loading history...
1564
	$note_html .= '</p>';
1565
	$note_html .= '</div>';
1566
1567
	return $note_html;
1568
1569
}
1570
1571
/**
1572
 * Exclude notes (comments) on give_payment post type from showing in Recent
1573
 * Comments widgets
1574
 *
1575
 * @param object $query WordPress Comment Query Object.
1576
 *
1577
 * @since 1.0
1578
 *
1579
 * @return void
1580
 */
1581
function give_hide_payment_notes( $query ) {
1582
	if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.1', '>=' ) ) {
1583
		$types = isset( $query->query_vars['type__not_in'] ) ? $query->query_vars['type__not_in'] : array();
1584
		if ( ! is_array( $types ) ) {
1585
			$types = array( $types );
1586
		}
1587
		$types[]                           = 'give_payment_note';
1588
		$query->query_vars['type__not_in'] = $types;
1589
	}
1590
}
1591
1592
add_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1593
1594
/**
1595
 * Exclude notes (comments) on give_payment post type from showing in Recent Comments widgets
1596
 *
1597
 * @param array  $clauses          Comment clauses for comment query.
1598
 * @param object $wp_comment_query WordPress Comment Query Object.
1599
 *
1600
 * @since 1.0
1601
 *
1602
 * @return array $clauses Updated comment clauses.
1603
 */
1604
function give_hide_payment_notes_pre_41( $clauses, $wp_comment_query ) {
0 ignored issues
show
Unused Code introduced by
The parameter $wp_comment_query 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...
1605
	if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.1', '<' ) ) {
1606
		$clauses['where'] .= ' AND comment_type != "give_payment_note"';
1607
	}
1608
1609
	return $clauses;
1610
}
1611
1612
add_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10, 2 );
1613
1614
1615
/**
1616
 * Exclude notes (comments) on give_payment post type from showing in comment feeds
1617
 *
1618
 * @param string $where
1619
 * @param object $wp_comment_query WordPress Comment Query Object.
1620
 *
1621
 * @since 1.0
1622
 *
1623
 * @return string $where
1624
 */
1625
function give_hide_payment_notes_from_feeds( $where, $wp_comment_query ) {
0 ignored issues
show
Unused Code introduced by
The parameter $wp_comment_query 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...
1626
	global $wpdb;
1627
1628
	$where .= $wpdb->prepare( ' AND comment_type != %s', 'give_payment_note' );
1629
1630
	return $where;
1631
}
1632
1633
add_filter( 'comment_feed_where', 'give_hide_payment_notes_from_feeds', 10, 2 );
1634
1635
1636
/**
1637
 * Remove Give Comments from the wp_count_comments function
1638
 *
1639
 * @param array $stats   (empty from core filter).
1640
 * @param int   $post_id Post ID.
1641
 *
1642
 * @access public
1643
 * @since  1.0
1644
 *
1645
 * @return array|object Array of comment counts.
1646
 */
1647
function give_remove_payment_notes_in_comment_counts( $stats, $post_id ) {
1648
	global $wpdb, $pagenow;
1649
1650
	if ( 'index.php' != $pagenow ) {
1651
		return $stats;
1652
	}
1653
1654
	$post_id = (int) $post_id;
1655
1656
	if ( apply_filters( 'give_count_payment_notes_in_comments', false ) ) {
1657
		return $stats;
1658
	}
1659
1660
	$stats = Give_Cache::get_group( "comments-{$post_id}", 'counts' );
1661
1662
	if ( ! is_null( $stats ) ) {
1663
		return $stats;
1664
	}
1665
1666
	$where = 'WHERE comment_type != "give_payment_note"';
1667
1668
	if ( $post_id > 0 ) {
1669
		$where .= $wpdb->prepare( ' AND comment_post_ID = %d', $post_id );
1670
	}
1671
1672
	$count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} {$where} GROUP BY comment_approved", ARRAY_A );
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...
1673
1674
	$total    = 0;
1675
	$approved = array(
1676
		'0'            => 'moderated',
0 ignored issues
show
introduced by
Detected usage of 0, possible slow query.
Loading history...
1677
		'1'            => 'approved',
1678
		'spam'         => 'spam',
1679
		'trash'        => 'trash',
1680
		'post-trashed' => 'post-trashed',
1681
	);
1682
	foreach ( (array) $count as $row ) {
1683
		// Don't count post-trashed toward totals.
1684
		if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] ) {
1685
			$total += $row['num_comments'];
1686
		}
1687
		if ( isset( $approved[ $row['comment_approved'] ] ) ) {
1688
			$stats[ $approved[ $row['comment_approved'] ] ] = $row['num_comments'];
1689
		}
1690
	}
1691
1692
	$stats['total_comments'] = $total;
1693
	foreach ( $approved as $key ) {
1694
		if ( empty( $stats[ $key ] ) ) {
1695
			$stats[ $key ] = 0;
1696
		}
1697
	}
1698
1699
	$stats = (object) $stats;
1700
	Give_Cache::set_group( "comments-{$post_id}", $stats, 'counts' );
1701
1702
	return $stats;
1703
}
1704
1705
add_filter( 'wp_count_comments', 'give_remove_payment_notes_in_comment_counts', 10, 2 );
1706
1707
1708
/**
1709
 * Filter where older than one week
1710
 *
1711
 * @param string $where Where clause.
1712
 *
1713
 * @access public
1714
 * @since  1.0
1715
 *
1716
 * @return string $where Modified where clause.
1717
 */
1718
function give_filter_where_older_than_week( $where = '' ) {
1719
	// Payments older than one week.
1720
	$start = date( 'Y-m-d', strtotime( '-7 days' ) );
1721
	$where .= " AND post_date <= '{$start}'";
1722
1723
	return $where;
1724
}
1725
1726
1727
/**
1728
 * Get Payment Form ID.
1729
 *
1730
 * Retrieves the form title and appends the level name if present.
1731
 *
1732
 * @param int|Give_Payment $donation Donation Data Object.
1733
 * @param array            $args     a. only_level = If set to true will only return the level name if multi-level enabled.
1734
 *                                   b. separator  = The separator between the Form Title and the Donation Level.
1735
 *
1736
 * @since 1.5
1737
 *
1738
 * @return string $form_title Returns the full title if $only_level is false, otherwise returns the levels title.
1739
 */
1740
function give_get_donation_form_title( $donation, $args = array() ) {
1741
1742
	if ( ! $donation instanceof Give_Payment ) {
1743
		$donation = new Give_Payment( $donation );
1744
	}
1745
1746
	if( ! $donation->ID ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
1747
		return '';
1748
	}
1749
1750
	$defaults = array(
1751
		'only_level' => false,
1752
		'separator'  => '',
1753
	);
1754
1755
	$args = wp_parse_args( $args, $defaults );
1756
1757
	$form_id     = $donation->form_id;
1758
	$price_id    = $donation->price_id;
1759
	$form_title  = $donation->form_title;
1760
	$only_level  = $args['only_level'];
1761
	$separator   = $args['separator'];
1762
	$level_label = '';
1763
1764
	$cache_key = Give_Cache::get_key(
1765
		'give_forms',
1766
		array(
1767
			$form_id,
1768
			$price_id,
1769
			$form_title,
1770
			$only_level,
1771
			$separator
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
1772
		)
1773
		, false
1774
	);
1775
1776
	$form_title_html = Give_Cache::get_db_query( $cache_key );
1777
1778
	if ( is_null( $form_title_html ) ) {
1779
		if ( true === $only_level ) {
1780
			$form_title = '';
1781
		}
1782
1783
		$form_title_html = $form_title;
1784
1785
		if ( 'custom' === $price_id ) {
1786
			$custom_amount_text = give_get_meta( $form_id, '_give_custom_amount_text', true );
1787
			$level_label        = ! empty( $custom_amount_text ) ? $custom_amount_text : __( 'Custom Amount', 'give' );
1788
		} elseif ( give_has_variable_prices( $form_id ) ) {
1789
			$level_label = give_get_price_option_name( $form_id, $price_id );
1790
		}
1791
1792
		// Only add separator if there is a form title.
1793
		if (
1794
			! empty( $form_title_html ) &&
1795
			! empty( $level_label )
1796
		) {
1797
			$form_title_html .= " {$separator} ";
1798
		}
1799
1800
		$form_title_html .= "<span class=\"donation-level-text-wrap\">{$level_label}</span>";
1801
		Give_Cache::set_db_query( $cache_key, $form_title_html );
1802
	}
1803
1804
	/**
1805
	 * Filter form title with level html
1806
	 *
1807
	 * @since 1.0
1808
	 */
1809
	return apply_filters( 'give_get_donation_form_title', $form_title_html, $donation->payment_meta, $donation );
1810
}
1811
1812
/**
1813
 * Get Price ID
1814
 *
1815
 * Retrieves the Price ID when provided a proper form ID and price (donation) total
1816
 *
1817
 * @param int    $form_id Form ID.
1818
 * @param string $price   Price ID.
1819
 *
1820
 * @return string $price_id
1821
 */
1822
function give_get_price_id( $form_id, $price ) {
1823
	$price_id = null;
1824
1825
	if ( give_has_variable_prices( $form_id ) ) {
1826
1827
		$levels = give_get_meta( $form_id, '_give_donation_levels', true );
1828
1829
		foreach ( $levels as $level ) {
1830
1831
			$level_amount = give_maybe_sanitize_amount( $level['_give_amount'] );
1832
1833
			// Check that this indeed the recurring price.
1834
			if ( $level_amount == $price ) {
1835
1836
				$price_id = $level['_give_id']['level_id'];
1837
				break;
1838
1839
			}
1840
		}
1841
1842
		if ( is_null( $price_id ) && give_is_custom_price_mode( $form_id ) ) {
1843
			$price_id = 'custom';
1844
		}
1845
	}
1846
1847
	// Price ID must be numeric or string.
1848
	$price_id = ! is_numeric( $price_id ) && ! is_string( $price_id ) ? 0 : $price_id;
1849
1850
	return $price_id;
1851
}
1852
1853
/**
1854
 * Get/Print give form dropdown html
1855
 *
1856
 * This function is wrapper to public method forms_dropdown of Give_HTML_Elements class to get/print form dropdown html.
1857
 * Give_HTML_Elements is defined in includes/class-give-html-elements.php.
1858
 *
1859
 * @param array $args Arguments for form dropdown.
1860
 * @param bool  $echo This parameter decides if print form dropdown html output or not.
1861
 *
1862
 * @since 1.6
1863
 *
1864
 * @return string
1865
 */
1866
function give_get_form_dropdown( $args = array(), $echo = false ) {
1867
	$form_dropdown_html = Give()->html->forms_dropdown( $args );
1868
1869
	if ( ! $echo ) {
1870
		return $form_dropdown_html;
1871
	}
1872
1873
	echo $form_dropdown_html;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$form_dropdown_html'
Loading history...
1874
}
1875
1876
/**
1877
 * Get/Print give form variable price dropdown html
1878
 *
1879
 * @param array $args Arguments for form dropdown.
1880
 * @param bool  $echo This parameter decide if print form dropdown html output or not.
1881
 *
1882
 * @since 1.6
1883
 *
1884
 * @return string|bool
1885
 */
1886
function give_get_form_variable_price_dropdown( $args = array(), $echo = false ) {
1887
1888
	// Check for give form id.
1889
	if ( empty( $args['id'] ) ) {
1890
		return false;
1891
	}
1892
1893
	$form = new Give_Donate_Form( $args['id'] );
1894
1895
	// Check if form has variable prices or not.
1896
	if ( ! $form->ID || ! $form->has_variable_prices() ) {
1897
		return false;
1898
	}
1899
1900
	$variable_prices        = $form->get_prices();
1901
	$variable_price_options = array();
1902
1903
	// Check if multi donation form support custom donation or not.
1904
	if ( $form->is_custom_price_mode() ) {
1905
		$variable_price_options['custom'] = _x( 'Custom', 'custom donation dropdown item', 'give' );
1906
	}
1907
1908
	// Get variable price and ID from variable price array.
1909
	foreach ( $variable_prices as $variable_price ) {
1910
		$variable_price_options[ $variable_price['_give_id']['level_id'] ] = ! empty( $variable_price['_give_text'] ) ? $variable_price['_give_text'] : give_currency_filter( give_format_amount( $variable_price['_give_amount'], array( 'sanitize' => false ) ) );
1911
	}
1912
1913
	// Update options.
1914
	$args = array_merge( $args, array(
1915
		'options' => $variable_price_options,
1916
	) );
1917
1918
	// Generate select html.
1919
	$form_dropdown_html = Give()->html->select( $args );
1920
1921
	if ( ! $echo ) {
1922
		return $form_dropdown_html;
1923
	}
1924
1925
	echo $form_dropdown_html;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$form_dropdown_html'
Loading history...
1926
}
1927
1928
/**
1929
 * Get the price_id from the payment meta.
1930
 *
1931
 * Some gateways use `give_price_id` and others were using just `price_id`;
1932
 * This checks for the difference and falls back to retrieving it from the form as a last resort.
1933
 *
1934
 * @param array $payment_meta Payment Meta.
1935
 *
1936
 * @since 1.8.6
1937
 *
1938
 * @return string
1939
 */
1940
function give_get_payment_meta_price_id( $payment_meta ) {
1941
1942
	if ( isset( $payment_meta['give_price_id'] ) ) {
1943
		$price_id = $payment_meta['give_price_id'];
1944
	} elseif ( isset( $payment_meta['price_id'] ) ) {
1945
		$price_id = $payment_meta['price_id'];
1946
	} else {
1947
		$price_id = give_get_price_id( $payment_meta['give_form_id'], $payment_meta['price'] );
1948
	}
1949
1950
	return apply_filters( 'give_get_payment_meta_price_id', $price_id );
1951
1952
}
1953