Test Failed
Push — issues/1944 ( f13954...e5d7bc )
by Ravinder
05:26
created

functions.php ➔ give_count_payments()   F

Complexity

Conditions 37
Paths > 20000

Size

Total Lines 170
Code Lines 97

Duplication

Lines 12
Ratio 7.06 %

Importance

Changes 0
Metric Value
cc 37
eloc 97
nc 1476722
nop 1
dl 12
loc 170
rs 2
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 ) {
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...
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
415
	global $wpdb;
416
417
	$defaults = array(
418
		'user'       => null,
419
		's'          => null,
420
		'start-date' => null,
421
		'end-date'   => null,
422
		'form_id'    => null,
423
	);
424
425
	$args = wp_parse_args( $args, $defaults );
426
427
	$select = 'SELECT p.post_status,count( * ) AS num_posts';
428
	$join   = '';
429
	$where  = "WHERE p.post_type = 'give_payment' AND p.post_status IN ('" . implode( "','", give_get_payment_status_keys() ) . "')";
430
431
	// Count payments for a specific user.
432
	if ( ! empty( $args['user'] ) ) {
433
434
		if ( is_email( $args['user'] ) ) {
435
			$field = 'email';
436
		} elseif ( is_numeric( $args['user'] ) ) {
437
			$field = 'id';
438
		} else {
439
			$field = '';
440
		}
441
442
		$join = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
443
444
		if ( ! empty( $field ) ) {
445
			$where .= "
446
				AND m.meta_key = '_give_payment_user_{$field}'
447
				AND m.meta_value = '{$args['user']}'";
448
		}
449
	} elseif ( ! empty( $args['donor'] ) ) {
450
451
		$join  = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
452
		$where .= "
453
			AND m.meta_key = '_give_payment_customer_id'
454
			AND m.meta_value = '{$args['donor']}'";
455
456
		// Count payments for a search.
457
	} elseif ( ! empty( $args['s'] ) ) {
458
459
		if ( is_email( $args['s'] ) || strlen( $args['s'] ) == 32 ) {
460
461
			if ( is_email( $args['s'] ) ) {
462
				$field = '_give_payment_user_email';
463
			} else {
464
				$field = '_give_payment_purchase_key';
465
			}
466
467
			$join  = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
468
			$where .= $wpdb->prepare( '
469
                AND m.meta_key = %s
470
                AND m.meta_value = %s', $field, $args['s'] );
471
472
		} elseif ( '#' == substr( $args['s'], 0, 1 ) ) {
473
474
			$search = str_replace( '#:', '', $args['s'] );
475
			$search = str_replace( '#', '', $search );
476
477
			$select = 'SELECT p.post_status,count( * ) AS num_posts ';
478
			$join   = '';
479
			$where  = $wpdb->prepare( 'WHERE p.post_type=%s  AND p.ID = %d ', 'give_payment', $search );
480
481
		} elseif ( is_numeric( $args['s'] ) ) {
482
483
			$join  = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
484
			$where .= $wpdb->prepare( "
485
				AND m.meta_key = '_give_payment_user_id'
486
				AND m.meta_value = %d", $args['s'] );
487
488
		} else {
489
			$search = $wpdb->esc_like( $args['s'] );
490
			$search = '%' . $search . '%';
491
492
			$where .= $wpdb->prepare( 'AND ((p.post_title LIKE %s) OR (p.post_content LIKE %s))', $search, $search );
493
		}// End if().
494
	}// End if().
495
496
	if ( ! empty( $args['form_id'] ) && is_numeric( $args['form_id'] ) ) {
497
498
		$join  = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
499
		$where .= $wpdb->prepare( '
500
                AND m.meta_key = %s
501
                AND m.meta_value = %s', '_give_payment_form_id', $args['form_id'] );
502
	}
503
504
	// Limit payments count by date.
505
	if ( ! empty( $args['start-date'] ) && false !== strpos( $args['start-date'], '/' ) ) {
506
507
		$date_parts = explode( '/', $args['start-date'] );
508
		$month      = ! empty( $date_parts[0] ) && is_numeric( $date_parts[0] ) ? $date_parts[0] : 0;
509
		$day        = ! empty( $date_parts[1] ) && is_numeric( $date_parts[1] ) ? $date_parts[1] : 0;
510
		$year       = ! empty( $date_parts[2] ) && is_numeric( $date_parts[2] ) ? $date_parts[2] : 0;
511
512
		$is_date = checkdate( $month, $day, $year );
513 View Code Duplication
		if ( false !== $is_date ) {
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...
514
515
			$date  = new DateTime( $args['start-date'] );
516
			$where .= $wpdb->prepare( " AND p.post_date >= '%s'", $date->format( 'Y-m-d' ) );
517
518
		}
519
520
		// Fixes an issue with the payments list table counts when no end date is specified (with stats class).
521
		if ( empty( $args['end-date'] ) ) {
522
			$args['end-date'] = $args['start-date'];
523
		}
524
	}
525
526
	if ( ! empty( $args['end-date'] ) && false !== strpos( $args['end-date'], '/' ) ) {
527
528
		$date_parts = explode( '/', $args['end-date'] );
529
530
		$month = ! empty( $date_parts[0] ) ? $date_parts[0] : 0;
531
		$day   = ! empty( $date_parts[1] ) ? $date_parts[1] : 0;
532
		$year  = ! empty( $date_parts[2] ) ? $date_parts[2] : 0;
533
534
		$is_date = checkdate( $month, $day, $year );
535 View Code Duplication
		if ( false !== $is_date ) {
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...
536
537
			$date  = new DateTime( $args['end-date'] );
538
			$where .= $wpdb->prepare( " AND p.post_date <= '%s'", $date->format( 'Y-m-d' ) );
539
540
		}
541
	}
542
543
	$query = "$select
544
		FROM $wpdb->posts p
545
		$join
546
		$where
547
		GROUP BY p.post_status
548
	";
549
550
	$cache_key = md5( $query );
551
552
	$count = wp_cache_get( $cache_key, 'counts' );
553
	if ( false !== $count ) {
554
		return $count;
555
	}
556
557
	$count = $wpdb->get_results( $query, ARRAY_A );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
558
559
	$stats    = array();
560
	$statuses = get_post_stati();
561
	if ( isset( $statuses['private'] ) && empty( $args['s'] ) ) {
562
		unset( $statuses['private'] );
563
	}
564
565
	foreach ( $statuses as $state ) {
566
		$stats[ $state ] = 0;
567
	}
568
569
	foreach ( (array) $count as $row ) {
570
571
		if ( 'private' == $row['post_status'] && empty( $args['s'] ) ) {
572
			continue;
573
		}
574
575
		$stats[ $row['post_status'] ] = $row['num_posts'];
576
	}
577
578
	$stats = (object) $stats;
579
	wp_cache_set( $cache_key, $stats, 'counts' );
580
581
	return $stats;
582
}
583
584
585
/**
586
 * Check For Existing Payment
587
 *
588
 * @param  int $payment_id Payment ID.
589
 *
590
 * @since  1.0
591
 *
592
 * @return bool $exists True if payment exists, false otherwise.
593
 */
594
function give_check_for_existing_payment( $payment_id ) {
595
	$exists  = false;
596
	$payment = new Give_Payment( $payment_id );
597
598
	if ( $payment_id === $payment->ID && 'publish' === $payment->status ) {
599
		$exists = true;
600
	}
601
602
	return $exists;
603
}
604
605
/**
606
 * Get Payment Status
607
 *
608
 * @param WP_Post|Give_Payment|int $payment      Payment object or payment ID.
609
 * @param bool                     $return_label Whether to return the translated status label instead of status value.
610
 *                                               Default false.
611
 *
612
 * @since 1.0
613
 *
614
 * @return bool|mixed True if payment status exists, false otherwise.
615
 */
616
function give_get_payment_status( $payment, $return_label = false ) {
617
618
	if ( is_numeric( $payment ) ) {
619
620
		$payment = new Give_Payment( $payment );
621
622
		if ( ! $payment->ID > 0 ) {
623
			return false;
624
		}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
625
626
	}
627
628
	if ( ! is_object( $payment ) || ! isset( $payment->post_status ) ) {
629
		return false;
630
	}
631
632
	$statuses = give_get_payment_statuses();
633
634
	if ( ! is_array( $statuses ) || empty( $statuses ) ) {
635
		return false;
636
	}
637
638
	// Get payment object if not already given.
639
	$payment = $payment instanceof Give_Payment ? $payment : new Give_Payment( $payment->ID );
640
641
	if ( array_key_exists( $payment->status, $statuses ) ) {
642
		if ( true === $return_label ) {
643
			// Return translated status label.
644
			return $statuses[ $payment->status ];
645
		} else {
646
			// Account that our 'publish' status is labeled 'Complete'
647
			$post_status = 'publish' === $payment->status ? 'Complete' : $payment->post_status;
648
649
			// Make sure we're matching cases, since they matter
650
			return array_search( strtolower( $post_status ), array_map( 'strtolower', $statuses ) );
651
		}
652
	}
653
654
	return false;
655
}
656
657
/**
658
 * Retrieves all available statuses for payments.
659
 *
660
 * @since  1.0
661
 *
662
 * @return array $payment_status All the available payment statuses.
663
 */
664
function give_get_payment_statuses() {
665
	$payment_statuses = array(
666
		'pending'     => __( 'Pending', 'give' ),
667
		'publish'     => __( 'Complete', 'give' ),
668
		'refunded'    => __( 'Refunded', 'give' ),
669
		'failed'      => __( 'Failed', 'give' ),
670
		'cancelled'   => __( 'Cancelled', 'give' ),
671
		'abandoned'   => __( 'Abandoned', 'give' ),
672
		'preapproval' => __( 'Pre-Approved', 'give' ),
673
		'processing'  => __( 'Processing', 'give' ),
674
		'revoked'     => __( 'Revoked', 'give' ),
675
	);
676
677
	return apply_filters( 'give_payment_statuses', $payment_statuses );
678
}
679
680
/**
681
 * Get Payment Status Keys
682
 *
683
 * Retrieves keys for all available statuses for payments
684
 *
685
 * @since 1.0
686
 *
687
 * @return array $payment_status All the available payment statuses.
688
 */
689
function give_get_payment_status_keys() {
690
	$statuses = array_keys( give_get_payment_statuses() );
691
	asort( $statuses );
692
693
	return array_values( $statuses );
694
}
695
696
/**
697
 * Get Earnings By Date
698
 *
699
 * @param int $day       Day number. Default is null.
700
 * @param int $month_num Month number. Default is null.
701
 * @param int $year      Year number. Default is null.
702
 * @param int $hour      Hour number. Default is null.
703
 *
704
 * @since 1.0
705
 *
706
 * @return int $earnings Earnings
707
 */
708
function give_get_earnings_by_date( $day = null, $month_num, $year = null, $hour = null ) {
709
	// This is getting deprecated soon. Use Give_Payment_Stats with the get_earnings() method instead.
710
711
	global $wpdb;
712
	$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...
713
714
	$args = array(
715
		'post_type'              => 'give_payment',
716
		'nopaging'               => true,
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set nopaging to true ever.
Loading history...
717
		'year'                   => $year,
718
		'monthnum'               => $month_num,
719
		'post_status'            => array( 'publish' ),
720
		'fields'                 => 'ids',
721
		'update_post_term_cache' => false,
722
	);
723
	if ( ! empty( $day ) ) {
724
		$args['day'] = $day;
725
	}
726
727
	if ( isset( $hour ) ) {
728
		$args['hour'] = $hour;
729
	}
730
731
	$args = apply_filters( 'give_get_earnings_by_date_args', $args );
732
	$key  = Give_Cache::get_key( 'give_stats', $args );
733
734 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...
735
		$earnings = false;
736
	} else {
737
		$earnings = Give_Cache::get( $key );
738
	}
739
740
	if ( false === $earnings ) {
741
		$donations = get_posts( $args );
742
		$earnings  = 0;
743
		if ( $donations ) {
744
			$donations      = implode( ',', $donations );
745
			$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...
746
747
			/**
748
			 * Filter The earnings by dates.
749
			 *
750
			 * @since 1.8.17
751
			 *
752
			 * @param float $earning_totals Total earnings between the dates.
753
			 * @param array $donations      Donations lists.
754
			 * @param array $args           Donation query args.
755
			 */
756
			$earnings = apply_filters( 'give_get_earnings_by_date', $earning_totals, $donations, $args );
757
		}
758
		// Cache the results for one hour.
759
		Give_Cache::set( $key, $earnings, HOUR_IN_SECONDS );
760
	}
761
762
	return round( $earnings, 2 );
763
}
764
765
/**
766
 * Get Donations (sales) By Date
767
 *
768
 * @param int $day       Day number. Default is null.
769
 * @param int $month_num Month number. Default is null.
770
 * @param int $year      Year number. Default is null.
771
 * @param int $hour      Hour number. Default is null.
772
 *
773
 * @since 1.0
774
 *
775
 * @return int $count Sales
776
 */
777
function give_get_sales_by_date( $day = null, $month_num = null, $year = null, $hour = null ) {
778
779
	// This is getting deprecated soon. Use Give_Payment_Stats with the get_sales() method instead.
780
	$args = array(
781
		'post_type'              => 'give_payment',
782
		'nopaging'               => true,
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set nopaging to true ever.
Loading history...
783
		'year'                   => $year,
784
		'fields'                 => 'ids',
785
		'post_status'            => array( 'publish' ),
786
		'update_post_meta_cache' => false,
787
		'update_post_term_cache' => false,
788
	);
789
790
	$show_free = apply_filters( 'give_sales_by_date_show_free', true, $args );
791
792
	if ( false === $show_free ) {
793
		$args['meta_query'] = array(
0 ignored issues
show
introduced by
Detected usage of meta_query, possible slow query.
Loading history...
794
			array(
795
				'key'     => '_give_payment_total',
796
				'value'   => 0,
797
				'compare' => '>',
798
				'type'    => 'NUMERIC',
799
			),
800
		);
801
	}
802
803
	if ( ! empty( $month_num ) ) {
804
		$args['monthnum'] = $month_num;
805
	}
806
807
	if ( ! empty( $day ) ) {
808
		$args['day'] = $day;
809
	}
810
811
	if ( isset( $hour ) ) {
812
		$args['hour'] = $hour;
813
	}
814
815
	$args = apply_filters( 'give_get_sales_by_date_args', $args );
816
817
	$key = Give_Cache::get_key( 'give_stats', $args );
818
819 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...
820
		$count = false;
821
	} else {
822
		$count = Give_Cache::get( $key );
823
	}
824
825
	if ( false === $count ) {
826
		$donations = new WP_Query( $args );
827
		$count     = (int) $donations->post_count;
828
		// Cache the results for one hour.
829
		Give_Cache::set( $key, $count, HOUR_IN_SECONDS );
830
	}
831
832
	return $count;
833
}
834
835
/**
836
 * Checks whether a payment has been marked as complete.
837
 *
838
 * @param int $payment_id Payment ID to check against.
839
 *
840
 * @since 1.0
841
 *
842
 * @return bool $ret True if complete, false otherwise.
843
 */
844
function give_is_payment_complete( $payment_id ) {
845
	$payment = new Give_Payment( $payment_id );
846
847
	$ret = false;
848
849
	if ( $payment->ID > 0 ) {
850
851
		if ( (int) $payment_id === (int) $payment->ID && 'publish' == $payment->status ) {
852
			$ret = true;
853
		}
854
	}
855
856
	return apply_filters( 'give_is_payment_complete', $ret, $payment_id, $payment->post_status );
857
}
858
859
/**
860
 * Get Total Donations.
861
 *
862
 * @since 1.0
863
 *
864
 * @return int $count Total number of donations.
865
 */
866
function give_get_total_donations() {
867
868
	$payments = give_count_payments();
869
870
	return $payments->publish;
871
}
872
873
/**
874
 * Get Total Earnings
875
 *
876
 * @param bool $recalculate Recalculate earnings forcefully.
877
 *
878
 * @since 1.0
879
 *
880
 * @return float $total Total earnings.
881
 */
882
function give_get_total_earnings( $recalculate = false ) {
883
884
	$total      = get_option( 'give_earnings_total', 0 );
885
	$meta_table = __give_v20_bc_table_details( 'payment' );
886
887
	// Calculate total earnings.
888
	if ( ! $total || $recalculate ) {
889
		global $wpdb;
890
891
		$total = (float) 0;
892
893
		$args = apply_filters( 'give_get_total_earnings_args', array(
894
			'offset' => 0,
895
			'number' => - 1,
896
			'status' => array( 'publish' ),
897
			'fields' => 'ids',
898
		) );
899
900
		$payments = give_get_payments( $args );
901
		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...
902
903
			/**
904
			 * If performing a donation, we need to skip the very last payment in the database,
905
			 * since it calls give_increase_total_earnings() on completion,
906
			 * which results in duplicated earnings for the very first donation.
907
			 */
908
			if ( did_action( 'give_update_payment_status' ) ) {
909
				array_pop( $payments );
910
			}
911
912
			if ( ! empty( $payments ) ) {
913
				$payments = implode( ',', $payments );
914
				$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...
915
			}
916
		}
917
918
		update_option( 'give_earnings_total', $total, 'no' );
919
	}
920
921
	if ( $total < 0 ) {
922
		$total = 0; // Don't ever show negative earnings.
923
	}
924
925
	return apply_filters( 'give_total_earnings', round( $total, give_get_price_decimals() ), $total );
926
}
927
928
/**
929
 * Increase the Total Earnings
930
 *
931
 * @param int $amount The amount you would like to increase the total earnings by. Default is 0.
932
 *
933
 * @since 1.0
934
 *
935
 * @return float $total Total earnings.
936
 */
