Test Failed
Pull Request — master (#2482)
by Devin
05:37
created

functions.php ➔ give_payment_amount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 5
ccs 0
cts 0
cp 0
crap 2
rs 9.4285
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 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 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...
88
			$payment = give_get_payments( array(
89
				'meta_key'       => '_give_payment_purchase_key',
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
90
				'meta_value'     => $value,
0 ignored issues
show
introduced by
Detected usage of meta_value, possible slow query.
Loading history...
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 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...
102
			$payment = give_get_payments( array(
103
				'meta_key'       => '_give_payment_number',
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
104
				'meta_value'     => $value,
0 ignored issues
show
introduced by
Detected usage of meta_value, possible slow query.
Loading history...
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
	}// End switch().
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
	/**
142 52
	 * Fire the filter on donation data before insert.
143 52
	 *
144 52
	 * @since 1.8.15
145 52
	 *
146 52
	 * @param array $payment_data Arguments passed.
147 52
	 */
148 52
	$payment_data = apply_filters( 'give_pre_insert_payment', $payment_data );
149 52
150 52
	$payment    = new Give_Payment();
151 52
	$gateway    = ! empty( $payment_data['gateway'] ) ? $payment_data['gateway'] : '';
152 52
	$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...
153 52
	$form_id    = isset( $payment_data['give_form_id'] ) ? $payment_data['give_form_id'] : 0;
154 52
	$price_id   = give_get_payment_meta_price_id( $payment_data );
155
	$form_title = isset( $payment_data['give_form_title'] ) ? $payment_data['give_form_title'] : get_the_title( $form_id );
156
157
	// Set properties.
158 52
	$payment->total          = $payment_data['price'];
159 52
	$payment->status         = ! empty( $payment_data['status'] ) ? $payment_data['status'] : 'pending';
160 52
	$payment->currency       = ! empty( $payment_data['currency'] ) ? $payment_data['currency'] : give_get_currency( $payment_data['give_form_id'], $payment_data );
161 52
	$payment->user_info      = $payment_data['user_info'];
162
	$payment->gateway        = $gateway;
163 52
	$payment->form_title     = $form_title;
164
	$payment->form_id        = $form_id;
165
	$payment->price_id       = $price_id;
166 52
	$payment->donor_id       = ( ! empty( $payment_data['donor_id'] ) ? $payment_data['donor_id'] : '' );
167
	$payment->user_id        = $payment_data['user_info']['id'];
168
	$payment->email          = $payment_data['user_email'];
169
	$payment->first_name     = $payment_data['user_info']['first_name'];
170
	$payment->last_name      = $payment_data['user_info']['last_name'];
171 52
	$payment->email          = $payment_data['user_info']['email'];
172 20
	$payment->ip             = give_get_ip();
173 20
	$payment->key            = $payment_data['purchase_key'];
174 20
	$payment->mode           = ( ! empty( $payment_data['mode'] ) ? (string) $payment_data['mode'] : ( give_is_test_mode() ? 'test' : 'live' ) );
175 20
	$payment->parent_payment = ! empty( $payment_data['parent'] ) ? absint( $payment_data['parent'] ) : '';
176
177
	// Add the donation.
178 52
	$args = array(
179
		'price'    => $payment->total,
180
		'price_id' => $payment->price_id,
181 52
	);
182
183
	$payment->add_donation( $payment->form_id, $args );
184 52
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
185
186
	// Set date if present.
187 52
	if ( isset( $payment_data['post_date'] ) ) {
188 52
		$payment->date = $payment_data['post_date'];
189
	}
190
191
	// Handle sequential payments.
192
	if ( give_get_option( 'enable_sequential' ) ) {
193
		$number          = give_get_next_payment_number();
194
		$payment->number = give_format_payment_number( $number );
195
		update_option( 'give_last_payment_number', $number );
196
	}
197
198
	// Save payment.
199
	$payment->save();
200
201
	/**
202
	 * Fires while inserting payments.
203
	 *
204
	 * @since 1.0
205
	 *
206
	 * @param int   $payment_id   The payment ID.
207
	 * @param array $payment_data Arguments passed.
208 35
	 */
209 35
	do_action( 'give_insert_payment', $payment->ID, $payment_data );
210 35
211
	// Return payment ID upon success.
212 35
	if ( ! empty( $payment->ID ) ) {
213
		return $payment->ID;
214
	}
215
216
	// Return false if no payment was inserted.
217
	return false;
218
219
}
220
221
/**
222
 * Create payment.
223
 *
224
 * @param $payment_data
225
 *
226
 * @return bool|int
227
 */
228
function give_create_payment( $payment_data ) {
229 31
230
	$form_id  = intval( $payment_data['post_data']['give-form-id'] );
231 31
	$price_id = isset( $payment_data['post_data']['give-price-id'] ) ? $payment_data['post_data']['give-price-id'] : '';
232 31
233 31
	// Collect payment data.
234 31
	$insert_payment_data = array(
235 31
		'price'           => $payment_data['price'],
236
		'give_form_title' => $payment_data['post_data']['give-form-title'],
237
		'give_form_id'    => $form_id,
238 31
		'give_price_id'   => $price_id,
239 31
		'date'            => $payment_data['date'],
240
		'user_email'      => $payment_data['user_email'],
241 31
		'purchase_key'    => $payment_data['purchase_key'],
242
		'currency'        => give_get_currency( $form_id, $payment_data ),
243 31
		'user_info'       => $payment_data['user_info'],
244 16
		'status'          => 'pending',
245 16
		'gateway'         => 'paypal',
246
	);
247 31
248
	/**
249
	 * Filter the payment params.
250 14
	 *
251
	 * @since 1.8
252 14
	 *
253
	 * @param array $insert_payment_data
254 14
	 */
255
	$insert_payment_data = apply_filters( 'give_create_payment', $insert_payment_data );
256
257
	// Record the pending payment.
258
	return give_insert_payment( $insert_payment_data );
259
}
260
261 14
/**
262
 * Updates a payment status.
263 31
 *
264
 * @param  int    $payment_id Payment ID.
265 31
 * @param  string $new_status New Payment Status. Default is 'publish'.
266
 *
267
 * @since  1.0
268 1
 *
269
 * @return bool
270 1
 */
271
function give_update_payment_status( $payment_id, $new_status = 'publish' ) {
272
273 31
	$updated = false;
274
	$payment = new Give_Payment( $payment_id );
275
276 31
	if ( $payment && $payment->ID > 0 ) {
277 31
278 31
		$payment->status = $new_status;
279
		$updated         = $payment->save();
280
281 31
	}
282
283 31
	return $updated;
284 31
}
285 31
286
287 31
/**
288 31
 * Deletes a Donation
289
 *
290
 * @param  int  $payment_id   Payment ID (default: 0).
291
 * @param  bool $update_donor If we should update the donor stats (default:true).
292
 *
293
 * @since  1.0
294
 * @global      $give_logs
295
 *
296
 * @return void
297
 */
298
function give_delete_donation( $payment_id = 0, $update_donor = true ) {
299
300
	global $give_logs;
301
302 20
	$payment  = new Give_Payment( $payment_id );
303
304
	// Bailout.
305
	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...
306
		return;
307 20
	}
308
309 20
	$amount   = give_donation_amount( $payment_id );
310 20
	$status   = $payment->post_status;
311
	$donor_id = give_get_payment_donor_id( $payment_id );
312 18
	$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...
313 18
314
	// Only undo donations that aren't these statuses.
315 20
	$dont_undo_statuses = apply_filters( 'give_undo_donation_statuses', array(
316 20
		'pending',
317
		'cancelled',
318 18
	) );
319 18
320
	if ( ! in_array( $status, $dont_undo_statuses ) ) {
321 20
		give_undo_donation( $payment_id );
322
	}
323
324
	// Only undo donations that aren't these statuses.
325
	$status_to_decrease_stats = apply_filters( 'give_decrease_donor_statuses', array( 'publish' ) );
326
327
	if ( in_array( $status, $status_to_decrease_stats ) ) {
328
329
		// Only decrease earnings if they haven't already been decreased (or were never increased for this payment).
330
		give_decrease_total_earnings( $amount );
331
332
		// @todo: Refresh only range related stat cache
333
		give_delete_donation_stats();
334
335
		if ( $donor->id && $update_donor ) {
336
337 6
			// Decrement the stats for the donor.
338
			$donor->decrease_donation_count();
339
			$donor->decrease_value( $amount );
340 6
341 6
		}
342 6
	}
343 6
344 6
	/**
345 6
	 * Fires before deleting payment.
346
	 *
347 6
	 * @param int $payment_id Payment ID.
348
	 *
349 6
	 * @since 1.0
350 6
	 */
351 6
	do_action( 'give_payment_delete', $payment_id );
352
353
	if ( $donor->id && $update_donor ) {
354 6
		// Remove the payment ID from the donor.
355
		$donor->remove_payment( $payment_id );
356
	}
357
358
	// Remove the payment.
359
	wp_delete_post( $payment_id, true );
360
361
	// Remove related sale log entries.
362
	$give_logs->delete_logs( null, 'sale', array(
363
		array(
364
			'key'   => '_give_log_payment_id',
365
			'value' => $payment_id,
366
		),
367
	) );
368
369
	/**
370
	 * Fires after payment deleted.
371
	 *
372
	 * @param int $payment_id Payment ID.
373 6
	 *
374
	 * @since 1.0
375
	 */
376
	do_action( 'give_payment_deleted', $payment_id );
377
}
378
379
/**
380
 * Undo Donation
381
 *
382
 * Undoes a donation, including the decrease of donations and earning stats.
383
 * Used for when refunding or deleting a donation.
384
 *
385
 * @param  int $payment_id Payment ID.
386
 *
387
 * @since  1.0
388
 *
389
 * @return void
390
 */
391
function give_undo_donation( $payment_id ) {
392
393
	$payment = new Give_Payment( $payment_id );
394
395
	$maybe_decrease_earnings = apply_filters( 'give_decrease_earnings_on_undo', true, $payment, $payment->form_id );
396
	if ( true === $maybe_decrease_earnings ) {
397
		// Decrease earnings.
398
		give_decrease_form_earnings( $payment->form_id, $payment->total );
399
	}
400
401
	$maybe_decrease_donations = apply_filters( 'give_decrease_donations_on_undo', true, $payment, $payment->form_id );
402
	if ( true === $maybe_decrease_donations ) {
403
		// Decrease donation count.
404
		give_decrease_donation_count( $payment->form_id );
405
	}
406
407
}
408
409
410
/**
411
 * Count Payments
412
 *
413
 * Returns the total number of payments recorded.
414
 *
415
 * @param  array $args Arguments passed.
416
 *
417
 * @since  1.0
418
 *
419
 * @return object $stats Contains the number of payments per payment status.
420 6
 */
421
function give_count_payments( $args = array() ) {
422
423
	global $wpdb;
424
425
	$defaults = array(
426 6
		'user'       => null,
427
		's'          => null,
428
		'start-date' => null,
429
		'end-date'   => null,
430
		'form_id'    => null,
431
	);
432
433
	$args = wp_parse_args( $args, $defaults );
434
435
	$select = 'SELECT p.post_status,count( * ) AS num_posts';
436
	$join   = '';
437
	$where  = "WHERE p.post_type = 'give_payment' AND p.post_status IN ('" . implode( "','", give_get_payment_status_keys() ) . "')";
438
439
	// Count payments for a specific user.
440
	if ( ! empty( $args['user'] ) ) {
441
442
		if ( is_email( $args['user'] ) ) {
443
			$field = 'email';
444
		} elseif ( is_numeric( $args['user'] ) ) {
445
			$field = 'id';
446
		} else {
447
			$field = '';
448 6
		}
449
450
		$join = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
451
452
		if ( ! empty( $field ) ) {
453
			$where .= "
454
				AND m.meta_key = '_give_payment_user_{$field}'
455
				AND m.meta_value = '{$args['user']}'";
456
		}
457
	} elseif ( ! empty( $args['donor'] ) ) {
458
459
		$join  = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
460
		$where .= "
461
			AND m.meta_key = '_give_payment_customer_id'
462
			AND m.meta_value = '{$args['donor']}'";
463
464
		// Count payments for a search.
465
	} elseif ( ! empty( $args['s'] ) ) {
466 6
467 6
		if ( is_email( $args['s'] ) || strlen( $args['s'] ) == 32 ) {
468
469
			if ( is_email( $args['s'] ) ) {
470 6
				$field = '_give_payment_user_email';
471 6
			} else {
472 6
				$field = '_give_payment_purchase_key';
473
			}
474 6
475
			$join  = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
476 6
			$where .= $wpdb->prepare( '
477
                AND m.meta_key = %s
478 6
                AND m.meta_value = %s', $field, $args['s'] );
479 6
480
		} elseif ( '#' == substr( $args['s'], 0, 1 ) ) {
481
482
			$search = str_replace( '#:', '', $args['s'] );
483 6
			$search = str_replace( '#', '', $search );
484
485 6
			$select = 'SELECT p.post_status,count( * ) AS num_posts ';
486 6
			$join   = '';
487 6
			$where  = $wpdb->prepare( 'WHERE p.post_type=%s  AND p.ID = %d ', 'give_payment', $search );
488 6
489 6
		} elseif ( is_numeric( $args['s'] ) ) {
490
491 6
			$join  = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
492 6
			$where .= $wpdb->prepare( "
493 6
				AND m.meta_key = '_give_payment_user_id'
494
				AND m.meta_value = %d", $args['s'] );
495 6
496
		} else {
497 6
			$search = $wpdb->esc_like( $args['s'] );
498
			$search = '%' . $search . '%';
499
500
			$where .= $wpdb->prepare( 'AND ((p.post_title LIKE %s) OR (p.post_content LIKE %s))', $search, $search );
501 6
		}// End if().
502 6
	}// End if().
503
504 6
	if ( ! empty( $args['form_id'] ) && is_numeric( $args['form_id'] ) ) {
505 6
506
		$join  = "LEFT JOIN $wpdb->postmeta m ON (p.ID = m.post_id)";
507 6
		$where .= $wpdb->prepare( '
508
                AND m.meta_key = %s
509
                AND m.meta_value = %s', '_give_payment_form_id', $args['form_id'] );
510
	}
511
512
	// Limit payments count by date.
513
	if ( ! empty( $args['start-date'] ) && false !== strpos( $args['start-date'], '/' ) ) {
514
515
		$date_parts = explode( '/', $args['start-date'] );
516
		$month      = ! empty( $date_parts[0] ) && is_numeric( $date_parts[0] ) ? $date_parts[0] : 0;
517
		$day        = ! empty( $date_parts[1] ) && is_numeric( $date_parts[1] ) ? $date_parts[1] : 0;
518
		$year       = ! empty( $date_parts[2] ) && is_numeric( $date_parts[2] ) ? $date_parts[2] : 0;
519
520
		$is_date = checkdate( $month, $day, $year );
521 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...
522
523
			$date  = new DateTime( $args['start-date'] );
524
			$where .= $wpdb->prepare( " AND p.post_date >= '%s'", $date->format( 'Y-m-d' ) );
525
526
		}
527
528
		// Fixes an issue with the payments list table counts when no end date is specified (with stats class).
529
		if ( empty( $args['end-date'] ) ) {
530
			$args['end-date'] = $args['start-date'];
531
		}
532
	}
533
534
	if ( ! empty( $args['end-date'] ) && false !== strpos( $args['end-date'], '/' ) ) {
535
536
		$date_parts = explode( '/', $args['end-date'] );
537
538
		$month = ! empty( $date_parts[0] ) ? $date_parts[0] : 0;
539
		$day   = ! empty( $date_parts[1] ) ? $date_parts[1] : 0;
540
		$year  = ! empty( $date_parts[2] ) ? $date_parts[2] : 0;
541
542
		$is_date = checkdate( $month, $day, $year );
543 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...
544
545
			$date  = new DateTime( $args['end-date'] );
546
			$where .= $wpdb->prepare( " AND p.post_date <= '%s'", $date->format( 'Y-m-d' ) );
547
548
		}
549
	}
550
551
	$query = "$select
552
		FROM $wpdb->posts p
553
		$join
554
		$where
555
		GROUP BY p.post_status
556
	";
557
558
	$cache_key = md5( $query );
559
560
	$count = wp_cache_get( $cache_key, 'counts' );
561
	if ( false !== $count ) {
562
		return $count;
563
	}
564
565
	$count = $wpdb->get_results( $query, ARRAY_A );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
566
567
	$stats    = array();
568
	$statuses = get_post_stati();
569
	if ( isset( $statuses['private'] ) && empty( $args['s'] ) ) {
570
		unset( $statuses['private'] );
571
	}
572
573
	foreach ( $statuses as $state ) {
574
		$stats[ $state ] = 0;
575
	}
576
577
	foreach ( (array) $count as $row ) {
578
579 52
		if ( 'private' == $row['post_status'] && empty( $args['s'] ) ) {
580 52
			continue;
581 52
		}
582 52
583 52
		$stats[ $row['post_status'] ] = $row['num_posts'];
584 52
	}
585 52
586 52
	$stats = (object) $stats;
587 52
	wp_cache_set( $cache_key, $stats, 'counts' );
588
589 52
	return $stats;
590
}
591
592
593
/**
594
 * Check For Existing Payment
595
 *
596
 * @param  int $payment_id Payment ID.
597
 *
598
 * @since  1.0
599
 *
600
 * @return bool $exists True if payment exists, false otherwise.
601 52
 */
602 52
function give_check_for_existing_payment( $payment_id ) {
603
	$exists  = false;
604 52
	$payment = new Give_Payment( $payment_id );
605
606
	if ( $payment_id === $payment->ID && 'publish' === $payment->status ) {
607
		$exists = true;
608
	}
609
610
	return $exists;
611
}
612
613
/**
614
 * Get Payment Status
615
 *
616
 * @param WP_Post|Give_Payment|int $payment      Payment object or payment ID.
617
 * @param bool                     $return_label Whether to return the translated status label instead of status value. Default false.
618
 *
619
 * @since 1.0
620
 *
621
 * @return bool|mixed True if payment status exists, false otherwise.
622
 */
623
function give_get_payment_status( $payment, $return_label = false ) {
624
625
	if ( is_numeric( $payment ) ) {
626
627
		$payment = new Give_Payment( $payment );
628
629
		if ( ! $payment->ID > 0 ) {
630
			return false;
631
		}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
632
633
	}
634
635
	if ( ! is_object( $payment ) || ! isset( $payment->post_status ) ) {
636
		return false;
637
	}
638
639
	$statuses = give_get_payment_statuses();
640
641
	if ( ! is_array( $statuses ) || empty( $statuses ) ) {
642
		return false;
643
	}
644
645
	// Get payment object if not already given.
646
	$payment = $payment instanceof Give_Payment ? $payment : new Give_Payment( $payment->ID );
647
648
	if ( array_key_exists( $payment->status, $statuses ) ) {
649
		if ( true === $return_label ) {
650
			// Return translated status label.
651
			return $statuses[ $payment->status ];
652
		} else {
653
			// Account that our 'publish' status is labeled 'Complete'
654
			$post_status = 'publish' === $payment->status ? 'Complete' : $payment->post_status;
655
656
			// Make sure we're matching cases, since they matter
657
			return array_search( strtolower( $post_status ), array_map( 'strtolower', $statuses ) );
658
		}
659
	}
660
661
	return false;
662
}
663
664
/**
665
 * Retrieves all available statuses for payments.
666
 *
667
 * @since  1.0
668
 *
669
 * @return array $payment_status All the available payment statuses.
670
 */
671
function give_get_payment_statuses() {
672
	$payment_statuses = array(
673
		'pending'     => __( 'Pending', 'give' ),
674
		'publish'     => __( 'Complete', 'give' ),
675
		'refunded'    => __( 'Refunded', 'give' ),
676
		'failed'      => __( 'Failed', 'give' ),
677
		'cancelled'   => __( 'Cancelled', 'give' ),
678
		'abandoned'   => __( 'Abandoned', 'give' ),
679
		'preapproval' => __( 'Pre-Approved', 'give' ),
680
		'processing'  => __( 'Processing', 'give' ),
681
		'revoked'     => __( 'Revoked', 'give' ),
682
	);
683
684
	return apply_filters( 'give_payment_statuses', $payment_statuses );
685
}
686
687
/**
688
 * Get Payment Status Keys
689
 *
690
 * Retrieves keys for all available statuses for payments
691
 *
692
 * @since 1.0
693
 *
694
 * @return array $payment_status All the available payment statuses.
695
 */
696
function give_get_payment_status_keys() {
697
	$statuses = array_keys( give_get_payment_statuses() );
698
	asort( $statuses );
699
700
	return array_values( $statuses );
701
}
702
703
/**
704
 * Get Earnings By Date
705
 *
706
 * @param int $day       Day number. Default is null.
707
 * @param int $month_num Month number. Default is null.
708
 * @param int $year      Year number. Default is null.
709
 * @param int $hour      Hour number. Default is null.
710
 *
711
 * @since 1.0
712
 *
713
 * @return int $earnings Earnings
714
 */
715
function give_get_earnings_by_date( $day = null, $month_num, $year = null, $hour = null ) {
716
717
	// This is getting deprecated soon. Use Give_Payment_Stats with the get_earnings() method instead.
718
	global $wpdb;
719
720
	$args = array(
721
		'post_type'              => 'give_payment',
722
		'nopaging'               => true,
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set nopaging to true ever.
Loading history...
723
		'year'                   => $year,
724
		'monthnum'               => $month_num,
725
		'post_status'            => array( 'publish' ),
726
		'fields'                 => 'ids',
727
		'update_post_term_cache' => false,
728
	);
729
	if ( ! empty( $day ) ) {
730
		$args['day'] = $day;
731
	}
732
733
	if ( isset( $hour ) ) {
734
		$args['hour'] = $hour;
735
	}
736
737
	$args = apply_filters( 'give_get_earnings_by_date_args', $args );
738
	$key  = Give_Cache::get_key( 'give_stats', $args );
739
740 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...
741
		$earnings = false;
742
	} else {
743
		$earnings = Give_Cache::get( $key );
744
	}
745
746
	if ( false === $earnings ) {
747
		$donations = get_posts( $args );
748
		$earnings  = 0;
749
		if ( $donations ) {
750
			$donations      = implode( ',', $donations );
751
			$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...
752
753
			/**
754
			 * Filter The earnings by dates.
755
			 *
756
			 * @since 1.8.17
757
			 *
758
			 * @param float $earning_totals Total earnings between the dates.
759
			 * @param array $donations      Donations lists.
760
			 * @param array $args           Donation query args.
761
			 */
762
			$earnings = apply_filters( 'give_get_earnings_by_date', $earning_totals, $donations, $args );
763
		}
764
		// Cache the results for one hour.
765
		Give_Cache::set( $key, $earnings, HOUR_IN_SECONDS );
766
	}
767
768
	return round( $earnings, 2 );
769
}
770 5
771
/**
772 5
 * Get Donations (sales) By Date
773
 *
774
 * @param int $day       Day number. Default is null.
775
 * @param int $month_num Month number. Default is null.
776
 * @param int $year      Year number. Default is null.
777
 * @param int $hour      Hour number. Default is null.
778
 *
779
 * @since 1.0
780
 *
781
 * @return int $count Sales
782
 */
783 42
function give_get_sales_by_date( $day = null, $month_num = null, $year = null, $hour = null ) {
784
785
	// This is getting deprecated soon. Use Give_Payment_Stats with the get_sales() method instead.
786 42
	$args = array(
787
		'post_type'              => 'give_payment',
788 42
		'nopaging'               => true,
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set nopaging to true ever.
Loading history...
789
		'year'                   => $year,
790 42
		'fields'                 => 'ids',
791
		'post_status'            => array( 'publish' ),
792 42
		'update_post_meta_cache' => false,
793
		'update_post_term_cache' => false,
794 42
	);
795
796 42
	$show_free = apply_filters( 'give_sales_by_date_show_free', true, $args );
797 42
798 42
	if ( false === $show_free ) {
799 42
		$args['meta_query'] = array(
0 ignored issues
show
introduced by
Detected usage of meta_query, possible slow query.
Loading history...
800
			array(
801 42
				'key'     => '_give_payment_total',
802
				'value'   => 0,
803
				'compare' => '>',
804 42
				'type'    => 'NUMERIC',
805 42
			),
806
		);
807
	}
808
809
	if ( ! empty( $month_num ) ) {
810
		$args['monthnum'] = $month_num;
811
	}
812
813 42
	if ( ! empty( $day ) ) {
814 42
		$args['day'] = $day;
815 42
	}
816
817 42
	if ( isset( $hour ) ) {
818
		$args['hour'] = $hour;
819
	}
820
821
	$args = apply_filters( 'give_get_sales_by_date_args', $args );
822 42
823
	$key = Give_Cache::get_key( 'give_stats', $args );
824
825 42 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...
826
		$count = false;
827
	} else {
828 42
		$count = Give_Cache::get( $key );
829 42
	}
830 42
831
	if ( false === $count ) {
832 42
		$donations = new WP_Query( $args );
833
		$count     = (int) $donations->post_count;
834
		// Cache the results for one hour.
835
		Give_Cache::set( $key, $count, HOUR_IN_SECONDS );
836 42
	}
837
838
	return $count;
839
}
840
841
/**
842
 * Checks whether a payment has been marked as complete.
843
 *
844
 * @param int $payment_id Payment ID to check against.
845
 *
846
 * @since 1.0
847
 *
848
 * @return bool $ret True if complete, false otherwise.
849 42
 */
850 42
function give_is_payment_complete( $payment_id ) {
851 42
	$payment = new Give_Payment( $payment_id );
852
853 42
	$ret = false;
854
855
	if ( $payment->ID > 0 ) {
856
857
		if ( (int) $payment_id === (int) $payment->ID && 'publish' == $payment->status ) {
858
			$ret = true;
859
		}
860
	}
861
862
	return apply_filters( 'give_is_payment_complete', $ret, $payment_id, $payment->post_status );
863
}
864
865
/**
866 19
 * Get Total Donations.
867 19
 *
868 19
 * @since 1.0
869
 *
870
 * @return int $count Total number of donations.
871 19
 */
872
function give_get_total_donations() {
873 19
874
	$payments = give_count_payments();
875
876
	return $payments->publish;
877
}
878
879
/**
880
 * Get Total Earnings
881
 *
882
 * @param bool $recalculate Recalculate earnings forcefully.
883
 *
884
 * @since 1.0
885
 *
886
 * @return float $total Total earnings.
887
 */
888 42
function give_get_total_earnings( $recalculate = false ) {
889
890 42
	$total = get_option( 'give_earnings_total', 0 );
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 18
905
		$payments = give_get_payments( $args );
906 18
		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 $wpdb->postmeta WHERE meta_key = '_give_payment_total' AND post_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 42
/**
951
 * Decrease the Total Earnings
952 42
 *
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 31
 */
997
function give_update_payment_meta( $payment_id = 0, $meta_key = '', $meta_value = '', $prev_value = '' ) {
998 31
	$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 52
 * @since 1.0
1087
 *
1088 52
 * @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 20
 */
1120
function give_get_payment_completed_date( $payment_id = 0 ) {
1121
	$payment = new Give_Payment( $payment_id );
1122
1123 20
	return $payment->completed_date;
1124
}
1125
1126
/**
1127 20
 * Get the gateway associated with a payment
1128 20
 *
1129 20
 * @param int $payment_id Payment ID.
1130
 *
1131 20
 * @since 1.0
1132
 *
1133 20
 * @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 20
 * @since 1.0
1147
 *
1148
 * @return string $currency The currency code.
1149
 */
1150 20
function give_get_payment_currency_code( $payment_id = 0 ) {
1151 20
	$payment = new Give_Payment( $payment_id );
1152 20
1153
	return $payment->currency;
1154 20
}
1155
1156 2
/**
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 2
 * @return string $currency The currency name.
1164
 */
1165
function give_get_payment_currency( $payment_id = 0 ) {
1166 20
	$currency = give_get_payment_currency_code( $payment_id );
1167 20
1168 20
	return apply_filters( 'give_payment_currency', give_get_currency_name( $currency ), $payment_id );
1169 20
}
1170 20
1171
/**
1172 20
 * Get the key for a donation
1173 20
 *
1174
 * @param int $payment_id Payment ID.
1175 20
 *
1176
 * @since 1.0
1177
 *
1178
 * @return string $key Donation key.
1179
 */
1180
function give_get_payment_key( $payment_id = 0 ) {
1181 20
	$payment = new Give_Payment( $payment_id );
1182
1183
	return $payment->key;
1184
}
1185
1186
/**
1187 20
 * Get the payment order number
1188 20
 *
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 20
 * @since 1.0
1194
 *
1195 20
 * @return string $number Payment order number.
1196 2
 */
1197 2
function give_get_payment_number( $payment_id = 0 ) {
1198
	$payment = new Give_Payment( $payment_id );
1199 20
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 52
			'order'   => 'DESC',
1264
			'orderby' => 'ID',
1265 52
			'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 Donation Amount
1329
 *
1330
 * Get the fully formatted or unformatted donation amount which is sent through give_currency_filter()
1331
 * and give_format_amount() to format the amount correctly in case of formatted amount.
1332
 *
1333
 * @param int|Give_Payment $donation    Donation ID or Donation Object.
1334
 * @param bool|array       $format_args Currency Formatting Arguments.
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, $format_args = false ) {
1342
	/* @var Give_Payment $donation */
1343
	if ( ! ( $donation instanceof Give_Payment ) ) {
1344
		$donation = new Give_Payment( absint( $donation ) );
1345
	}
1346
1347 18
	if ( ! is_array( $format_args ) ) {
1348
		$format_args = array(
1349
			'currency' => (bool) $format_args,
1350
			'amount'   => (bool) $format_args,
1351 18
		);
1352
	}
1353 18
1354
	$format_args = wp_parse_args(
1355
		$format_args,
1356
		array(
1357
			'currency' => false,
1358
			'amount'   => false,
1359
		)
1360
	);
1361
1362
	$amount           = $donation->total;
1363
	$formatted_amount = $amount;
1364
1365
	if ( $format_args['amount'] ) {
1366
		$formatted_amount = give_format_amount(
1367
			$amount,
1368
			array(
1369
				'sanitize' => false,
1370
				'currency' => $donation->currency,
1371
			)
1372
		);
1373
	}
1374
1375
	if ( $format_args['currency'] ) {
1376
		$formatted_amount = give_currency_filter( $formatted_amount, $donation->currency );
1377
	}
1378
1379
	/**
1380
	 * Filter Donation amount.
1381
	 *
1382
	 * @since 1.8.17
1383
	 *
1384
	 * @param string $formatted_amount Formatted/Un-formatted amount.
1385
	 * @param float  $amount           Donation amount.
1386
	 * @param int    $donation_id      Donation ID.
1387
	 */
1388
	return apply_filters( 'give_donation_amount', (string) $formatted_amount, $amount, $donation );
1389
}
1390
1391
/**
1392
 * Payment Subtotal
1393
 *
1394
 * Retrieves subtotal for payment and then returns a full formatted amount. This
1395
 * function essentially calls give_get_payment_subtotal()
1396
 *
1397
 * @param int $payment_id Payment ID.
1398
 *
1399
 * @since 1.5
1400
 *
1401
 * @see   give_get_payment_subtotal()
1402
 *
1403
 * @return array Fully formatted payment subtotal.
1404
 */
1405
function give_payment_subtotal( $payment_id = 0 ) {
1406
	$subtotal = give_get_payment_subtotal( $payment_id );
1407
1408
	return give_currency_filter( give_format_amount( $subtotal, array( 'sanitize' => false ) ), give_get_payment_currency_code( $payment_id ) );
1409
}
1410
1411
/**
1412
 * Get Payment Subtotal
1413
 *
1414
 * Retrieves subtotal for payment and then returns a non formatted amount.
1415
 *
1416
 * @param int $payment_id Payment ID.
1417
 *
1418
 * @since 1.5
1419
 *
1420
 * @return float $subtotal Subtotal for payment (non formatted).
1421
 */
1422
function give_get_payment_subtotal( $payment_id = 0 ) {
1423
	$payment = new Give_Payment( $payment_id );
1424
1425
	return $payment->subtotal;
1426
}
1427
1428
/**
1429
 * Retrieves the donation ID
1430
 *
1431
 * @param int $payment_id Payment ID.
1432
 *
1433
 * @since  1.0
1434
 *
1435
 * @return string The donation ID.
1436
 */
1437
function give_get_payment_transaction_id( $payment_id = 0 ) {
1438
	$payment = new Give_Payment( $payment_id );
1439
1440
	return $payment->transaction_id;
1441
}
1442 52
1443
/**
1444
 * Sets a Transaction ID in post meta for the given Payment ID.
1445
 *
1446 52
 * @param int    $payment_id     Payment ID.
1447
 * @param string $transaction_id The transaction ID from the gateway.
1448 52
 *
1449 52
 * @since  1.0
1450 52
 *
1451 52
 * @return bool|mixed
1452 52
 */
1453 52
function give_set_payment_transaction_id( $payment_id = 0, $transaction_id = '' ) {
1454 52
1455 52
	if ( empty( $payment_id ) || empty( $transaction_id ) ) {
1456 52
		return false;
1457 52
	}
1458 52
1459 52
	$transaction_id = apply_filters( 'give_set_payment_transaction_id', $transaction_id, $payment_id );
1460
1461
	return give_update_payment_meta( $payment_id, '_give_payment_transaction_id', $transaction_id );
1462 52
}
1463
1464 52
/**
1465
 * Retrieve the donation ID based on the key
1466 52
 *
1467
 * @param string  $key  the key to search for.
1468
 *
1469
 * @since 1.0
1470
 * @global object $wpdb Used to query the database using the WordPress Database API.
1471
 *
1472
 * @return int $purchase Donation ID.
1473
 */
1474 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...
1475
	global $wpdb;
1476
1477
	$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 ) );
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...
1478
1479
	if ( $purchase != null ) {
1480
		return $purchase;
1481
	}
1482
1483
	return 0;
1484
}
1485
1486
1487
/**
1488
 * Retrieve the donation ID based on the transaction ID
1489
 *
1490
 * @param string  $key  The transaction ID to search for.
1491
 *
1492
 * @since 1.3
1493
 * @global object $wpdb Used to query the database using the WordPress Database API.
1494
 *
1495
 * @return int $purchase Donation ID.
1496
 */
