Completed
Push — master ( 45f118...bcc91e )
by Devin
17:37 queued 14:12
created

functions.php ➔ give_get_total_earnings()   C

Complexity

Conditions 7
Paths 12

Size

Total Lines 44
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 7.5375

Importance

Changes 0
Metric Value
cc 7
eloc 21
nc 12
nop 1
dl 0
loc 44
ccs 7
cts 9
cp 0.7778
crap 7.5375
rs 6.7272
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 46 and the first side effect is on line 14.

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

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

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

Loading history...
2
/**
3
 * 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 42
 * @type string $orderby Sort retrieved payments by parameter. Default is 'ID'.
39 42
 * @type string $status The status of the payments. Default is 'any'.
40 42
 * @type string $user User. Default is null.
41
 * @type string $meta_key Custom field key. Default is null.
42 42
 * }
43 42
 *
44
 * @return array $payments Payments retrieved from the database
45 42
 */
46
function give_get_payments( $args = array() ) {
47
48
	// Fallback to post objects to ensure backwards compatibility.
49
	if ( ! isset( $args['output'] ) ) {
50
		$args['output'] = 'posts';
51
	}
52
53
	$args     = apply_filters( 'give_get_payments_args', $args );
54
	$payments = new Give_Payments_Query( $args );
55
56
	return $payments->get_payments();
57
}
58
59
/**
60 42
 * Retrieve payment by a given field
61
 *
62
 * @since  1.0
63
 *
64 42
 * @param  string $field The field to retrieve the payment with.
65
 * @param  mixed $value The value for $field.
66 42
 *
67 42
 * @return mixed
68 42
 */
69
function give_get_payment_by( $field = '', $value = '' ) {
70 42
71
	if ( empty( $field ) || empty( $value ) ) {
72
		return false;
73
	}
74 42
75
	switch ( strtolower( $field ) ) {
76
77
		case 'id':
78
			$payment = new Give_Payment( $value );
79
			$id      = $payment->ID;
80
81
			if ( empty( $id ) ) {
82
				return false;
83
			}
84
85
			break;
86
87
		case 'key':
88
			$payment = give_get_payments( array(
89
				'meta_key'       => '_give_payment_purchase_key',
90
				'meta_value'     => $value,
91
				'posts_per_page' => 1,
92
				'fields'         => 'ids',
93
			) );
94
95
			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...
96
				$payment = new Give_Payment( $payment[0] );
97
			}
98
99
			break;
100
101
		case 'payment_number':
102
			$payment = give_get_payments( array(
103
				'meta_key'       => '_give_payment_number',
104
				'meta_value'     => $value,
105
				'posts_per_page' => 1,
106 42
				'fields'         => 'ids',
107
			) );
108 42
109 42
			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...
110
				$payment = new Give_Payment( $payment[0] );
111
			}
112
113
			break;
114
115
		default:
116
			return false;
117
	}
118
119
	if ( $payment ) {
120
		return $payment;
121
	}
122
123
	return false;
124
}
125
126 52
/**
127
 * Insert Payment
128
 *
129
 * @since  1.0
130 52
 *
131 52
 * @param  array $payment_data Arguments passed.
132 52
 *
133 52
 * @return int|bool Payment ID if payment is inserted, false otherwise.
134 52
 */
135 52
function give_insert_payment( $payment_data = array() ) {
136
137
	if ( empty( $payment_data ) ) {
138 52
		return false;
139 52
	}
140 52
141 52
	$payment    = new Give_Payment();
142 52
	$gateway    = ! empty( $payment_data['gateway'] ) ? $payment_data['gateway'] : '';
143 52
	$gateway    = empty( $gateway ) && isset( $_POST['give-gateway'] ) ? $_POST['give-gateway'] : $gateway;
144 52
	$form_id    = isset( $payment_data['give_form_id'] ) ? $payment_data['give_form_id'] : 0;
145 52
	$price_id   = give_get_payment_meta_price_id( $payment_data );
146 52
	$form_title = isset( $payment_data['give_form_title'] ) ? $payment_data['give_form_title'] : get_the_title( $form_id );
147 52
148 52
	// Set properties.
149 52
	$payment->total          = $payment_data['price'];
150 52
	$payment->status         = ! empty( $payment_data['status'] ) ? $payment_data['status'] : 'pending';
151 52
	$payment->currency       = ! empty( $payment_data['currency'] ) ? $payment_data['currency'] : give_get_currency();
152 52
	$payment->user_info      = $payment_data['user_info'];
153 52
	$payment->gateway        = $gateway;
154 52
	$payment->form_title     = $form_title;
155
	$payment->form_id        = $form_id;
156
	$payment->price_id       = $price_id;
157
	$payment->user_id        = $payment_data['user_info']['id'];
158 52
	$payment->email          = $payment_data['user_email'];
159 52
	$payment->first_name     = $payment_data['user_info']['first_name'];
160 52
	$payment->last_name      = $payment_data['user_info']['last_name'];
161 52
	$payment->email          = $payment_data['user_info']['email'];
162
	$payment->ip             = give_get_ip();
163 52
	$payment->key            = $payment_data['purchase_key'];
164
	$payment->mode           = give_is_test_mode() ? 'test' : 'live';
165
	$payment->parent_payment = ! empty( $payment_data['parent'] ) ? absint( $payment_data['parent'] ) : '';
166 52
167
	// Add the donation.
168
	$args = array(
169
		'price'    => $payment->total,
170
		'price_id' => $payment->price_id,
171 52
		'fees'     => isset( $payment_data['fees'] ) ? $payment_data['fees'] : array(),
172 20
	);
173 20
174 20
	$payment->add_donation( $payment->form_id, $args );
175 20
176
	// Set date if present.
177
	if ( isset( $payment_data['post_date'] ) ) {
178 52
		$payment->date = $payment_data['post_date'];
179
	}
180
181 52
	// Handle sequential payments.
182
	if ( give_get_option( 'enable_sequential' ) ) {
183
		$number          = give_get_next_payment_number();
184 52
		$payment->number = give_format_payment_number( $number );
185
		update_option( 'give_last_payment_number', $number );
186
	}
187 52
188 52
	// Clear the user's donation cache.
189
	delete_transient( 'give_user_' . $payment_data['user_info']['id'] . '_purchases' );
190
191
	// Save payment.
192
	$payment->save();
193
194
	/**
195
	 * Fires while inserting payments.
196
	 *
197
	 * @since 1.0
198
	 *
199
	 * @param int $payment_id The payment ID.
200
	 * @param array $payment_data Arguments passed.
201
	 */
202
	do_action( 'give_insert_payment', $payment->ID, $payment_data );
203
204
	// Return payment ID upon success.
205
	if ( ! empty( $payment->ID ) ) {
206
		return $payment->ID;
207
	}
208 35
209 35
	// Return false if no payment was inserted.
210 35
	return false;
211
212 35
}
213
214
/**
215
 * Create payment.
216
 *
217
 * @param $payment_data
218
 *
219
 * @return bool|int
220
 */
221
function give_create_payment( $payment_data ) {
222
223
	$form_id  = intval( $payment_data['post_data']['give-form-id'] );
224
	$price_id = isset( $payment_data['post_data']['give-price-id'] ) ? $payment_data['post_data']['give-price-id'] : '';
225
226
	// Collect payment data.
227
	$insert_payment_data = array(
228
		'price'           => $payment_data['price'],
229 31
		'give_form_title' => $payment_data['post_data']['give-form-title'],
230
		'give_form_id'    => $form_id,
231 31
		'give_price_id'   => $price_id,
232 31
		'date'            => $payment_data['date'],
233 31
		'user_email'      => $payment_data['user_email'],
234 31
		'purchase_key'    => $payment_data['purchase_key'],
235 31
		'currency'        => give_get_currency(),
236
		'user_info'       => $payment_data['user_info'],
237
		'status'          => 'pending',
238 31
		'gateway'         => 'paypal',
239 31
	);
240
241 31
	/**
242
	 * Filter the payment params.
243 31
	 *
244 16
	 * @since 1.8
245 16
	 *
246
	 * @param array $insert_payment_data
247 31
	 */
248
	$insert_payment_data = apply_filters( 'give_create_payment', $insert_payment_data );
249
250 14
	// Record the pending payment.
251
	return give_insert_payment( $insert_payment_data );
252 14
}
253
254 14
/**
255
 * Updates a payment status.
256
 *
257
 * @since  1.0
258
 *
259
 * @param  int $payment_id Payment ID.
260
 * @param  string $new_status New Payment Status. Default is 'publish'.
261 14
 *
262
 * @return bool
263 31
 */