937
function give_increase_total_earnings( $amount = 0 ) {
938
	$total = give_get_total_earnings();
939
	$total += $amount;
940
	update_option( 'give_earnings_total', $total );
941
942
	return $total;
943
}
944
945
/**
946
 * Decrease the Total Earnings
947
 *
948
 * @param int $amount The amount you would like to decrease the total earnings by.
949
 *
950
 * @since 1.0
951
 *
952
 * @return float $total Total earnings.
953
 */
954
function give_decrease_total_earnings( $amount = 0 ) {
955
	$total = give_get_total_earnings();
956
	$total -= $amount;
957
	if ( $total < 0 ) {
958
		$total = 0;
959
	}
960
	update_option( 'give_earnings_total', $total );
961
962
	return $total;
963
}
964
965
/**
966
 * Get Payment Meta for a specific Payment
967
 *
968
 * @param int    $payment_id Payment ID.
969
 * @param string $meta_key   The meta key to pull.
970
 * @param bool   $single     Pull single meta entry or as an object.
971
 *
972
 * @since 1.0
973
 *
974
 * @return mixed $meta Payment Meta.
975
 */
976
function give_get_payment_meta( $payment_id = 0, $meta_key = '_give_payment_meta', $single = true ) {
977
	$payment = new Give_Payment( $payment_id );
978
979
	return $payment->get_meta( $meta_key, $single );
980
}
981
982
/**
983
 * Update the meta for a payment
984
 *
985
 * @param  int    $payment_id Payment ID.
986
 * @param  string $meta_key   Meta key to update.
987
 * @param  string $meta_value Value to update to.
988
 * @param  string $prev_value Previous value.
989
 *
990
 * @return mixed Meta ID if successful, false if unsuccessful.
991
 */