1497 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...
1498
	global $wpdb;
1499
1500
	$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 ) );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
1501
1502
	if ( $purchase != null ) {
1503
		return $purchase;
1504
	}
1505
1506
	return 0;
1507
}
1508
1509
/**
1510
 * Retrieve all notes attached to a donation
1511
 *
1512
 * @param int    $payment_id The donation ID to retrieve notes for.
1513
 * @param string $search     Search for notes that contain a search term.
1514
 *
1515
 * @since 1.0
1516
 *
1517
 * @return array $notes Donation Notes
1518
 */
1519
function give_get_payment_notes( $payment_id = 0, $search = '' ) {
1520
1521
	if ( empty( $payment_id ) && empty( $search ) ) {
1522
		return false;
1523
	}
1524
1525
	remove_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1526
	remove_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10 );
1527
1528
	$notes = get_comments( array(
1529
		'post_id' => $payment_id,
1530
		'order'   => 'ASC',
1531
		'search'  => $search,
1532
	) );
1533
1534
	add_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1535
	add_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10, 2 );
1536
1537
	return $notes;
1538
}
1539
1540
1541
/**
1542
 * Add a note to a payment
1543
 *
1544
 * @param int    $payment_id The payment ID to store a note for.
1545
 * @param string $note       The note to store.
1546
 *
1547
 * @since 1.0
1548
 *
1549
 * @return int The new note ID
1550
 */