264
function give_update_payment_status( $payment_id, $new_status = 'publish' ) {
265 31
266
	$payment         = new Give_Payment( $payment_id );
267
	$payment->status = $new_status;
268 1
	$updated         = $payment->save();
269
270 1
	return $updated;
271
}
272
273 31
274
/**
275
 * Deletes a Donation
276 31
 *
277 31
 * @since  1.0
278 31
 * @global      $give_logs
279
 *
280
 * @param  int $payment_id Payment ID (default: 0).
281 31
 * @param  bool $update_customer If we should update the customer stats (default:true).
282
 *
283 31
 * @return void
284 31
 */
285 31
function give_delete_purchase( $payment_id = 0, $update_customer = true ) {
286
	global $give_logs;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
287 31
288 31
	$payment     = new Give_Payment( $payment_id );
289
	$amount      = give_get_payment_amount( $payment_id );
290
	$status      = $payment->post_status;
291
	$customer_id = give_get_payment_customer_id( $payment_id );
292
	$customer    = new Give_Customer( $customer_id );
293
294
	// Only undo donations that aren't these statuses.
295
	$dont_undo_statuses = apply_filters( 'give_undo_purchase_statuses', array(
296
		'pending',
297
		'cancelled',
298
	) );
299
300
	if ( ! in_array( $status, $dont_undo_statuses ) ) {
301
		give_undo_purchase( false, $payment_id );
302 20
	}
303
304
	if ( $status == 'publish' ) {
305
306
		// Only decrease earnings if they haven't already been decreased (or were never increased for this payment).
307 20
		give_decrease_total_earnings( $amount );
308
309 20
		// @todo: Refresh only range related stat cache
310 20
		give_delete_donation_stats();
311
312 18
		if ( $customer->id && $update_customer ) {
313 18
314
			// Decrement the stats for the donor.
315 20
			$customer->decrease_purchase_count();
316 20
			$customer->decrease_value( $amount );
317
318 18
		}
319 18
	}
320
321 20
	/**
322
	 * Fires before deleting payment.
323
	 *
324
	 * @since 1.0
325
	 *
326
	 * @param int $payment_id Payment ID.
327
	 */
328
	do_action( 'give_payment_delete', $payment_id );
329
330
	if ( $customer->id && $update_customer ) {
331
332
		// Remove the payment ID from the donor.
333
		$customer->remove_payment( $payment_id );
334
335
	}
336
337 6
	// Remove the payment.
338
	wp_delete_post( $payment_id, true );
339
340 6
	// Remove related sale log entries.
341 6
	$give_logs->delete_logs(
342 6
		null,
343 6
		'sale',
344 6
		array(
345 6
			array(
346
				'key'   => '_give_log_payment_id',
347 6
				'value' => $payment_id,
348
			),
349 6
		)
350 6
	);
351 6
352
	/**
353
	 * Fires after payment deleted.
354 6
	 *
355
	 * @since 1.0
356
	 *
357
	 * @param int $payment_id Payment ID.
358
	 */
359
	do_action( 'give_payment_deleted', $payment_id );
360
}
361
362
/**
363
 * Undo Donation
364
 *
365
 * Undoes a donation, including the decrease of donations and earning stats.
366
 * Used for when refunding or deleting a donation.
367
 *
368
 * @since  1.0
369
 *
370
 * @param  int|bool $form_id Form ID (default: false).
371
 * @param  int $payment_id Payment ID.
372
 *
373 6
 * @return void
374
 */
375
function give_undo_purchase( $form_id = false, $payment_id ) {
376
377
	if ( ! empty( $form_id ) ) {
378
		$form_id = false;
379
		_give_deprected_argument( 'form_id', 'give_undo_purchase', '1.5' );
380
	}
381
382
	$payment = new Give_Payment( $payment_id );
383
384
	$maybe_decrease_earnings = apply_filters( 'give_decrease_earnings_on_undo', true, $payment, $payment->form_id );
385
	if ( true === $maybe_decrease_earnings ) {
386
		// Decrease earnings.
387
		give_decrease_earnings( $payment->form_id, $payment->total );
388
	}
389
390
	$maybe_decrease_sales = apply_filters( 'give_decrease_sales_on_undo', true, $payment, $payment->form_id );
391
	if ( true === $maybe_decrease_sales ) {
392
		// Decrease donation count.
393
		give_decrease_purchase_count( $payment->form_id );
394
	}
395
396
}
397
398
399
/**
400
 * Count Payments
401
 *
402
 * Returns the total number of payments recorded.
403
 *
404
 * @since  1.0
405
 *
406
 * @param  array $args Arguments passed.
407
 *
408
 * @return object $stats Contains the number of payments per payment status.
409
 */