992
function give_update_payment_meta( $payment_id = 0, $meta_key = '', $meta_value = '', $prev_value = '' ) {
993
	$payment = new Give_Payment( $payment_id );
994
995
	return $payment->update_meta( $meta_key, $meta_value, $prev_value );
996
}
997
998
/**
999
 * Get the user_info Key from Payment Meta
1000
 *
1001
 * @param int $payment_id Payment ID.
1002
 *
1003
 * @since 1.0
1004
 *
1005
 * @return array $user_info User Info Meta Values.
1006
 */
1007
function give_get_payment_meta_user_info( $payment_id ) {
1008
	$payment = new Give_Payment( $payment_id );
1009
1010
	return $payment->user_info;
1011
}
1012
1013
/**
1014
 * Get the donations Key from Payment Meta
1015
 *
1016
 * Retrieves the form_id from a (Previously titled give_get_payment_meta_donations)
1017
 *
1018
 * @param int $payment_id Payment ID.
1019
 *
1020
 * @since 1.0
1021
 *
1022
 * @return int $form_id Form ID.
1023
 */
1024
function give_get_payment_form_id( $payment_id ) {
1025
	$payment = new Give_Payment( $payment_id );
1026
1027
	return $payment->form_id;
1028
}
1029
1030
/**
1031
 * Get the user email associated with a payment
1032
 *
1033
 * @param int $payment_id Payment ID.
1034
 *
1035
 * @since 1.0
1036
 *
1037
 * @return string $email User email.
1038
 */