1551
function give_insert_payment_note( $payment_id = 0, $note = '' ) {
1552
	if ( empty( $payment_id ) ) {
1553
		return false;
1554
	}
1555
1556
	/**
1557
	 * Fires before inserting payment note.
1558
	 *
1559
	 * @param int    $payment_id Payment ID.
1560
	 * @param string $note       The note.
1561
	 *
1562
	 * @since 1.0
1563
	 */
1564
	do_action( 'give_pre_insert_payment_note', $payment_id, $note );
1565
1566
	$note_id = wp_insert_comment( wp_filter_comment( array(
1567
		'comment_post_ID'      => $payment_id,
1568
		'comment_content'      => $note,
1569
		'user_id'              => is_admin() ? get_current_user_id() : 0,
1570
		'comment_date'         => current_time( 'mysql' ),
1571
		'comment_date_gmt'     => current_time( 'mysql', 1 ),
1572
		'comment_approved'     => 1,
1573
		'comment_parent'       => 0,
1574
		'comment_author'       => '',
1575
		'comment_author_IP'    => '',
1576
		'comment_author_url'   => '',
1577
		'comment_author_email' => '',
1578
		'comment_type'         => 'give_payment_note',
1579
1580
	) ) );
1581
1582
	/**
1583
	 * Fires after payment note inserted.
1584
	 *
1585
	 * @param int    $note_id    Note ID.
1586
	 * @param int    $payment_id Payment ID.
1587
	 * @param string $note       The note.
1588
	 *
1589
	 * @since 1.0
1590
	 */
1591
	do_action( 'give_insert_payment_note', $note_id, $payment_id, $note );
1592
1593
	return $note_id;
1594
}
1595
1596
/**
1597
 * Deletes a payment note
1598
 *
1599
 * @param int $comment_id The comment ID to delete.
1600
 * @param int $payment_id The payment ID the note is connected to.
1601
 *
1602
 * @since 1.0
1603
 *
1604
 * @return bool True on success, false otherwise.
1605
 */