410
function give_count_payments( $args = array() ) {
411
412
	global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
413
414
	$defaults = array(
415
		'user'       => null,
416
		's'          => null,
417
		'start-date' => null,
418
		'end-date'   => null,
419
		'form_id'    => null,
420 6
	);
421
422
	$args = wp_parse_args( $args, $defaults );
423
424
	$select = 'SELECT p.post_status,count( * ) AS num_posts';
425
	$join   = '';
426 6
	$where  = "WHERE p.post_type = 'give_payment'";
427
428
	// Count payments for a specific user.
429
	if ( ! empty( $args['user'] ) ) {
430
431
		if ( is_email( $args['user'] ) ) {
432
			$field = 'email';
433
		} elseif ( is_numeric( $args['user'] ) ) {
434
			$field = 'id';
435
		} else {
436
			$field = '';
437
		}
438
439
		$join = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
440
441
		if ( ! empty( $field ) ) {
442
			$where .= "
443
				AND m.meta_key = '_give_payment_user_{$field}'
444
				AND m.meta_value = '{$args['user']}'";
445
		}
446
447
		// Count payments for a search.
448 6
	} elseif ( ! empty( $args['s'] ) ) {
449
450
		if ( is_email( $args['s'] ) || strlen( $args['s'] ) == 32 ) {
451
452
			if ( is_email( $args['s'] ) ) {
453
				$field = '_give_payment_user_email';
454
			} else {
455
				$field = '_give_payment_purchase_key';
456
			}
457
458
			$join  = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
459
			$where .= $wpdb->prepare( '
460
                AND m.meta_key = %s
461
                AND m.meta_value = %s',
462
				$field,
463
				$args['s']
464
			);
465
466 6
		} elseif ( '#' == substr( $args['s'], 0, 1 ) ) {
467 6
468
			$search = str_replace( '#:', '', $args['s'] );
469
			$search = str_replace( '#', '', $search );
470 6
471 6
			$select = 'SELECT p2.post_status,count( * ) AS num_posts ';
472 6
			$join   = "LEFT JOIN $wpdb->postmeta m ON m.meta_key = '_give_log_payment_id' AND m.post_id = p.ID ";
473
			$join   .= "INNER JOIN $wpdb->posts p2 ON m.meta_value = p2.ID ";
474 6
			$where  = "WHERE p.post_type = 'give_log' ";
475
			$where  .= $wpdb->prepare( 'AND p.post_parent = %d} ', $search );
476 6
477
		} elseif ( is_numeric( $args['s'] ) ) {
478 6
479 6
			$join  = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
480
			$where .= $wpdb->prepare( "
481
				AND m.meta_key = '_give_payment_user_id'
482
				AND m.meta_value = %d",
483 6
				$args['s']
484
			);
485 6
486 6
		} else {
487 6
			$search = $wpdb->esc_like( $args['s'] );
488 6
			$search = '%' . $search . '%';
489 6
490
			$where .= $wpdb->prepare( 'AND ((p.post_title LIKE %s) OR (p.post_content LIKE %s))', $search, $search );
491 6
		}
492 6
	}
493 6
494
	if ( ! empty( $args['form_id'] ) && is_numeric( $args['form_id'] ) ) {
495 6
496
		$where .= $wpdb->prepare( ' AND p.post_parent = %d', $args['form_id'] );
497 6
498
	}
499
	// Limit payments count by date.
500
	if ( ! empty( $args['start-date'] ) && false !== strpos( $args['start-date'], '/' ) ) {
501 6
502 6
		$date_parts = explode( '/', $args['start-date'] );
503
		$month      = ! empty( $date_parts[0] ) && is_numeric( $date_parts[0] ) ? $date_parts[0] : 0;
504 6
		$day        = ! empty( $date_parts[1] ) && is_numeric( $date_parts[1] ) ? $date_parts[1] : 0;
505 6
		$year       = ! empty( $date_parts[2] ) && is_numeric( $date_parts[2] ) ? $date_parts[2] : 0;
506
507 6
		$is_date = checkdate( $month, $day, $year );
508
		if ( false !== $is_date ) {
509
510
			$date  = new DateTime( $args['start-date'] );
511
			$where .= $wpdb->prepare( " AND p.post_date >= '%s'", $date->format( 'Y-m-d' ) );
512
513
		}
514
515
		// Fixes an issue with the payments list table counts when no end date is specified (partiy with stats class).
516
		if ( empty( $args['end-date'] ) ) {
517
			$args['end-date'] = $args['start-date'];
518
		}
519
	}
520
521
	if ( ! empty( $args['end-date'] ) && false !== strpos( $args['end-date'], '/' ) ) {
522
523
		$date_parts = explode( '/', $args['end-date'] );
524
525
		$month = ! empty( $date_parts[0] ) ? $date_parts[0] : 0;
526
		$day   = ! empty( $date_parts[1] ) ? $date_parts[1] : 0;
527
		$year  = ! empty( $date_parts[2] ) ? $date_parts[2] : 0;
528
529
		$is_date = checkdate( $month, $day, $year );
530
		if ( false !== $is_date ) {
531
532
			$date  = new DateTime( $args['end-date'] );
533
			$where .= $wpdb->prepare( " AND p.post_date <= '%s'", $date->format( 'Y-m-d' ) );
534
535
		}
536
	}
537
538
	$where = apply_filters( 'give_count_payments_where', $where );
539
	$join  = apply_filters( 'give_count_payments_join', $join );
540
541
	$query = "$select
542
		FROM $wpdb->posts p
543
		$join
544
		$where
545
		GROUP BY p.post_status
546
	";
547
548
	$cache_key = md5( $query );
549
550
	$count = wp_cache_get( $cache_key, 'counts' );
551
	if ( false !== $count ) {
552
		return $count;
553
	}
554
555
	$count = $wpdb->get_results( $query, ARRAY_A );
556
557
	$stats    = array();
558
	$statuses = get_post_stati();
559
	if ( isset( $statuses['private'] ) && empty( $args['s'] ) ) {
560
		unset( $statuses['private'] );
561
	}
562
563
	foreach ( $statuses as $state ) {
564
		$stats[ $state ] = 0;
565
	}
566
567
	foreach ( (array) $count as $row ) {
568
569
		if ( 'private' == $row['post_status'] && empty( $args['s'] ) ) {
570
			continue;
571
		}
572
573
		$stats[ $row['post_status'] ] = $row['num_posts'];
574
	}
575
576
	$stats = (object) $stats;
577
	wp_cache_set( $cache_key, $stats, 'counts' );
578
579 52
	return $stats;
580 52
}
581 52
582 52
583 52
/**
584 52
 * Check For Existing Payment
585 52
 *
586 52
 * @since  1.0
587 52
 *
588
 * @param  int $payment_id Payment ID
589 52
 *
590
 * @return bool $exists True if payment exists, false otherwise.
591
 */
592
function give_check_for_existing_payment( $payment_id ) {
593
	$exists  = false;
594
	$payment = new Give_Payment( $payment_id );
595
596
	if ( $payment_id === $payment->ID && 'publish' === $payment->status ) {
597
		$exists = true;
598
	}
599
600
	return $exists;
601 52
}
602 52
603
/**
604 52
 * Get Payment Status
605
 *
606
 * @since 1.0
607
 *
608
 * @param WP_Post|Give_Payment $payment Payment object.
609
 * @param bool $return_label Whether to return the translated status label
610
 *                                           instead of status value. Default false.
611
 *
612
 * @return bool|mixed True if payment status exists, false otherwise.
613
 */
614
function give_get_payment_status( $payment, $return_label = false ) {
615
616
	if ( ! is_object( $payment ) || ! isset( $payment->post_status ) ) {
617
		return false;
618
	}
619
620
	$statuses = give_get_payment_statuses();
621
622
	if ( ! is_array( $statuses ) || empty( $statuses ) ) {
623
		return false;
624
	}
625
626
	// Get payment object if no already given.
627
	$payment = $payment instanceof Give_Payment ? $payment : new Give_Payment( $payment->ID );
628
629
	if ( array_key_exists( $payment->status, $statuses ) ) {
630
		if ( true === $return_label ) {
631
			// Return translated status label.
632
			return $statuses[ $payment->status ];
633
		} else {
634
			// Account that our 'publish' status is labeled 'Complete'
635
			$post_status = 'publish' == $payment->status ? 'Complete' : $payment->post_status;
636
637
			// Make sure we're matching cases, since they matter
638
			return array_search( strtolower( $post_status ), array_map( 'strtolower', $statuses ) );
639
		}
640
	}
641
642
	return false;
643
}
644
645
/**
646
 * Retrieves all available statuses for payments.
647
 *
648
 * @since  1.0
649
 *
650
 * @return array $payment_status All the available payment statuses.
651
 */
652
function give_get_payment_statuses() {
653
	$payment_statuses = array(
654
		'pending'     => __( 'Pending', 'give' ),
655
		'publish'     => __( 'Complete', 'give' ),
656
		'refunded'    => __( 'Refunded', 'give' ),
657
		'failed'      => __( 'Failed', 'give' ),
658
		'cancelled'   => __( 'Cancelled', 'give' ),
659
		'abandoned'   => __( 'Abandoned', 'give' ),
660
		'preapproval' => __( 'Pre-Approved', 'give' ),
661
		'processing'  => __( 'Processing', 'give' ),
662
		'revoked'     => __( 'Revoked', 'give' ),
663
	);
664
665
	return apply_filters( 'give_payment_statuses', $payment_statuses );
666
}
667
668
/**
669
 * Get Payment Status Keys
670
 *
671
 * Retrieves keys for all available statuses for payments
672
 *
673
 * @since  1.0
674
 *
675
 * @return array $payment_status All the available payment statuses.
676
 */
677
function give_get_payment_status_keys() {
678
	$statuses = array_keys( give_get_payment_statuses() );
679
	asort( $statuses );
680
681
	return array_values( $statuses );
682
}
683
684
/**
685
 * Get Earnings By Date
686
 *
687
 * @since  1.0
688
 *
689
 * @param  int $day Day number. Default is null.
690
 * @param  int $month_num Month number. Default is null.
691
 * @param  int $year Year number. Default is null.
692
 * @param  int $hour Hour number. Default is null.
693
 *
694
 * @return int $earnings  Earnings
0 ignored issues
show
Documentation introduced by
Should the return type not be double?

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

Loading history...
695
 */
696
function give_get_earnings_by_date( $day = null, $month_num, $year = null, $hour = null ) {
697
698
	// This is getting deprecated soon. Use Give_Payment_Stats with the get_earnings() method instead.
699
	global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
700
701
	$args = array(
702
		'post_type'              => 'give_payment',
703
		'nopaging'               => true,
704
		'year'                   => $year,
705
		'monthnum'               => $month_num,
706
		'post_status'            => array( 'publish' ),
707
		'fields'                 => 'ids',
708
		'update_post_term_cache' => false,
709
	);
710
	if ( ! empty( $day ) ) {
711
		$args['day'] = $day;
712
	}
713
714
	if ( ! empty( $hour ) ) {
715
		$args['hour'] = $hour;
716
	}
717
718
	$args = apply_filters( 'give_get_earnings_by_date_args', $args );
719
	$key  = Give_Cache::get_key( 'give_stats', $args );
720
721
	if ( ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'give-refresh-reports' ) ) {
722
		$earnings = false;
723
	} else {
724
		$earnings = Give_Cache::get( $key );
725
	}