1039
function give_get_payment_user_email( $payment_id ) {
1040
	$payment = new Give_Payment( $payment_id );
1041
1042
	return $payment->email;
1043
}
1044
1045
/**
1046
 * Is the payment provided associated with a user account
1047
 *
1048
 * @param int $payment_id The payment ID.
1049
 *
1050
 * @since 1.3
1051
 *
1052
 * @return bool $is_guest_payment If the payment is associated with a user (false) or not (true)
1053
 */
1054
function give_is_guest_payment( $payment_id ) {
1055
	$payment_user_id  = give_get_payment_user_id( $payment_id );
1056
	$is_guest_payment = ! empty( $payment_user_id ) && $payment_user_id > 0 ? false : true;
1057
1058
	return (bool) apply_filters( 'give_is_guest_payment', $is_guest_payment, $payment_id );
1059
}
1060
1061
/**
1062
 * Get the user ID associated with a payment
1063
 *
1064
 * @param int $payment_id Payment ID.
1065
 *
1066
 * @since 1.3
1067
 *
1068
 * @return int $user_id User ID.
1069
 */
1070
function give_get_payment_user_id( $payment_id ) {
1071
	$payment = new Give_Payment( $payment_id );
1072
1073
	return $payment->user_id;
1074
}
1075
1076
/**
1077
 * Get the donor ID associated with a payment.
1078
 *
1079
 * @param int $payment_id Payment ID.
1080
 *
1081
 * @since 1.0
1082
 *
1083
 * @return int $payment->customer_id Donor ID.
1084
 */
1085
function give_get_payment_donor_id( $payment_id ) {
1086
	$payment = new Give_Payment( $payment_id );
1087
1088
	return $payment->customer_id;
1089
}
1090
1091
/**
1092
 * Get the IP address used to make a donation
1093
 *
1094
 * @param int $payment_id Payment ID.
1095
 *
1096
 * @since 1.0
1097
 *
1098
 * @return string $ip User IP.
1099
 */
1100
function give_get_payment_user_ip( $payment_id ) {
1101
	$payment = new Give_Payment( $payment_id );
1102
1103
	return $payment->ip;
1104
}
1105
1106
/**
1107
 * Get the date a payment was completed
1108
 *
1109
 * @param int $payment_id Payment ID.
1110
 *
1111
 * @since 1.0
1112
 *
1113
 * @return string $date The date the payment was completed.
1114
 */
1115
function give_get_payment_completed_date( $payment_id = 0 ) {
1116
	$payment = new Give_Payment( $payment_id );
1117
1118
	return $payment->completed_date;
1119
}
1120
1121
/**
1122
 * Get the gateway associated with a payment
1123
 *
1124
 * @param int $payment_id Payment ID.
1125
 *
1126
 * @since 1.0
1127
 *
1128
 * @return string $gateway Gateway.
1129
 */
1130
function give_get_payment_gateway( $payment_id ) {
1131
	$payment = new Give_Payment( $payment_id );
1132
1133
	return $payment->gateway;
1134
}
1135
1136
/**
1137
 * Get the currency code a payment was made in
1138
 *
1139
 * @param int $payment_id Payment ID.
1140
 *
1141
 * @since 1.0
1142
 *
1143
 * @return string $currency The currency code.
1144
 */
1145
function give_get_payment_currency_code( $payment_id = 0 ) {
1146
	$payment = new Give_Payment( $payment_id );
1147
1148
	return $payment->currency;
1149
}
1150
1151
/**
1152
 * Get the currency name a payment was made in
1153
 *
1154
 * @param int $payment_id Payment ID.
1155
 *
1156
 * @since 1.0
1157
 *
1158
 * @return string $currency The currency name.
1159
 */
1160
function give_get_payment_currency( $payment_id = 0 ) {
1161
	$currency = give_get_payment_currency_code( $payment_id );
1162
1163
	return apply_filters( 'give_payment_currency', give_get_currency_name( $currency ), $payment_id );
1164
}
1165
1166
/**
1167
 * Get the key for a donation
1168
 *
1169
 * @param int $payment_id Payment ID.
1170
 *
1171
 * @since 1.0
1172
 *
1173
 * @return string $key Donation key.
1174
 */
1175
function give_get_payment_key( $payment_id = 0 ) {
1176
	$payment = new Give_Payment( $payment_id );
1177
1178
	return $payment->key;
1179
}
1180
1181
/**
1182
 * Get the payment order number
1183
 *
1184
 * This will return the payment ID if sequential order numbers are not enabled or the order number does not exist
1185
 *
1186
 * @param int $payment_id Payment ID.
1187
 *
1188
 * @since 1.0
1189
 *
1190
 * @return string $number Payment order number.
1191
 */
1192
function give_get_payment_number( $payment_id = 0 ) {
1193
	$payment = new Give_Payment( $payment_id );
1194
1195
	return $payment->number;
1196
}
1197
1198
/**
1199
 * Formats the payment number with the prefix and postfix
1200
 *
1201
 * @param int $number The payment number to format.
1202
 *
1203
 * @since 1.3
1204
 *
1205
 * @return string      The formatted payment number.
1206
 */
1207
function give_format_payment_number( $number ) {
1208
1209
	if ( ! give_get_option( 'enable_sequential' ) ) {
1210
		return $number;
1211
	}
1212
1213
	if ( ! is_numeric( $number ) ) {
1214
		return $number;
1215
	}
1216
1217
	$prefix  = give_get_option( 'sequential_prefix' );
1218
	$number  = absint( $number );
1219
	$postfix = give_get_option( 'sequential_postfix' );
1220
1221
	$formatted_number = $prefix . $number . $postfix;
1222
1223
	return apply_filters( 'give_format_payment_number', $formatted_number, $prefix, $number, $postfix );
1224
}
1225
1226
/**
1227
 * Gets the next available order number
1228
 *
1229
 * This is used when inserting a new payment
1230
 *
1231
 * @since 1.0
1232
 *
1233
 * @return string $number The next available payment number.
1234
 */