1606
function give_delete_payment_note( $comment_id = 0, $payment_id = 0 ) {
1607
	if ( empty( $comment_id ) ) {
1608
		return false;
1609
	}
1610
1611
	/**
1612
	 * Fires before deleting donation note.
1613
	 *
1614
	 * @param int $comment_id Note ID.
1615
	 * @param int $payment_id Payment ID.
1616
	 *
1617
	 * @since 1.0
1618
	 */
1619
	do_action( 'give_pre_delete_payment_note', $comment_id, $payment_id );
1620
1621
	$ret = wp_delete_comment( $comment_id, true );
1622
1623
	/**
1624
	 * Fires after donation note deleted.
1625
	 *
1626
	 * @param int $comment_id Note ID.
1627
	 * @param int $payment_id Payment ID.
1628
	 *
1629
	 * @since 1.0
1630
	 */
1631
	do_action( 'give_post_delete_payment_note', $comment_id, $payment_id );
1632
1633
	return $ret;
1634
}
1635
1636
/**
1637
 * Gets the payment note HTML
1638
 *
1639
 * @param object|int $note       The comment object or ID.
1640
 * @param int        $payment_id The payment ID the note is connected to.
1641
 *
1642
 * @since 1.0
1643
 *
1644
 * @return string
1645
 */