726
727
	if ( false === $earnings ) {
728
		$sales    = get_posts( $args );
729
		$earnings = 0;
730
		if ( $sales ) {
731
			$sales = implode( ',', $sales );
732
733
			$earnings = $wpdb->get_var( "SELECT SUM(meta_value) FROM $wpdb->postmeta WHERE meta_key = '_give_payment_total' AND post_id IN ({$sales})" );
734
735
		}
736
		// Cache the results for one hour.
737
		Give_Cache::set( $key, $earnings, HOUR_IN_SECONDS );
738
	}
739
740
	return round( $earnings, 2 );
741
}
742
743
/**
744
 * Get Donations (sales) By Date
745
 *
746
 * @since  1.0
747
 *
748
 * @param  int $day Day number. Default is null.
749
 * @param  int $month_num Month number. Default is null.
750
 * @param  int $year Year number. Default is null.
751
 * @param  int $hour Hour number. Default is null.
752
 *
753
 * @return int $count     Sales
754
 */
755
function give_get_sales_by_date( $day = null, $month_num = null, $year = null, $hour = null ) {
756
757
	// This is getting deprecated soon. Use Give_Payment_Stats with the get_sales() method instead.
758
	$args = array(
759
		'post_type'              => 'give_payment',
760
		'nopaging'               => true,
761
		'year'                   => $year,
762
		'fields'                 => 'ids',
763
		'post_status'            => array( 'publish' ),
764
		'update_post_meta_cache' => false,
765
		'update_post_term_cache' => false,
766
	);
767
768
	$show_free = apply_filters( 'give_sales_by_date_show_free', true, $args );
769
770 5
	if ( false === $show_free ) {
771
		$args['meta_query'] = array(
772 5
			array(
773
				'key'     => '_give_payment_total',
774
				'value'   => 0,
775
				'compare' => '>',
776
				'type'    => 'NUMERIC',
777
			),
778
		);
779
	}
780
781
	if ( ! empty( $month_num ) ) {
782
		$args['monthnum'] = $month_num;
783 42
	}
784
785
	if ( ! empty( $day ) ) {
786 42
		$args['day'] = $day;
787
	}
788 42
789
	if ( ! empty( $hour ) ) {
790 42
		$args['hour'] = $hour;
791
	}
792 42
793
	$args = apply_filters( 'give_get_sales_by_date_args', $args );
794 42
795
	$key = Give_Cache::get_key( 'give_stats', $args );
796 42
797 42
	if ( ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'give-refresh-reports' ) ) {
798 42
		$count = false;
799 42
	} else {
800
		$count = Give_Cache::get( $key );
801 42
	}
802
803
	if ( false === $count ) {
804 42
		$sales = new WP_Query( $args );
805 42
		$count = (int) $sales->post_count;
806
		// Cache the results for one hour.
807
		Give_Cache::set( $key, $count, HOUR_IN_SECONDS );
808
	}
809
810
	return $count;
811
}
812
813 42
/**
814 42
 * Checks whether a payment has been marked as complete.
815 42
 *
816
 * @since  1.0
817 42
 *
818
 * @param  int $payment_id Payment ID to check against.
819
 *
820
 * @return bool $ret True if complete, false otherwise.
821
 */
822 42
function give_is_payment_complete( $payment_id ) {
823
	$payment = new Give_Payment( $payment_id );
824
825 42
	$ret = false;
826
827
	if ( $payment->ID > 0 ) {
828 42
829 42
		if ( (int) $payment_id === (int) $payment->ID && 'publish' == $payment->status ) {
830 42
			$ret = true;
831
		}
832 42
	}
833
834
	return apply_filters( 'give_is_payment_complete', $ret, $payment_id, $payment->post_status );
835
}
836 42
837
/**
838
 * Get Total Donations.
839
 *
840
 * @since  1.0
841
 *
842
 * @return int $count Total sales.
843
 */
844
function give_get_total_sales() {
845
846
	$payments = give_count_payments();
847
848
	return $payments->publish;
849 42
}
850 42
851 42
/**
852
 * Get Total Earnings
853 42
 *
854
 * @since  1.0
855
 *
856
 * @param bool $recalculate Recalculate earnings forcefully.
857
 *
858
 * @return float $total Total earnings.
859
 */
860
function give_get_total_earnings( $recalculate = false ) {
861
862
	$total = get_option( 'give_earnings_total', 0 );
863
864
	// Calculate total earnings.
865
	if ( ! $total || $recalculate ) {
866 19
		global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
867 19
868 19
		$total = (float) 0;
869
870
		$args = apply_filters( 'give_get_total_earnings_args', array(
871 19
			'offset' => 0,
872
			'number' => - 1,
873 19
			'status' => array( 'publish' ),
874
			'fields' => 'ids',
875
		) );
876
877
		$payments = give_get_payments( $args );
878
		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...
879
880
			/**
881
			 * If performing a donation, we need to skip the very last payment in the database,
882
			 * since it calls give_increase_total_earnings() on completion,
883
			 * which results in duplicated earnings for the very first donation.
884
			 */
885
			if ( did_action( 'give_update_payment_status' ) ) {
886
				array_pop( $payments );
887
			}
888 42
889
			if ( ! empty( $payments ) ) {
890 42
				$payments = implode( ',', $payments );
891
				$total    += $wpdb->get_var( "SELECT SUM(meta_value) FROM $wpdb->postmeta WHERE meta_key = '_give_payment_total' AND post_id IN({$payments})" );
892
			}
893
		}
894
895
		update_option( 'give_earnings_total', $total, 'no' );
896
	}
897
898
	if ( $total < 0 ) {
899
		$total = 0; // Don't ever show negative earnings.
900
	}
901
902
	return apply_filters( 'give_total_earnings', round( $total, give_currency_decimal_filter() ) );
903
}
904 18
905
/**
906 18
 * Increase the Total Earnings
907
 *
908
 * @since  1.0
909
 *
910
 * @param  int $amount The amount you would like to increase the total earnings by.
911
 *                       Default is 0.
912
 *
913
 * @return float $total  Total earnings.
914
 */
915
function give_increase_total_earnings( $amount = 0 ) {
916
	$total = give_get_total_earnings();
917
	$total += $amount;
918
	update_option( 'give_earnings_total', $total );
919
920
	return $total;
921
}
922
923
/**
924
 * Decrease the Total Earnings
925
 *
926
 * @since 1.0
927
 *
928
 * @param int $amount The amount you would like to decrease the total earnings by.
929
 *
930
 * @return float $total Total earnings.
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

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

Loading history...
931
 */
932
function give_decrease_total_earnings( $amount = 0 ) {
933
	$total = give_get_total_earnings();
934
	$total -= $amount;
935
	if ( $total < 0 ) {
936
		$total = 0;
937
	}
938
	update_option( 'give_earnings_total', $total );
939
940
	return $total;
941
}
942
943
/**
944
 * Get Payment Meta for a specific Payment
945
 *
946
 * @since 1.0
947
 *
948
 * @param int $payment_id Payment ID.
949
 * @param string $meta_key The meta key to pull.
950 42
 * @param bool $single Pull single meta entry or as an object.
951
 *
952 42
 * @return mixed $meta Payment Meta.
953
 */
954
function give_get_payment_meta( $payment_id = 0, $meta_key = '_give_payment_meta', $single = true ) {
955
	$payment = new Give_Payment( $payment_id );
956
957
	return $payment->get_meta( $meta_key, $single );
958
}
959
960
/**
961
 * Update the meta for a payment
962
 *
963
 * @param  int $payment_id Payment ID.
964
 * @param  string $meta_key Meta key to update.
965
 * @param  string $meta_value Value to update to.
966
 * @param  string $prev_value Previous value.
967
 *
968
 * @return mixed Meta ID if successful, false if unsuccessful.
969
 */
970
function give_update_payment_meta( $payment_id = 0, $meta_key = '', $meta_value = '', $prev_value = '' ) {
971
	$payment = new Give_Payment( $payment_id );
972
973
	return $payment->update_meta( $meta_key, $meta_value, $prev_value );
974
}
975
976
/**
977
 * Get the user_info Key from Payment Meta
978
 *
979
 * @since 1.0
980
 *
981
 * @param int $payment_id Payment ID.
982
 *
983
 * @return string $user_info User Info Meta Values.
0 ignored issues
show
Documentation introduced by
Should the return type not be array?

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

Loading history...
984
 */