1235
function give_get_next_payment_number() {
1236
1237
	if ( ! give_get_option( 'enable_sequential' ) ) {
1238
		return false;
1239
	}
1240
1241
	$number           = get_option( 'give_last_payment_number' );
1242
	$start            = give_get_option( 'sequential_start', 1 );
1243
	$increment_number = true;
1244
1245
	if ( false !== $number ) {
1246
1247
		if ( empty( $number ) ) {
1248
1249
			$number           = $start;
1250
			$increment_number = false;
1251
1252
		}
1253
	} else {
1254
1255
		// This case handles the first addition of the new option, as well as if it get's deleted for any reason.
1256
		$payments     = new Give_Payments_Query( array(
1257
			'number'  => 1,
1258
			'order'   => 'DESC',
1259
			'orderby' => 'ID',
1260
			'output'  => 'posts',
1261
			'fields'  => 'ids',
1262
		) );
1263
		$last_payment = $payments->get_payments();
1264
1265
		if ( ! empty( $last_payment ) ) {
1266
1267
			$number = give_get_payment_number( $last_payment[0] );
1268
1269
		}
1270
1271
		if ( ! empty( $number ) && $number !== (int) $last_payment[0] ) {
1272
1273
			$number = give_remove_payment_prefix_postfix( $number );
1274
1275
		} else {
1276
1277
			$number           = $start;
1278
			$increment_number = false;
1279
		}
1280
	}// End if().
1281
1282
	$increment_number = apply_filters( 'give_increment_payment_number', $increment_number, $number );
1283
1284
	if ( $increment_number ) {
1285
		$number ++;
1286
	}
1287
1288
	return apply_filters( 'give_get_next_payment_number', $number );
1289
}
1290
1291
/**
1292
 * Given a given a number, remove the pre/postfix
1293
 *
1294
 * @param string $number The formatted Current Number to increment.
1295
 *
1296
 * @since 1.3
1297
 *
1298
 * @return string The new Payment number without prefix and postfix.
1299
 */
1300
function give_remove_payment_prefix_postfix( $number ) {
1301
1302
	$prefix  = give_get_option( 'sequential_prefix' );
1303
	$postfix = give_get_option( 'sequential_postfix' );
1304
1305
	// Remove prefix.
1306
	$number = preg_replace( '/' . $prefix . '/', '', $number, 1 );
1307
1308
	// Remove the postfix.
1309
	$length      = strlen( $number );
1310
	$postfix_pos = strrpos( $number, $postfix );
1311
	if ( false !== $postfix_pos ) {
1312
		$number = substr_replace( $number, '', $postfix_pos, $length );
1313
	}
1314
1315
	// Ensure it's a whole number.
1316
	$number = intval( $number );
1317
1318
	return apply_filters( 'give_remove_payment_prefix_postfix', $number, $prefix, $postfix );
1319
1320
}
1321
1322
/**
1323
 * Get Donation Amount
1324
 *
1325
 * Get the fully formatted or unformatted donation amount which is sent through give_currency_filter()
1326
 * and give_format_amount() to format the amount correctly in case of formatted amount.
1327
 *
1328
 * @param int|Give_Payment $donation    Donation ID or Donation Object.
1329
 * @param bool|array       $format_args Currency Formatting Arguments.
1330
 *
1331
 * @since 1.0
1332
 * @since 1.8.17 Added filter and internally use functions.
1333
 *
1334
 * @return string $amount Fully formatted donation amount.
1335
 */
1336
function give_donation_amount( $donation, $format_args = false ) {
1337
	/* @var Give_Payment $donation */
1338
	if ( ! ( $donation instanceof Give_Payment ) ) {
1339
		$donation = new Give_Payment( absint( $donation ) );
1340
	}
1341
1342
	if ( ! is_array( $format_args ) ) {
1343
		$format_args = array(
1344
			'currency' => (bool) $format_args,
1345
			'amount'   => (bool) $format_args,
1346
		);
1347
	}
1348
1349
	$format_args = wp_parse_args(
1350
		$format_args,
1351
		array(
1352
			'currency' => false,
1353
			'amount'   => false,
1354
		)
1355
	);
1356
1357
	$amount           = $donation->total;
1358
	$formatted_amount = $amount;
1359
1360
	if ( $format_args['amount'] ) {
1361
		$formatted_amount = give_format_amount(
1362
			$amount,
1363
			array(
1364
				'sanitize' => false,
1365
				'currency' => $donation->currency,
1366
			)
1367
		);
1368
	}
1369
1370
	if ( $format_args['currency'] ) {
1371
		$formatted_amount = give_currency_filter(
1372
			$formatted_amount,
1373
			array( 'currency_code' => $donation->currency )
1374
		);
1375
	}
1376
1377
	/**
1378
	 * Filter Donation amount.
1379
	 *
1380
	 * @since 1.8.17
1381
	 *
1382
	 * @param string $formatted_amount Formatted/Un-formatted amount.
1383
	 * @param float  $amount           Donation amount.
1384
	 * @param int    $donation_id      Donation ID.
1385
	 */
1386
	return apply_filters( 'give_donation_amount', (string) $formatted_amount, $amount, $donation );
1387
}
1388
1389
/**
1390
 * Payment Subtotal
1391
 *
1392
 * Retrieves subtotal for payment and then returns a full formatted amount. This
1393
 * function essentially calls give_get_payment_subtotal()
1394
 *
1395
 * @param int $payment_id Payment ID.
1396
 *
1397
 * @since 1.5
1398
 *
1399
 * @see   give_get_payment_subtotal()
1400
 *
1401
 * @return array Fully formatted payment subtotal.
1402
 */
1403
function give_payment_subtotal( $payment_id = 0 ) {
1404
	$subtotal = give_get_payment_subtotal( $payment_id );
1405
1406
	return give_currency_filter( give_format_amount( $subtotal, array( 'sanitize' => false ) ), array( 'currency_code' => give_get_payment_currency_code( $payment_id ) ) );
1407
}
1408
1409
/**
1410
 * Get Payment Subtotal
1411
 *
1412
 * Retrieves subtotal for payment and then returns a non formatted amount.
1413
 *
1414
 * @param int $payment_id Payment ID.
1415
 *
1416
 * @since 1.5
1417
 *
1418
 * @return float $subtotal Subtotal for payment (non formatted).
1419
 */
1420
function give_get_payment_subtotal( $payment_id = 0 ) {
1421
	$payment = new Give_Payment( $payment_id );
1422
1423
	return $payment->subtotal;
1424
}
1425
1426
/**
1427
 * Retrieves the donation ID
1428
 *
1429
 * @param int $payment_id Payment ID.
1430
 *
1431
 * @since  1.0
1432
 *
1433
 * @return string The donation ID.
1434
 */
1435
function give_get_payment_transaction_id( $payment_id = 0 ) {
1436
	$payment = new Give_Payment( $payment_id );
1437
1438
	return $payment->transaction_id;
1439
}
1440
1441
/**
1442
 * Sets a Transaction ID in post meta for the given Payment ID.
1443
 *
1444
 * @param int    $payment_id     Payment ID.
1445
 * @param string $transaction_id The transaction ID from the gateway.
1446
 *
1447
 * @since  1.0
1448
 *
1449
 * @return bool|mixed
1450
 */
