Test Failed
Push — issues/1944 ( dc7b30...4d5bd7 )
by Ravinder
05:09
created

functions.php ➔ give_delete_donation()   C

Complexity

Conditions 8
Paths 13

Size

Total Lines 72
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 26
nc 13
nop 2
dl 0
loc 72
rs 6.3883
c 0
b 0
f 0

How to fix   Long Method   

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