1646
function give_get_payment_note_html( $note, $payment_id = 0 ) {
1647
1648
	if ( is_numeric( $note ) ) {
1649
		$note = get_comment( $note );
1650
	}
1651
1652
	if ( ! empty( $note->user_id ) ) {
1653
		$user = get_userdata( $note->user_id );
1654
		$user = $user->display_name;
1655
	} else {
1656
		$user = __( 'System', 'give' );
1657
	}
1658
1659
	$date_format = give_date_format() . ', ' . get_option( 'time_format' );
1660
1661
	$delete_note_url = wp_nonce_url( add_query_arg( array(
1662
		'give-action' => 'delete_payment_note',
1663
		'note_id'     => $note->comment_ID,
1664
		'payment_id'  => $payment_id,
1665
	) ), 'give_delete_payment_note_' . $note->comment_ID );
1666
1667
	$note_html = '<div class="give-payment-note" id="give-payment-note-' . $note->comment_ID . '">';
1668
	$note_html .= '<p>';
1669
	$note_html .= '<strong>' . $user . '</strong>&nbsp;&ndash;&nbsp;<span style="color:#aaa;font-style:italic;">' . date_i18n( $date_format, strtotime( $note->comment_date ) ) . '</span><br/>';
1670
	$note_html .= $note->comment_content;
1671
	$note_html .= '&nbsp;&ndash;&nbsp;<a href="' . esc_url( $delete_note_url ) . '" class="give-delete-payment-note" data-note-id="' . absint( $note->comment_ID ) . '" data-payment-id="' . absint( $payment_id ) . '" aria-label="' . __( 'Delete this donation note.', 'give' ) . '">' . __( 'Delete', 'give' ) . '</a>';
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw '__'
Loading history...
1672
	$note_html .= '</p>';
1673
	$note_html .= '</div>';
1674
1675
	return $note_html;
1676
1677
}
1678
1679
/**
1680
 * Exclude notes (comments) on give_payment post type from showing in Recent
1681
 * Comments widgets
1682
 *
1683
 * @param object $query WordPress Comment Query Object.
1684
 *
1685
 * @since 1.0
1686
 *
1687
 * @return void
1688
 */