1451
function give_set_payment_transaction_id( $payment_id = 0, $transaction_id = '' ) {
1452
1453
	if ( empty( $payment_id ) || empty( $transaction_id ) ) {
1454
		return false;
1455
	}
1456
1457
	$transaction_id = apply_filters( 'give_set_payment_transaction_id', $transaction_id, $payment_id );
1458
1459
	return give_update_payment_meta( $payment_id, '_give_payment_transaction_id', $transaction_id );
1460
}
1461
1462
/**
1463
 * Retrieve the donation ID based on the key
1464
 *
1465
 * @param string  $key  the key to search for.
1466
 *
1467
 * @since 1.0
1468
 * @global object $wpdb Used to query the database using the WordPress Database API.
1469
 *
1470
 * @return int $purchase Donation ID.
1471
 */
1472 View Code Duplication
function give_get_purchase_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...
1473
	global $wpdb;
1474
	$meta_table = __give_v20_bc_table_details( 'payment' );
1475
1476
	$purchase = $wpdb->get_var( $wpdb->prepare( "SELECT {$meta_table['column']['id']} FROM {$meta_table['name']} WHERE meta_key = '_give_payment_purchase_key' 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...
1477
1478
	if ( $purchase != null ) {
1479
		return $purchase;
1480
	}
1481
1482
	return 0;
1483
}
1484
1485
1486
/**
1487
 * Retrieve the donation ID based on the transaction ID
1488
 *
1489
 * @param string  $key  The transaction ID to search for.
1490
 *
1491
 * @since 1.3
1492
 * @global object $wpdb Used to query the database using the WordPress Database API.
1493
 *
1494
 * @return int $purchase Donation ID.
1495
 */
1496 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...
1497
	global $wpdb;
1498
	$meta_table = __give_v20_bc_table_details( 'payment' );
1499
1500
	$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...
1501
1502
	if ( $purchase != null ) {
1503
		return $purchase;
1504
	}
1505
1506
	return 0;
1507
}
1508
1509
/**
1510
 * Retrieve all notes attached to a donation
1511
 *
1512
 * @param int    $payment_id The donation ID to retrieve notes for.
1513
 * @param string $search     Search for notes that contain a search term.
1514
 *
1515
 * @since 1.0
1516
 *
1517
 * @return array $notes Donation Notes
1518
 */
1519
function give_get_payment_notes( $payment_id = 0, $search = '' ) {
1520
1521
	if ( empty( $payment_id ) && empty( $search ) ) {
1522
		return false;
1523
	}
1524
1525
	remove_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1526
	remove_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10 );
1527
1528
	$notes = get_comments( array(
1529
		'post_id' => $payment_id,
1530
		'order'   => 'ASC',
1531
		'search'  => $search,
1532
	) );
1533
1534
	add_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1535
	add_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10, 2 );
1536
1537
	return $notes;
1538
}
1539
1540
1541
/**
1542
 * Add a note to a payment
1543
 *
1544
 * @param int    $payment_id The payment ID to store a note for.
1545
 * @param string $note       The note to store.
1546
 *
1547
 * @since 1.0
1548
 *
1549
 * @return int The new note ID
1550
 */
1551
function give_insert_payment_note( $payment_id = 0, $note = '' ) {
1552
	if ( empty( $payment_id ) ) {
1553
		return false;
1554
	}
1555
1556
	/**
1557
	 * Fires before inserting payment note.
1558
	 *
1559
	 * @param int    $payment_id Payment ID.
1560
	 * @param string $note       The note.
1561
	 *
1562
	 * @since 1.0
1563
	 */
1564
	do_action( 'give_pre_insert_payment_note', $payment_id, $note );
1565
1566
	$note_id = wp_insert_comment( wp_filter_comment( array(
1567
		'comment_post_ID'      => $payment_id,
1568
		'comment_content'      => $note,
1569
		'user_id'              => is_admin() ? get_current_user_id() : 0,
1570
		'comment_date'         => current_time( 'mysql' ),
1571
		'comment_date_gmt'     => current_time( 'mysql', 1 ),
1572
		'comment_approved'     => 1,
1573
		'comment_parent'       => 0,
1574
		'comment_author'       => '',
1575
		'comment_author_IP'    => '',
1576
		'comment_author_url'   => '',
1577
		'comment_author_email' => '',
1578
		'comment_type'         => 'give_payment_note',
1579
1580
	) ) );
1581
1582
	/**
1583
	 * Fires after payment note inserted.
1584
	 *
1585
	 * @param int    $note_id    Note ID.
1586
	 * @param int    $payment_id Payment ID.
1587
	 * @param string $note       The note.
1588
	 *
1589
	 * @since 1.0
1590
	 */
1591
	do_action( 'give_insert_payment_note', $note_id, $payment_id, $note );
1592
1593
	return $note_id;
1594
}
1595
1596
/**
1597
 * Deletes a payment note
1598
 *
1599
 * @param int $comment_id The comment ID to delete.
1600
 * @param int $payment_id The payment ID the note is connected to.
1601
 *
1602
 * @since 1.0
1603
 *
1604
 * @return bool True on success, false otherwise.
1605
 */
1606
function give_delete_payment_note( $comment_id = 0, $payment_id = 0 ) {
1607
	if ( empty( $comment_id ) ) {
1608
		return false;
1609
	}
1610
1611
	/**
1612
	 * Fires before deleting donation note.
1613
	 *
1614
	 * @param int $comment_id Note ID.
1615
	 * @param int $payment_id Payment ID.
1616
	 *
1617
	 * @since 1.0
1618
	 */
1619
	do_action( 'give_pre_delete_payment_note', $comment_id, $payment_id );
1620
1621
	$ret = wp_delete_comment( $comment_id, true );
1622
1623
	/**
1624
	 * Fires after donation note deleted.
1625
	 *
1626
	 * @param int $comment_id Note ID.
1627
	 * @param int $payment_id Payment ID.
1628
	 *
1629
	 * @since 1.0
1630
	 */
1631
	do_action( 'give_post_delete_payment_note', $comment_id, $payment_id );
1632
1633
	return $ret;
1634
}
1635
1636
/**
1637
 * Gets the payment note HTML
1638
 *
1639
 * @param object|int $note       The comment object or ID.
1640
 * @param int        $payment_id The payment ID the note is connected to.
1641
 *
1642
 * @since 1.0
1643
 *
1644
 * @return string
1645
 */