985
function give_get_payment_meta_user_info( $payment_id ) {
986
	$payment = new Give_Payment( $payment_id );
987
988
	return $payment->user_info;
989
}
990
991
/**
992
 * Get the donations Key from Payment Meta
993
 *
994
 * Retrieves the form_id from a (Previously titled give_get_payment_meta_donations)
995
 *
996 31
 * @since 1.0
997
 *
998 31
 * @param int $payment_id Payment ID.
999
 *
1000
 * @return int $form_id Form ID.
0 ignored issues
show
Documentation introduced by
Should the return type not be string?

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

Loading history...
1001
 */
1002
function give_get_payment_form_id( $payment_id ) {
1003
	$payment = new Give_Payment( $payment_id );
1004
1005
	return $payment->form_id;
1006
}
1007
1008
/**
1009
 * Get the user email associated with a payment
1010
 *
1011
 * @since 1.0
1012
 *
1013
 * @param int $payment_id Payment ID.
1014
 *
1015
 * @return string $email User email.
1016
 */
1017
function give_get_payment_user_email( $payment_id ) {
1018
	$payment = new Give_Payment( $payment_id );
1019
1020
	return $payment->email;
1021
}
1022
1023
/**
1024
 * Is the payment provided associated with a user account
1025
 *
1026
 * @since  1.3
1027
 *
1028
 * @param  int $payment_id The payment ID.
1029
 *
1030
 * @return bool $is_guest_payment If the payment is associated with a user (false) or not (true)
1031
 */
1032
function give_is_guest_payment( $payment_id ) {
1033
	$payment_user_id  = give_get_payment_user_id( $payment_id );
1034
	$is_guest_payment = ! empty( $payment_user_id ) && $payment_user_id > 0 ? false : true;
1035
1036
	return (bool) apply_filters( 'give_is_guest_payment', $is_guest_payment, $payment_id );
1037
}
1038
1039
/**
1040
 * Get the user ID associated with a payment
1041
 *
1042
 * @since 1.3
1043
 *
1044
 * @param int $payment_id Payment ID.
1045
 *
1046
 * @return int $user_id User ID.
1047
 */
1048
function give_get_payment_user_id( $payment_id ) {
1049
	$payment = new Give_Payment( $payment_id );
1050
1051
	return $payment->user_id;
1052
}
1053
1054
/**
1055
 * Get the donor ID associated with a payment
1056
 *
1057
 * @since 1.0
1058
 *
1059
 * @param int $payment_id Payment ID.
1060
 *
1061
 * @return int $customer_id Customer ID.
1062
 */
1063
function give_get_payment_customer_id( $payment_id ) {
1064
	$payment = new Give_Payment( $payment_id );
1065
1066
	return $payment->customer_id;
1067
}
1068
1069
/**
1070
 * Get the IP address used to make a donation
1071
 *
1072
 * @since 1.0
1073
 *
1074
 * @param int $payment_id Payment ID.
1075
 *
1076
 * @return string $ip User IP.
1077
 */
1078
function give_get_payment_user_ip( $payment_id ) {
1079
	$payment = new Give_Payment( $payment_id );
1080
1081
	return $payment->ip;
1082
}
1083
1084
/**
1085
 * Get the date a payment was completed
1086 52
 *
1087
 * @since 1.0
1088 52
 *
1089
 * @param int $payment_id Payment ID.
1090
 *
1091
 * @return string $date The date the payment was completed.
1092
 */
1093
function give_get_payment_completed_date( $payment_id = 0 ) {
1094
	$payment = new Give_Payment( $payment_id );
1095
1096
	return $payment->completed_date;
1097
}
1098
1099
/**
1100
 * Get the gateway associated with a payment
1101
 *
1102
 * @since 1.0
1103
 *
1104
 * @param int $payment_id Payment ID.
1105
 *
1106
 * @return string $gateway Gateway.
1107
 */
1108
function give_get_payment_gateway( $payment_id ) {
1109
	$payment = new Give_Payment( $payment_id );
1110
1111
	return $payment->gateway;
1112
}
1113
1114
/**
1115
 * Get the currency code a payment was made in
1116
 *
1117
 * @since 1.0
1118
 *
1119 20
 * @param int $payment_id Payment ID.
1120
 *
1121
 * @return string $currency The currency code.
1122
 */
1123 20
function give_get_payment_currency_code( $payment_id = 0 ) {
1124
	$payment = new Give_Payment( $payment_id );
1125
1126
	return $payment->currency;
1127 20
}
1128 20
1129 20
/**
1130
 * Get the currency name a payment was made in
1131 20
 *
1132
 * @since 1.0
1133 20
 *
1134
 * @param int $payment_id Payment ID.
1135
 *
1136
 * @return string $currency The currency name.
1137
 */
1138
function give_get_payment_currency( $payment_id = 0 ) {
1139
	$currency = give_get_payment_currency_code( $payment_id );
1140
1141
	return apply_filters( 'give_payment_currency', give_get_currency_name( $currency ), $payment_id );
1142
}
1143
1144
/**
1145
 * Get the key for a donation
1146 20
 *
1147
 * @since 1.0
1148
 *
1149
 * @param int $payment_id Payment ID.
1150 20
 *
1151 20
 * @return string $key Donation key.
1152 20
 */
1153
function give_get_payment_key( $payment_id = 0 ) {
1154 20
	$payment = new Give_Payment( $payment_id );
1155
1156 2
	return $payment->key;
1157
}
1158
1159
/**
1160
 * Get the payment order number
1161
 *
1162
 * This will return the payment ID if sequential order numbers are not enabled or the order number does not exist
1163 2
 *
1164
 * @since 1.0
1165
 *
1166 20
 * @param int $payment_id Payment ID.
1167 20
 *
1168 20
 * @return string $number Payment order number.
1169 20
 */
1170 20
function give_get_payment_number( $payment_id = 0 ) {
1171
	$payment = new Give_Payment( $payment_id );
1172 20
1173 20
	return $payment->number;
1174
}
1175 20
1176
/**
1177
 * Formats the payment number with the prefix and postfix
1178
 *
1179
 * @since  1.3
1180
 *
1181 20
 * @param  int $number The payment number to format.
1182
 *
1183
 * @return string      The formatted payment number.
1184
 */
1185
function give_format_payment_number( $number ) {
1186
1187 20
	if ( ! give_get_option( 'enable_sequential' ) ) {
1188 20
		return $number;
1189
	}
1190
1191
	if ( ! is_numeric( $number ) ) {
1192
		return $number;
1193 20
	}
1194
1195 20
	$prefix  = give_get_option( 'sequential_prefix' );
1196 2
	$number  = absint( $number );
1197 2
	$postfix = give_get_option( 'sequential_postfix' );
1198
1199 20
	$formatted_number = $prefix . $number . $postfix;
1200
1201
	return apply_filters( 'give_format_payment_number', $formatted_number, $prefix, $number, $postfix );
1202
}
1203
1204
/**
1205
 * Gets the next available order number
1206
 *
1207
 * This is used when inserting a new payment
1208
 *
1209
 * @since 1.0
1210
 * @return string $number The next available payment number.
1211
 */
1212
function give_get_next_payment_number() {
1213
1214
	if ( ! give_get_option( 'enable_sequential' ) ) {
1215
		return false;
1216
	}
1217
1218
	$number           = get_option( 'give_last_payment_number' );
1219
	$start            = give_get_option( 'sequential_start', 1 );
1220
	$increment_number = true;
1221
1222
	if ( false !== $number ) {
1223
1224
		if ( empty( $number ) ) {
1225
1226
			$number           = $start;
1227
			$increment_number = false;
1228
1229
		}
1230
	} else {
1231
1232
		// This case handles the first addition of the new option, as well as if it get's deleted for any reason.
1233
		$payments     = new Give_Payments_Query( array(
1234
			'number'  => 1,
1235
			'order'   => 'DESC',
1236
			'orderby' => 'ID',
1237
			'output'  => 'posts',
1238
			'fields'  => 'ids',
1239
		) );
1240
		$last_payment = $payments->get_payments();
1241
1242
		if ( ! empty( $last_payment ) ) {
1243
1244
			$number = give_get_payment_number( $last_payment[0] );
1245
1246
		}
1247
1248
		if ( ! empty( $number ) && $number !== (int) $last_payment[0] ) {
1249
1250
			$number = give_remove_payment_prefix_postfix( $number );
1251
1252
		} else {
1253
1254
			$number           = $start;
1255
			$increment_number = false;
1256
		}
1257
	}
1258
1259
	$increment_number = apply_filters( 'give_increment_payment_number', $increment_number, $number );
1260
1261
	if ( $increment_number ) {
1262
		$number ++;
1263 52
	}
1264
1265 52
	return apply_filters( 'give_get_next_payment_number', $number );
1266
}
1267
1268
/**
1269
 * Given a given a number, remove the pre/postfix
1270
 *
1271
 * @since  1.3
1272
 *
1273
 * @param  string $number The formatted Current Number to increment.
1274
 *
1275
 * @return string The new Payment number without prefix and postfix.
1276
 */