1689
function give_hide_payment_notes( $query ) {
1690
	if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.1', '>=' ) ) {
1691
		$types = isset( $query->query_vars['type__not_in'] ) ? $query->query_vars['type__not_in'] : array();
1692
		if ( ! is_array( $types ) ) {
1693
			$types = array( $types );
1694
		}
1695
		$types[]                           = 'give_payment_note';
1696
		$query->query_vars['type__not_in'] = $types;
1697
	}
1698
}
1699
1700
add_action( 'pre_get_comments', 'give_hide_payment_notes', 10 );
1701
1702
/**
1703
 * Exclude notes (comments) on give_payment post type from showing in Recent Comments widgets
1704
 *
1705
 * @param array  $clauses          Comment clauses for comment query.
1706
 * @param object $wp_comment_query WordPress Comment Query Object.
1707
 *
1708 42
 * @since 1.0
1709 42
 *
1710 42
 * @return array $clauses Updated comment clauses.
1711
 */
1712 42
function give_hide_payment_notes_pre_41( $clauses, $wp_comment_query ) {
0 ignored issues
show
Unused Code introduced by
The parameter $wp_comment_query is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1713
	if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.1', '<' ) ) {
1714
		$clauses['where'] .= ' AND comment_type != "give_payment_note"';
1715
	}