1646
function give_get_payment_note_html( $note, $payment_id = 0 ) {
1647
1648
	if ( is_numeric( $note ) ) {
1649
		$note = get_comment( $note );
1650
	}
1651
1652
	if ( ! empty( $note->user_id ) ) {
1653
		$user = get_userdata( $note->user_id );
1654
		$user = $user->display_name;
1655
	} else {
1656
		$user = __( 'System', 'give' );
1657
	}
1658
1659
	$date_format = give_date_format() . ', ' . get_option( 'time_format' );
1660
1661
	$delete_note_url = wp_nonce_url( add_query_arg( array(
1662
		'give-action' => 'delete_payment_note',
1663
		'note_id'     => $note->comment_ID,
1664
		'payment_id'  => $payment_id,
1665
	) ), 'give_delete_payment_note_' . $note->comment_ID );
1666
1667
	$note_html = '<div class="give-payment-note" id="give-payment-note-' . $note->comment_ID . '">';
1668
	$note_html .= '<p>';
1669
	$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/>';
1670
	$note_html .= $note->comment_content;
1671
	$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...
1672
	$note_html .= '</p>';
1673
	$note_html .= '</div>';
1674
1675
	return $note_html;
1676
1677
}
1678
1679
/**
1680
 * Exclude notes (comments) on give_payment post type from showing in Recent
1681
 * Comments widgets
1682
 *
1683
 * @param object $query WordPress Comment Query Object.
1684
 *
1685
 * @since 1.0
1686
 *
1687
 * @return void
1688
 */
1689
function give_hide_payment_notes( $query ) {
1690
	if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.1', '>=' ) ) {
1691
		$types = isset( $query->query_vars['type__not_in'] ) ? $query->query_vars['type__not_in'] : array();
1692
		if ( ! is_array( $types ) ) {
1693
			$types = array( $types );
1694
		}
1695
		$types[]                           = 'give_payment_note';
1696
		$query->query_vars['type__not_in'] = $types;
1697
	}
1698
}
1699
1700
add_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1701
1702
/**
1703
 * Exclude notes (comments) on give_payment post type from showing in Recent Comments widgets
1704
 *
1705
 * @param array  $clauses          Comment clauses for comment query.
1706
 * @param object $wp_comment_query WordPress Comment Query Object.
1707
 *
1708
 * @since 1.0
1709
 *
1710
 * @return array $clauses Updated comment clauses.
1711
 */
1712
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...
1713
	if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.1', '<' ) ) {
1714
		$clauses['where'] .= ' AND comment_type != "give_payment_note"';
1715
	}
1716
1717
	return $clauses;
1718
}
1719
1720
add_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10, 2 );
1721
1722
1723
/**
1724
 * Exclude notes (comments) on give_payment post type from showing in comment feeds
1725
 *
1726
 * @param string $where
1727
 * @param object $wp_comment_query WordPress Comment Query Object.
1728
 *
1729
 * @since 1.0
1730
 *
1731
 * @return string $where
1732
 */
1733
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...
1734
	global $wpdb;
1735
1736
	$where .= $wpdb->prepare( ' AND comment_type != %s', 'give_payment_note' );
1737
1738
	return $where;
1739
}
1740
1741
add_filter( 'comment_feed_where', 'give_hide_payment_notes_from_feeds', 10, 2 );
1742
1743
1744
/**
1745
 * Remove Give Comments from the wp_count_comments function
1746
 *
1747
 * @param array $stats   (empty from core filter).
1748
 * @param int   $post_id Post ID.
1749
 *
1750
 * @access public
1751
 * @since  1.0
1752
 *
1753
 * @return array|object Array of comment counts.
1754
 */
1755
function give_remove_payment_notes_in_comment_counts( $stats, $post_id ) {
1756
	global $wpdb, $pagenow;
1757
1758
	if ( 'index.php' != $pagenow ) {
1759
		return $stats;
1760
	}
1761
1762
	$post_id = (int) $post_id;
1763
1764
	if ( apply_filters( 'give_count_payment_notes_in_comments', false ) ) {
1765
		return $stats;
1766
	}
1767
1768
	$stats = Give_Cache::get_group( "comments-{$post_id}", 'counts' );
1769
1770
	if ( ! is_null( $stats  ) ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 2 found
Loading history...
1771
		return $stats;
1772
	}
1773
1774
	$where = 'WHERE comment_type != "give_payment_note"';
1775
1776
	if ( $post_id > 0 ) {
1777
		$where .= $wpdb->prepare( ' AND comment_post_ID = %d', $post_id );
1778
	}
1779
1780
	$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...
1781
1782
	$total    = 0;
1783
	$approved = array(
1784
		'0'            => 'moderated',
0 ignored issues
show
introduced by
Detected usage of 0, possible slow query.
Loading history...
1785
		'1'            => 'approved',
1786
		'spam'         => 'spam',
1787
		'trash'        => 'trash',
1788
		'post-trashed' => 'post-trashed',
1789
	);
1790
	foreach ( (array) $count as $row ) {
1791
		// Don't count post-trashed toward totals.
1792
		if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] ) {
1793
			$total += $row['num_comments'];
1794
		}
1795
		if ( isset( $approved[ $row['comment_approved'] ] ) ) {
1796
			$stats[ $approved[ $row['comment_approved'] ] ] = $row['num_comments'];
1797
		}
1798
	}
1799
1800
	$stats['total_comments'] = $total;
1801
	foreach ( $approved as $key ) {
1802
		if ( empty( $stats[ $key ] ) ) {
1803
			$stats[ $key ] = 0;
1804
		}
1805
	}
1806
1807
	$stats = (object) $stats;
1808
	Give_Cache::set_group( "comments-{$post_id}", $stats, 'counts' );
1809
1810
	return $stats;
1811
}
1812
1813
add_filter( 'wp_count_comments', 'give_remove_payment_notes_in_comment_counts', 10, 2 );
1814
1815
1816
/**
1817
 * Filter where older than one week
1818
 *
1819
 * @param string $where Where clause.
1820
 *
1821
 * @access public
1822
 * @since  1.0
1823
 *
1824
 * @return string $where Modified where clause.
1825
 */
1826
function give_filter_where_older_than_week( $where = '' ) {
1827
	// Payments older than one week.
1828
	$start = date( 'Y-m-d', strtotime( '-7 days' ) );
1829
	$where .= " AND post_date <= '{$start}'";
1830
1831
	return $where;
1832
}
1833
1834
1835
/**
1836
 * Get Payment Form ID.
1837
 *
1838
 * Retrieves the form title and appends the level name if present.
1839
 *
1840
 * @param array  $payment_meta Payment meta data.
1841
 * @param bool   $only_level   If set to true will only return the level name if multi-level enabled.
1842
 * @param string $separator    The separator between the .
1843
 *
1844
 * @since 1.5
1845
 *
1846
 * @return string $form_title Returns the full title if $only_level is false, otherwise returns the levels title.
1847
 */