1277
function give_remove_payment_prefix_postfix( $number ) {
1278
1279
	$prefix  = give_get_option( 'sequential_prefix' );
1280
	$postfix = give_get_option( 'sequential_postfix' );
1281
1282
	// Remove prefix.
1283
	$number = preg_replace( '/' . $prefix . '/', '', $number, 1 );
1284
1285
	// Remove the postfix.
1286
	$length      = strlen( $number );
1287
	$postfix_pos = strrpos( $number, $postfix );
1288
	if ( false !== $postfix_pos ) {
1289
		$number = substr_replace( $number, '', $postfix_pos, $length );
1290
	}
1291
1292
	// Ensure it's a whole number.
1293
	$number = intval( $number );
1294
1295
	return apply_filters( 'give_remove_payment_prefix_postfix', $number, $prefix, $postfix );
1296
1297
}
1298
1299
1300
/**
1301
 * Get Payment Amount
1302
 *
1303
 * Get the fully formatted payment amount. The payment amount is retrieved using give_get_payment_amount() and is then
1304
 * sent through give_currency_filter() and  give_format_amount() to format the amount correctly.
1305
 *
1306
 * @since       1.0
1307
 *
1308
 * @param int $payment_id Payment ID.
1309
 *
1310
 * @return string $amount Fully formatted payment amount.
1311
 */
1312
function give_payment_amount( $payment_id = 0 ) {
1313
	$amount = give_get_payment_amount( $payment_id );
1314
1315
	return give_currency_filter( give_format_amount( $amount ), give_get_payment_currency_code( $payment_id ) );
1316
}
1317
1318
/**
1319
 * Get the amount associated with a payment
1320
 *
1321
 * @access public
1322
 * @since  1.0
1323
 *
1324
 * @param int $payment_id Payment ID.
1325
 *
1326
 * @return mixed|void
1327
 */
1328
function give_get_payment_amount( $payment_id ) {
1329
1330
	$payment = new Give_Payment( $payment_id );
1331
1332
	return apply_filters( 'give_payment_amount', floatval( $payment->total ), $payment_id );
1333
}
1334
1335
/**
1336
 * Payment Subtotal
1337
 *
1338
 * Retrieves subtotal for payment (this is the amount before fees) and then returns a full formatted amount. This
1339
 * function essentially calls give_get_payment_subtotal()
1340
 *
1341
 * @since 1.5
1342
 *
1343
 * @param int $payment_id Payment ID.
1344
 *
1345
 * @see   give_get_payment_subtotal()
1346
 *
1347 18
 * @return array Fully formatted payment subtotal.
1348
 */
1349
function give_payment_subtotal( $payment_id = 0 ) {
1350
	$subtotal = give_get_payment_subtotal( $payment_id );
1351 18
1352
	return give_currency_filter( give_format_amount( $subtotal ), give_get_payment_currency_code( $payment_id ) );
1353 18
}
1354
1355
/**
1356
 * Get Payment Subtotal
1357
 *
1358
 * Retrieves subtotal for payment (this is the amount before fees) and then returns a non formatted amount.
1359
 *
1360
 * @since 1.5
1361
 *
1362
 * @param int $payment_id Payment ID.
1363
 *
1364
 * @return float $subtotal Subtotal for payment (non formatted).
1365
 */
1366
function give_get_payment_subtotal( $payment_id = 0 ) {
1367
	$payment = new G_Payment( $payment_id );
1368
1369
	return $payment->subtotal;
1370
}
1371
1372
/**
1373
 * Retrieves arbitrary fees for the payment
1374
 *
1375
 * @since 1.5
1376
 *
1377
 * @param int $payment_id Payment ID.
1378
 * @param string $type Fee type.
1379
 *
1380
 * @return mixed array if payment fees found, false otherwise.
1381
 */
1382
function give_get_payment_fees( $payment_id = 0, $type = 'all' ) {
1383
	$payment = new Give_Payment( $payment_id );
1384
1385
	return $payment->get_fees( $type );
1386
}
1387
1388
/**
1389
 * Retrieves the donation ID
1390
 *
1391
 * @since  1.0
1392
 *
1393
 * @param int $payment_id Payment ID.
1394
 *
1395
 * @return string The donation ID.
1396
 */
1397
function give_get_payment_transaction_id( $payment_id = 0 ) {
1398
	$payment = new Give_Payment( $payment_id );
1399
1400
	return $payment->transaction_id;
1401
}
1402
1403
/**
1404
 * Sets a Transaction ID in post meta for the given Payment ID.
1405
 *
1406
 * @since  1.0
1407
 *
1408
 * @param int $payment_id Payment ID.
1409
 * @param string $transaction_id The transaction ID from the gateway.
1410
 *
1411
 * @return bool|mixed
1412
 */
1413
function give_set_payment_transaction_id( $payment_id = 0, $transaction_id = '' ) {
1414
1415
	if ( empty( $payment_id ) || empty( $transaction_id ) ) {
1416
		return false;
1417
	}
1418
1419
	$transaction_id = apply_filters( 'give_set_payment_transaction_id', $transaction_id, $payment_id );
1420
1421
	return give_update_payment_meta( $payment_id, '_give_payment_transaction_id', $transaction_id );
1422
}
1423
1424
/**
1425
 * Retrieve the donation ID based on the key
1426
 *
1427
 * @since 1.0
1428
 * @global object $wpdb Used to query the database using the WordPress Database API.
1429
 *
1430
 * @param string $key the key to search for.
1431
 *
1432
 * @return int $purchase Donation ID.
1433
 */
1434
function give_get_purchase_id_by_key( $key ) {
1435
	global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1436
1437
	$purchase = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_give_payment_purchase_key' AND meta_value = %s LIMIT 1", $key ) );
1438
1439
	if ( $purchase != null ) {
1440
		return $purchase;
1441
	}
1442 52
1443
	return 0;
1444
}
1445
1446 52
1447
/**
1448 52
 * Retrieve the donation ID based on the transaction ID
1449 52
 *
1450 52
 * @since 1.3
1451 52
 * @global object $wpdb Used to query the database using the WordPress Database API.
1452 52
 *
1453 52
 * @param string $key The transaction ID to search for.
1454 52
 *
1455 52
 * @return int $purchase Donation ID.
1456 52
 */
1457 52
function give_get_purchase_id_by_transaction_id( $key ) {
1458 52
	global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1459 52
1460
	$purchase = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_give_payment_transaction_id' AND meta_value = %s LIMIT 1", $key ) );
1461
1462 52
	if ( $purchase != null ) {
1463
		return $purchase;
1464 52
	}
1465
1466 52
	return 0;
1467
}
1468
1469
/**
1470
 * Retrieve all notes attached to a donation
1471
 *
1472
 * @since 1.0
1473
 *
1474
 * @param int $payment_id The donation ID to retrieve notes for.
1475
 * @param string $search Search for notes that contain a search term.
1476
 *
1477
 * @return array $notes Donation Notes
1478
 */
1479
function give_get_payment_notes( $payment_id = 0, $search = '' ) {
1480
1481
	if ( empty( $payment_id ) && empty( $search ) ) {
1482
		return false;
1483
	}
1484
1485
	remove_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1486
	remove_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10 );
1487
1488
	$notes = get_comments( array( 'post_id' => $payment_id, 'order' => 'ASC', 'search' => $search ) );
1489
1490
	add_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1491
	add_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10, 2 );
1492
1493
	return $notes;