1716 42
1717
	return $clauses;
1718 34
}
1719 34
1720 34
add_filter( 'comments_clauses', 'give_hide_payment_notes_pre_41', 10, 2 );
1721 34
1722
1723 34
/**
1724
 * Exclude notes (comments) on give_payment post type from showing in comment feeds
1725
 *
1726
 * @param string $where
1727
 * @param object $wp_comment_query WordPress Comment Query Object.
1728
 *
1729 34
 * @since 1.0
1730
 *
1731
 * @return string $where
1732 34
 */
1733
function give_hide_payment_notes_from_feeds( $where, $wp_comment_query ) {
0 ignored issues
show
Unused Code introduced by
The parameter $wp_comment_query is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1734 34
	global $wpdb;
1735
1736 42
	$where .= $wpdb->prepare( ' AND comment_type != %s', 'give_payment_note' );
1737
1738
	return $where;
1739
}
1740
1741
add_filter( 'comment_feed_where', 'give_hide_payment_notes_from_feeds', 10, 2 );
1742
1743
1744
/**
1745
 * Remove Give Comments from the wp_count_comments function
1746
 *
1747
 * @param array $stats   (empty from core filter).
1748
 * @param int   $post_id Post ID.
1749
 *
1750
 * @access public
1751
 * @since  1.0
1752 52
 *
1753
 * @return array|object Array of comment counts.
1754 52
 */
1755
function give_remove_payment_notes_in_comment_counts( $stats, $post_id ) {
1756 32
	global $wpdb, $pagenow;
1757
1758 32
	if ( 'index.php' != $pagenow ) {
1759
		return $stats;
1760 32
	}
1761
1762
	$post_id = (int) $post_id;
1763 32
1764
	if ( apply_filters( 'give_count_payment_notes_in_comments', false ) ) {
1765 32
		return $stats;
1766
	}
1767 32
1768
	$stats = wp_cache_get( "comments-{$post_id}", 'counts' );
1769 32
1770
	if ( false !== $stats ) {
1771 32
		return $stats;
1772
	}
1773 52
1774
	$where = 'WHERE comment_type != "give_payment_note"';
1775
1776
	if ( $post_id > 0 ) {
1777
		$where .= $wpdb->prepare( ' AND comment_post_ID = %d', $post_id );
1778
	}
1779
1780
	$count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} {$where} GROUP BY comment_approved", ARRAY_A );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
1781
1782
	$total    = 0;
1783
	$approved = array(
1784
		'0'            => 'moderated',
0 ignored issues
show
introduced by
Detected usage of 0, possible slow query.
Loading history...
1785
		'1'            => 'approved',
1786
		'spam'         => 'spam',
1787
		'trash'        => 'trash',
1788
		'post-trashed' => 'post-trashed',
1789
	);
1790
	foreach ( (array) $count as $row ) {
1791
		// Don't count post-trashed toward totals.
1792
		if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] ) {
1793
			$total += $row['num_comments'];
1794
		}
1795
		if ( isset( $approved[ $row['comment_approved'] ] ) ) {
1796
			$stats[ $approved[ $row['comment_approved'] ] ] = $row['num_comments'];
1797
		}
1798
	}
1799
1800
	$stats['total_comments'] = $total;
1801
	foreach ( $approved as $key ) {
1802
		if ( empty( $stats[ $key ] ) ) {
1803
			$stats[ $key ] = 0;
1804
		}
1805
	}
1806
1807
	$stats = (object) $stats;
1808
	wp_cache_set( "comments-{$post_id}", $stats, 'counts' );
1809
1810
	return $stats;
1811
}
1812
1813
add_filter( 'wp_count_comments', 'give_remove_payment_notes_in_comment_counts', 10, 2 );
1814
1815
1816
/**
1817
 * Filter where older than one week
1818
 *
1819
 * @param string $where Where clause.
1820
 *
1821
 * @access public
1822
 * @since  1.0
1823
 *
1824
 * @return string $where Modified where clause.
1825
 */
1826
function give_filter_where_older_than_week( $where = '' ) {
1827
	// Payments older than one week.
1828
	$start = date( 'Y-m-d', strtotime( '-7 days' ) );
1829
	$where .= " AND post_date <= '{$start}'";
1830
1831
	return $where;
1832
}
1833
1834
1835
/**
1836
 * Get Payment Form ID.
1837
 *
1838
 * Retrieves the form title and appends the level name if present.
1839
 *
1840
 * @param array  $payment_meta Payment meta data.
1841
 * @param bool   $only_level   If set to true will only return the level name if multi-level enabled.
1842
 * @param string $separator    The separator between the .
1843
 *
1844
 * @since 1.5
1845
 *
1846
 * @return string $form_title Returns the full title if $only_level is false, otherwise returns the levels title.
1847
 */