1848
function give_get_payment_form_title( $payment_meta, $only_level = false, $separator = '' ) {
1849
	$form_id    = isset( $payment_meta['form_id'] ) ? $payment_meta['form_id'] : 0;
1850
	$price_id   = isset( $payment_meta['price_id'] ) ? $payment_meta['price_id'] : null;
1851
	$form_title = isset( $payment_meta['form_title'] ) ? $payment_meta['form_title'] : '';
1852
1853
	$cache_key = Give_Cache::get_key(
1854
		'give_forms',
1855
		array(
1856
			$form_id,
1857
			$price_id,
1858
			$form_title,
1859
			$only_level,
1860
			$separator
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
1861
		)
1862
		, false
1863
	);
1864
1865
	$form_title_html = Give_Cache::get_db_query( $cache_key );
1866
1867
	if ( is_null( $form_title_html ) ) {
1868
		if ( $only_level == true ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
introduced by
Found "== true". Use Yoda Condition checks, you must
Loading history...
1869
			$form_title = '';
1870
		}
1871
1872
		$form_title_html = $form_title;
1873
1874
		// If multi-level, append to the form title.
1875
		if ( give_has_variable_prices( $form_id ) ) {
1876
1877
			// Only add separator if there is a form title.
1878
			if ( ! empty( $form_title ) ) {
1879
				$form_title_html = "{$form_title} {$separator} ";
1880
			}
1881
1882
			$form_title_html .= '<span class="donation-level-text-wrap">';
1883
1884
			if ( 'custom' === $price_id ) {
1885
				$custom_amount_text = give_get_meta( $form_id, '_give_custom_amount_text', true );
1886
				$form_title_html    .= ! empty( $custom_amount_text ) ? $custom_amount_text : __( 'Custom Amount', 'give' );
1887
			} else {
1888
				$form_title_html .= give_get_price_option_name( $form_id, $price_id );
1889
			}
1890
1891
			$form_title_html .= '</span>';
1892
1893
		}
1894
1895
		Give_Cache::set_db_query( $cache_key, $form_title_html );
1896
	}
1897
1898
	return apply_filters( 'give_get_payment_form_title', $form_title_html, $payment_meta );
1899
1900
}
1901
1902
/**
1903
 * Get Price ID
1904
 *
1905
 * Retrieves the Price ID when provided a proper form ID and price (donation) total
1906
 *
1907
 * @param int    $form_id Form ID.
1908
 * @param string $price   Price ID.
1909
 *
1910
 * @return string $price_id
1911
 */
1912
function give_get_price_id( $form_id, $price ) {
1913
	$price_id = null;
1914
1915
	if ( give_has_variable_prices( $form_id ) ) {
1916
1917
		$levels = give_get_meta( $form_id, '_give_donation_levels', true );
1918
1919
		foreach ( $levels as $level ) {
1920
1921
			$level_amount = give_maybe_sanitize_amount( $level['_give_amount'] );
1922
1923
			// Check that this indeed the recurring price.
1924
			if ( $level_amount == $price ) {
1925
1926
				$price_id = $level['_give_id']['level_id'];
1927
				break;
1928
1929
			}
1930
		}
1931
1932
		if ( is_null( $price_id ) && give_is_custom_price_mode( $form_id ) ) {
1933
			$price_id = 'custom';
1934
		}
1935
	}
1936
1937
	// Price ID must be numeric or string.
1938
	$price_id = ! is_numeric( $price_id ) && ! is_string( $price_id ) ? 0 : $price_id;
1939
1940
	return $price_id;
1941
}
1942
1943
/**
1944
 * Get/Print give form dropdown html
1945
 *
1946
 * This function is wrapper to public method forms_dropdown of Give_HTML_Elements class to get/print form dropdown html.
1947
 * Give_HTML_Elements is defined in includes/class-give-html-elements.php.
1948
 *
1949
 * @param array $args Arguments for form dropdown.
1950
 * @param bool  $echo This parameter decides if print form dropdown html output or not.
1951
 *
1952
 * @since 1.6
1953
 *
1954
 * @return string
1955
 */
1956
function give_get_form_dropdown( $args = array(), $echo = false ) {
1957
	$form_dropdown_html = Give()->html->forms_dropdown( $args );
1958
1959
	if ( ! $echo ) {
1960
		return $form_dropdown_html;
1961
	}
1962
1963
	echo $form_dropdown_html;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$form_dropdown_html'
Loading history...
1964
}
1965
1966
/**
1967
 * Get/Print give form variable price dropdown html
1968
 *
1969
 * @param array $args Arguments for form dropdown.
1970
 * @param bool  $echo This parameter decide if print form dropdown html output or not.
1971
 *
1972
 * @since 1.6
1973
 *
1974
 * @return string|bool
1975
 */
1976
function give_get_form_variable_price_dropdown( $args = array(), $echo = false ) {
1977
1978
	// Check for give form id.
1979
	if ( empty( $args['id'] ) ) {
1980
		return false;
1981
	}
1982
1983
	$form = new Give_Donate_Form( $args['id'] );
1984
1985
	// Check if form has variable prices or not.
1986
	if ( ! $form->ID || ! $form->has_variable_prices() ) {
1987
		return false;
1988
	}
1989
1990
	$variable_prices        = $form->get_prices();
1991
	$variable_price_options = array();
1992
1993
	// Check if multi donation form support custom donation or not.
1994
	if ( $form->is_custom_price_mode() ) {
1995
		$variable_price_options['custom'] = _x( 'Custom', 'custom donation dropdown item', 'give' );
1996
	}
1997
1998
	// Get variable price and ID from variable price array.
1999
	foreach ( $variable_prices as $variable_price ) {
2000
		$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 ) ) );
2001
	}
2002
2003
	// Update options.
2004
	$args = array_merge( $args, array(
2005
		'options' => $variable_price_options,
2006
	) );
2007
2008
	// Generate select html.
2009
	$form_dropdown_html = Give()->html->select( $args );
2010
2011
	if ( ! $echo ) {
2012
		return $form_dropdown_html;
2013
	}
2014
2015
	echo $form_dropdown_html;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$form_dropdown_html'
Loading history...
2016
}
2017
2018
/**
2019
 * Get the price_id from the payment meta.
2020
 *
2021
 * Some gateways use `give_price_id` and others were using just `price_id`;
2022
 * This checks for the difference and falls back to retrieving it from the form as a last resort.
2023
 *
2024
 * @param array $payment_meta Payment Meta.
2025
 *
2026
 * @since 1.8.6
2027
 *
2028
 * @return string
2029
 */
2030
function give_get_payment_meta_price_id( $payment_meta ) {
2031
2032
	if ( isset( $payment_meta['give_price_id'] ) ) {
2033
		$price_id = $payment_meta['give_price_id'];
2034
	} elseif ( isset( $payment_meta['price_id'] ) ) {
2035
		$price_id = $payment_meta['price_id'];
2036
	} else {
2037
		$price_id = give_get_price_id( $payment_meta['give_form_id'], $payment_meta['price'] );
2038
	}
2039
2040
	return apply_filters( 'give_get_payment_meta_price_id', $price_id );
2041
2042
}
2043