1494
}
1495
1496
1497
/**
1498
 * Add a note to a payment
1499
 *
1500
 * @since 1.0
1501
 *
1502
 * @param int $payment_id The payment ID to store a note for.
1503
 * @param string $note The note to store.
1504
 *
1505
 * @return int The new note ID
1506
 */
1507
function give_insert_payment_note( $payment_id = 0, $note = '' ) {
1508
	if ( empty( $payment_id ) ) {
1509
		return false;
1510
	}
1511
1512
	/**
1513
	 * Fires before inserting payment note.
1514
	 *
1515
	 * @since 1.0
1516
	 *
1517
	 * @param int $payment_id Payment ID.
1518
	 * @param string $note The note.
1519
	 */
1520
	do_action( 'give_pre_insert_payment_note', $payment_id, $note );
1521
1522
	$note_id = wp_insert_comment( wp_filter_comment( array(
1523
		'comment_post_ID'      => $payment_id,
1524
		'comment_content'      => $note,
1525
		'user_id'              => is_admin() ? get_current_user_id() : 0,
1526
		'comment_date'         => current_time( 'mysql' ),
1527
		'comment_date_gmt'     => current_time( 'mysql', 1 ),
1528
		'comment_approved'     => 1,
1529
		'comment_parent'       => 0,
1530
		'comment_author'       => '',
1531
		'comment_author_IP'    => '',
1532
		'comment_author_url'   => '',
1533
		'comment_author_email' => '',
1534
		'comment_type'         => 'give_payment_note',
1535
1536
	) ) );
1537
1538
	/**
1539
	 * Fires after payment note inserted.
1540
	 *
1541
	 * @since 1.0
1542
	 *
1543
	 * @param int $note_id Note ID.
1544
	 * @param int $payment_id Payment ID.
1545
	 * @param string $note The note.
1546
	 */
1547
	do_action( 'give_insert_payment_note', $note_id, $payment_id, $note );
1548
1549
	return $note_id;
1550
}
1551
1552
/**
1553
 * Deletes a payment note
1554
 *
1555
 * @since 1.0
1556
 *
1557
 * @param int $comment_id The comment ID to delete.
1558
 * @param int $payment_id The payment ID the note is connected to.
1559
 *
1560
 * @return bool True on success, false otherwise.
1561
 */
1562
function give_delete_payment_note( $comment_id = 0, $payment_id = 0 ) {
1563
	if ( empty( $comment_id ) ) {
1564
		return false;
1565
	}
1566
1567
	/**
1568
	 * Fires before deleting donation note.
1569
	 *
1570
	 * @since 1.0
1571
	 *
1572
	 * @param int $comment_id Note ID.
1573
	 * @param int $payment_id Payment ID.
1574
	 */
1575
	do_action( 'give_pre_delete_payment_note', $comment_id, $payment_id );
1576
1577
	$ret = wp_delete_comment( $comment_id, true );
1578
1579
	/**
1580
	 * Fires after donation note deleted.
1581
	 *
1582
	 * @since 1.0
1583
	 *
1584
	 * @param int $comment_id Note ID.
1585
	 * @param int $payment_id Payment ID.
1586
	 */
1587
	do_action( 'give_post_delete_payment_note', $comment_id, $payment_id );
1588
1589
	return $ret;
1590
}
1591
1592
/**
1593
 * Gets the payment note HTML
1594
 *
1595
 * @since 1.0
1596
 *
1597
 * @param object|int $note The comment object or ID.
1598
 * @param int $payment_id The payment ID the note is connected to.
1599
 *
1600
 * @return string
1601
 */
1602
function give_get_payment_note_html( $note, $payment_id = 0 ) {
1603
1604
	if ( is_numeric( $note ) ) {
1605
		$note = get_comment( $note );
1606
	}
1607
1608
	if ( ! empty( $note->user_id ) ) {
1609
		$user = get_userdata( $note->user_id );
1610
		$user = $user->display_name;
1611
	} else {
1612
		$user = esc_html__( 'System', 'give' );
1613
	}
1614
1615
	$date_format = give_date_format() . ', ' . get_option( 'time_format' );
1616
1617
	$delete_note_url = wp_nonce_url( add_query_arg( array(
1618
		'give-action' => 'delete_payment_note',
1619
		'note_id'     => $note->comment_ID,
1620
		'payment_id'  => $payment_id,
1621
	) ),
1622
		'give_delete_payment_note_' . $note->comment_ID
1623
	);
1624
1625
	$note_html = '<div class="give-payment-note" id="give-payment-note-' . $note->comment_ID . '">';
1626
	$note_html .= '<p>';
1627
	$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/>';
1628
	$note_html .= $note->comment_content;
1629
	$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="' . esc_attr__( 'Delete this donation note.', 'give' ) . '">' . esc_html__( 'Delete', 'give' ) . '</a>';
1630
	$note_html .= '</p>';
1631
	$note_html .= '</div>';
1632
1633
	return $note_html;
1634
1635
}
1636
1637
/**
1638
 * Exclude notes (comments) on give_payment post type from showing in Recent
1639
 * Comments widgets
1640
 *
1641
 * @since 1.0
1642
 *
1643
 * @param object $query WordPress Comment Query Object.
1644
 *
1645
 * @return void
1646
 */
1647
function give_hide_payment_notes( $query ) {
1648
	if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.1', '>=' ) ) {
1649
		$types = isset( $query->query_vars['type__not_in'] ) ? $query->query_vars['type__not_in'] : array();
1650
		if ( ! is_array( $types ) ) {
1651
			$types = array( $types );
1652
		}
1653
		$types[]                           = 'give_payment_note';
1654
		$query->query_vars['type__not_in'] = $types;
1655
	}
1656
}
1657
1658
add_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1659
1660
/**
1661
 * Exclude notes (comments) on give_payment post type from showing in Recent Comments widgets
1662
 *
1663
 * @since 1.0
1664
 *
1665
 * @param array $clauses Comment clauses for comment query.
1666
 * @param object $wp_comment_query WordPress Comment Query Object.
1667
 *
1668
 * @return array $clauses Updated comment clauses.
1669
 */
1670
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...
1671
	if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.1', '<' ) ) {
1672
		$clauses['where'] .= ' AND comment_type != "give_payment_note"';
1673
	}
1674
1675
	return $clauses;
1676
}
1677
1678
add_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10, 2 );
1679
1680
1681
/**
1682
 * Exclude notes (comments) on give_payment post type from showing in comment feeds
1683
 *
1684
 * @since 1.0
1685
 *
1686
 * @param string $where
1687
 * @param object $wp_comment_query WordPress Comment Query Object.
1688
 *
1689
 * @return string $where
1690
 */
1691
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...
1692
	global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1693
1694
	$where .= $wpdb->prepare( ' AND comment_type != %s', 'give_payment_note' );
1695
1696
	return $where;
1697
}
1698
1699
add_filter( 'comment_feed_where', 'give_hide_payment_notes_from_feeds', 10, 2 );
1700
1701
1702
/**
1703
 * Remove Give Comments from the wp_count_comments function
1704
 *
1705
 * @access public
1706
 * @since  1.0
1707
 *
1708 42
 * @param array $stats (empty from core filter).
1709 42
 * @param int $post_id Post ID.
1710 42
 *
1711
 * @return array Array of comment counts.
1712 42
 */
1713
function give_remove_payment_notes_in_comment_counts( $stats, $post_id ) {
1714
	global $wpdb, $pagenow;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1715
1716 42
	if ( 'index.php' != $pagenow ) {
1717
		return $stats;
1718 34
	}
1719 34
1720 34
	$post_id = (int) $post_id;
1721 34
1722
	if ( apply_filters( 'give_count_payment_notes_in_comments', false ) ) {
1723 34
		return $stats;
1724
	}
1725
1726
	$stats = wp_cache_get( "comments-{$post_id}", 'counts' );
1727
1728
	if ( false !== $stats ) {
1729 34
		return $stats;
1730
	}
1731
1732 34
	$where = 'WHERE comment_type != "give_payment_note"';
1733
1734 34
	if ( $post_id > 0 ) {
1735
		$where .= $wpdb->prepare( ' AND comment_post_ID = %d', $post_id );
1736 42
	}
1737
1738
	$count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} {$where} GROUP BY comment_approved", ARRAY_A );
1739
1740
	$total    = 0;