1848
function give_get_payment_form_title( $payment_meta, $only_level = false, $separator = '' ) {
1849
1850
	$form_id    = isset( $payment_meta['form_id'] ) ? $payment_meta['form_id'] : 0;
1851
	$price_id   = isset( $payment_meta['price_id'] ) ? $payment_meta['price_id'] : null;
1852
	$form_title = isset( $payment_meta['form_title'] ) ? $payment_meta['form_title'] : '';
1853
1854
	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...
1855
		$form_title = '';
1856
	}
1857
1858
	// If multi-level, append to the form title.
1859
	if ( give_has_variable_prices( $form_id ) ) {
1860
1861
		// Only add separator if there is a form title.
1862
		if ( ! empty( $form_title ) ) {
1863
			$form_title .= ' ' . $separator . ' ';
1864
		}
1865
1866
		$form_title .= '<span class="donation-level-text-wrap">';
1867
1868
		if ( 'custom' === $price_id ) {
1869
			$custom_amount_text = give_get_meta( $form_id, '_give_custom_amount_text', true );
1870
			$form_title         .= ! empty( $custom_amount_text ) ? $custom_amount_text : __( 'Custom Amount', 'give' );
1871
		} else {
1872
			$form_title .= give_get_price_option_name( $form_id, $price_id );
1873
		}
1874
1875
		$form_title .= '</span>';
1876
1877
	}
1878
1879
	return apply_filters( 'give_get_payment_form_title', $form_title, $payment_meta );
1880
1881
}
1882
1883
/**
1884
 * Get Price ID
1885
 *
1886
 * Retrieves the Price ID when provided a proper form ID and price (donation) total
1887
 *
1888
 * @param int    $form_id Form ID.
1889
 * @param string $price   Price ID.
1890
 *
1891
 * @return string $price_id
1892
 */
1893
function give_get_price_id( $form_id, $price ) {
1894
	$price_id = null;
1895
1896
	if ( give_has_variable_prices( $form_id ) ) {
1897
1898
		$levels = give_get_meta( $form_id, '_give_donation_levels', true );
1899
1900
		foreach ( $levels as $level ) {
1901
1902
			$level_amount = give_maybe_sanitize_amount( $level['_give_amount'] );
1903
1904
			// Check that this indeed the recurring price.
1905
			if ( $level_amount == $price ) {
1906
1907
				$price_id = $level['_give_id']['level_id'];
1908
				break;
1909
1910
			}
1911
		}
1912
1913
		if ( is_null( $price_id ) && give_is_custom_price_mode( $form_id ) ) {
1914
			$price_id = 'custom';
1915
		}
1916
	}
1917
1918
	// Price ID must be numeric or string.
1919
	$price_id = ! is_numeric( $price_id ) && ! is_string( $price_id ) ? 0 : $price_id;
1920
1921
	return $price_id;
1922
}
1923
1924
/**
1925
 * Get/Print give form dropdown html
1926
 *
1927
 * This function is wrapper to public method forms_dropdown of Give_HTML_Elements class to get/print form dropdown html.
1928
 * Give_HTML_Elements is defined in includes/class-give-html-elements.php.
1929
 *
1930
 * @param array $args Arguments for form dropdown.
1931
 * @param bool  $echo This parameter decides if print form dropdown html output or not.
1932
 *
1933
 * @since 1.6
1934
 *
1935
 * @return string
1936
 */
1937
function give_get_form_dropdown( $args = array(), $echo = false ) {
1938
	$form_dropdown_html = Give()->html->forms_dropdown( $args );
1939
1940
	if ( ! $echo ) {
1941
		return $form_dropdown_html;
1942
	}
1943
1944
	echo $form_dropdown_html;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$form_dropdown_html'
Loading history...
1945
}
1946
1947
/**
1948
 * Get/Print give form variable price dropdown html
1949
 *
1950
 * @param array $args Arguments for form dropdown.
1951
 * @param bool  $echo This parameter decide if print form dropdown html output or not.
1952
 *
1953
 * @since 1.6
1954
 *
1955
 * @return string|bool
1956
 */
1957
function give_get_form_variable_price_dropdown( $args = array(), $echo = false ) {
1958
1959
	// Check for give form id.
1960
	if ( empty( $args['id'] ) ) {
1961
		return false;
1962
	}
1963
1964
	$form = new Give_Donate_Form( $args['id'] );
1965
1966
	// Check if form has variable prices or not.
1967
	if ( ! $form->ID || ! $form->has_variable_prices() ) {
1968
		return false;
1969
	}
1970
1971
	$variable_prices        = $form->get_prices();
1972
	$variable_price_options = array();
1973
1974
	// Check if multi donation form support custom donation or not.
1975
	if ( $form->is_custom_price_mode() ) {
1976
		$variable_price_options['custom'] = _x( 'Custom', 'custom donation dropdown item', 'give' );
1977
	}
1978
1979
	// Get variable price and ID from variable price array.
1980
	foreach ( $variable_prices as $variable_price ) {
1981
		$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 ) ) );
1982
	}
1983
1984
	// Update options.
1985
	$args = array_merge( $args, array(
1986
		'options' => $variable_price_options,
1987
	) );
1988
1989
	// Generate select html.
1990
	$form_dropdown_html = Give()->html->select( $args );
1991
1992
	if ( ! $echo ) {
1993
		return $form_dropdown_html;
1994
	}
1995
1996
	echo $form_dropdown_html;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$form_dropdown_html'
Loading history...
1997
}
1998
1999
/**
2000
 * Get the price_id from the payment meta.
2001
 *
2002
 * Some gateways use `give_price_id` and others were using just `price_id`;
2003
 * This checks for the difference and falls back to retrieving it from the form as a last resort.
2004
 *
2005
 * @param array $payment_meta Payment Meta.
2006
 *
2007
 * @since 1.8.6
2008
 *
2009
 * @return string
2010
 */
2011
function give_get_payment_meta_price_id( $payment_meta ) {
2012
2013
	if ( isset( $payment_meta['give_price_id'] ) ) {
2014
		$price_id = $payment_meta['give_price_id'];
2015
	} elseif ( isset( $payment_meta['price_id'] ) ) {
2016
		$price_id = $payment_meta['price_id'];
2017
	} else {
2018
		$price_id = give_get_price_id( $payment_meta['give_form_id'], $payment_meta['price'] );
2019
	}
2020
2021
	return apply_filters( 'give_get_payment_meta_price_id', $price_id );
2022
2023
}
2024