1741
	$approved = array(
1742
		'0'            => 'moderated',
1743
		'1'            => 'approved',
1744
		'spam'         => 'spam',
1745
		'trash'        => 'trash',
1746
		'post-trashed' => 'post-trashed',
1747
	);
1748
	foreach ( (array) $count as $row ) {
1749
		// Don't count post-trashed toward totals.
1750
		if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] ) {
1751
			$total += $row['num_comments'];
1752 52
		}
1753
		if ( isset( $approved[ $row['comment_approved'] ] ) ) {
1754 52
			$stats[ $approved[ $row['comment_approved'] ] ] = $row['num_comments'];
1755
		}
1756 32
	}
1757
1758 32
	$stats['total_comments'] = $total;
1759
	foreach ( $approved as $key ) {
1760 32
		if ( empty( $stats[ $key ] ) ) {
1761
			$stats[ $key ] = 0;
1762
		}
1763 32
	}
1764
1765 32
	$stats = (object) $stats;
1766
	wp_cache_set( "comments-{$post_id}", $stats, 'counts' );
1767 32
1768
	return $stats;
1769 32
}
1770
1771 32
add_filter( 'wp_count_comments', 'give_remove_payment_notes_in_comment_counts', 10, 2 );
1772
1773 52
1774
/**
1775
 * Filter where older than one week
1776
 *
1777
 * @access public
1778
 * @since  1.0
1779
 *
1780
 * @param string $where Where clause.
1781
 *
1782
 * @return string $where Modified where clause.
1783
 */
1784
function give_filter_where_older_than_week( $where = '' ) {
1785
	// Payments older than one week.
1786
	$start = date( 'Y-m-d', strtotime( '-7 days' ) );
1787
	$where .= " AND post_date <= '{$start}'";
1788
1789
	return $where;
1790
}
1791
1792
1793
/**
1794
 * Get Payment Form ID.
1795
 *
1796
 * Retrieves the form title and appends the level name if present.
1797
 *
1798
 * @since 1.5
1799
 *
1800
 * @param array $payment_meta Payment meta data.
1801
 * @param bool $only_level If set to true will only return the level name if multi-level enabled.
1802
 * @param string $separator The separator between the .
1803
 *
1804
 * @return string $form_title Returns the full title if $only_level is false, otherwise returns the levels title.
1805
 */
1806
function give_get_payment_form_title( $payment_meta, $only_level = false, $separator = '' ) {
1807
1808
	$form_id    = isset( $payment_meta['form_id'] ) ? $payment_meta['form_id'] : 0;
1809
	$price_id   = isset( $payment_meta['price_id'] ) ? $payment_meta['price_id'] : null;
1810
	$form_title = isset( $payment_meta['form_title'] ) ? $payment_meta['form_title'] : '';
1811
1812
	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...
1813
		$form_title = '';
1814
	}
1815
1816
	//If multi-level, append to the form title.
1817
	if ( give_has_variable_prices( $form_id ) ) {
1818
1819
		//Only add separator if there is a form title.
1820
		if ( ! empty( $form_title ) ) {
1821
			$form_title .= ' ' . $separator . ' ';
1822
		}
1823
1824
		$form_title .= '<span class="donation-level-text-wrap">';
1825
1826
		if ( $price_id == 'custom' ) {
1827
			$custom_amount_text = get_post_meta( $form_id, '_give_custom_amount_text', true );
1828
			$form_title         .= ! empty( $custom_amount_text ) ? $custom_amount_text : __( 'Custom Amount', 'give' );
1829
		} else {
1830
			$form_title .= give_get_price_option_name( $form_id, $price_id );
1831
		}
1832
1833
		$form_title .= '</span>';
1834
1835
	}
1836
1837
	return apply_filters( 'give_get_payment_form_title', $form_title, $payment_meta );
1838
1839
}
1840
1841
/**
1842
 * Get Price ID
1843
 *
1844
 * Retrieves the Price ID when provided a proper form ID and price (donation) total
1845
 *
1846
 * @param int $form_id Form ID.
1847
 * @param string $price Price ID.
1848
 *
1849
 * @return string $price_id
1850
 */
1851
function give_get_price_id( $form_id, $price ) {
1852
1853
	$price_id = 0;
1854
1855
	if ( give_has_variable_prices( $form_id ) ) {
1856
1857
		$levels = maybe_unserialize( get_post_meta( $form_id, '_give_donation_levels', true ) );
1858
1859
		foreach ( $levels as $level ) {
1860
1861
			$level_amount = (float) give_sanitize_amount( $level['_give_amount'] );
1862
1863
			// Check that this indeed the recurring price.
1864
			if ( $level_amount == $price ) {
1865
1866
				$price_id = $level['_give_id']['level_id'];
1867
1868
			}
1869
		}
1870
	}
1871
1872
	return $price_id;
1873
1874
}
1875
1876
/**
1877
 * Get/Print give form dropdown html
1878
 *
1879
 * This function is wrapper to public method forms_dropdown of Give_HTML_Elements class to get/print form dropdown html.
1880
 * Give_HTML_Elements is defined in includes/class-give-html-elements.php.
1881
 *
1882
 * @since 1.6
1883
 *
1884
 * @param array $args Arguments for form dropdown.
1885
 * @param bool $echo This parameter decides if print form dropdown html output or not.
1886
 *
1887
 * @return string|void
1888
 */
1889
function give_get_form_dropdown( $args = array(), $echo = false ) {
1890
	$form_dropdown_html = Give()->html->forms_dropdown( $args );
1891
1892
	if ( ! $echo ) {
1893
		return $form_dropdown_html;
1894
	}
1895
1896
	echo $form_dropdown_html;
1897
}
1898
1899
/**
1900
 * Get/Print give form variable price dropdown html
1901
 *
1902
 * @since 1.6
1903
 *
1904
 * @param array $args Arguments for form dropdown.
1905
 * @param bool $echo This parameter decide if print form dropdown html output or not.
1906
 *
1907
 * @return string|bool
0 ignored issues
show
Documentation introduced by
Should the return type not be false|string|null?

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

Loading history...
1908
 */
1909
function give_get_form_variable_price_dropdown( $args = array(), $echo = false ) {
1910
1911
	// Check for give form id.
1912
	if ( empty( $args['id'] ) ) {
1913
		return false;
1914
	}
1915
1916
	$form = new Give_Donate_Form( $args['id'] );
1917
1918
	// Check if form has variable prices or not.
1919
	if ( ! $form->ID || ! $form->has_variable_prices() ) {
1920
		return false;
1921
	}
1922
1923
	$variable_prices        = $form->get_prices();
1924
	$variable_price_options = array();
1925
1926
	// Check if multi donation form support custom donation or not.
1927
	if ( $form->is_custom_price_mode() ) {
1928
		$variable_price_options['custom'] = _x( 'Custom', 'custom donation dropdown item', 'give' );
1929
	}
1930
1931
	// Get variable price and ID from variable price array.
1932
	foreach ( $variable_prices as $variable_price ) {
1933
		$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'] ) );
1934
	}
1935
1936
	// Update options.
1937
	$args = array_merge( $args, array( 'options' => $variable_price_options ) );
1938
1939
	// Generate select html.
1940
	$form_dropdown_html = Give()->html->select( $args );
1941
1942
	if ( ! $echo ) {
1943
		return $form_dropdown_html;
1944
	}
1945
1946
	echo $form_dropdown_html;
1947
}
1948
1949
/**
1950
 * Get the price_id from the payment meta.
1951
 *
1952
 * Some gateways use `give_price_id` and others were using just `price_id`;
1953
 * This checks for the difference and falls back to retrieving it from the form as a last resort.
1954
 *
1955
 * @since 1.8.6
1956
 *
1957
 * @param $payment_meta
1958
 *
1959
 * @return string
1960
 */
1961
function give_get_payment_meta_price_id( $payment_meta ) {
1962
1963
	if ( isset( $payment_meta['give_price_id'] ) ) {
1964
		$price_id = $payment_meta['give_price_id'];
1965
	} elseif ( isset( $payment_meta['price_id'] ) ) {
1966
		$price_id = $payment_meta['price_id'];
1967
	} else {
1968
		$price_id = give_get_price_id( $payment_meta['give_form_id'], $payment_meta['price'] );
1969
	}
1970
1971
	return apply_filters( 'give_get_payment_meta_price_id', $price_id );
1972
1973
}