Completed
Push — issues-1992 ( a60c48 )
by Ravinder
926:34 queued 918:40
created

functions.php ➔ give_get_payment_amount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Payment Functions
4
 *
5
 * @package     Give
6
 * @subpackage  Payments
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.0
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Get Payments
19
 *
20
 * Retrieve payments from the database.
21
 *
22
 * Since 1.0, this function takes an array of arguments, instead of individual
23
 * parameters. All of the original parameters remain, but can be passed in any
24
 * order via the array.
25
 *
26
 * @since 1.0
27
 *
28
 * @param array $args     {
29
 *                        Optional. Array of arguments passed to payments query.
30
 *
31
 * @type int    $offset   The number of payments to offset before retrieval.
32
 *                            Default is 0.
33
 * @type int    $number   The number of payments to query for. Use -1 to request all
34
 *                            payments. Default is 20.
35
 * @type string $mode     Default is 'live'.
36
 * @type string $order    Designates ascending or descending order of payments.
37
 *                            Accepts 'ASC', 'DESC'. Default is 'DESC'.
38
 * @type string $orderby  Sort retrieved payments by parameter. Default is 'ID'.
39
 * @type string $status   The status of the payments. Default is 'any'.
40
 * @type string $user     User. Default is null.
41
 * @type string $meta_key Custom field key. Default is null.
42
 *
43
 * }
44
 *
45
 * @return array $payments Payments retrieved from the database
46
 */
47
function give_get_payments( $args = array() ) {
48
49
	// Fallback to post objects to ensure backwards compatibility.
50
	if ( ! isset( $args['output'] ) ) {
51
		$args['output'] = 'posts';
52
	}
53
54
	$args     = apply_filters( 'give_get_payments_args', $args );
55
	$payments = new Give_Payments_Query( $args );
56
57
	return $payments->get_payments();
58
}
59
60
/**
61
 * Retrieve payment by a given field
62
 *
63
 * @since  1.0
64
 *
65
 * @param  string $field The field to retrieve the payment with.
66
 * @param  mixed  $value The value for $field.
67
 *
68
 * @return mixed
69
 */
70
function give_get_payment_by( $field = '', $value = '' ) {
71
72
	if ( empty( $field ) || empty( $value ) ) {
73
		return false;
74
	}
75
76
	switch ( strtolower( $field ) ) {
77
78
		case 'id':
79
			$payment = new Give_Payment( $value );
80
			$id      = $payment->ID;
81
82
			if ( empty( $id ) ) {
83
				return false;
84
			}
85
86
			break;
87
88 View Code Duplication
		case 'key':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
89
			$payment = give_get_payments( array(
90
				'meta_key'       => '_give_payment_purchase_key',
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
91
				'meta_value'     => $value,
0 ignored issues
show
introduced by
Detected usage of meta_value, possible slow query.
Loading history...
92
				'posts_per_page' => 1,
93
				'fields'         => 'ids',
94
			) );
95
96
			if ( $payment ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $payment of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
97
				$payment = new Give_Payment( $payment[0] );
98
			}
99
100
			break;
101
102 View Code Duplication
		case 'payment_number':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
103
			$payment = give_get_payments( array(
104
				'meta_key'       => '_give_payment_number',
0 ignored issues
show
introduced by
Detected usage of meta_key, possible slow query.
Loading history...
105
				'meta_value'     => $value,
0 ignored issues
show
introduced by
Detected usage of meta_value, possible slow query.
Loading history...
106
				'posts_per_page' => 1,
107
				'fields'         => 'ids',
108
			) );
109
110
			if ( $payment ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $payment of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
111
				$payment = new Give_Payment( $payment[0] );
112
			}
113
114
			break;
115
116
		default:
117
			return false;
118
	}// End switch().
119
120
	if ( $payment ) {
121
		return $payment;
122
	}
123
124
	return false;
125
}
126
127
/**
128
 * Insert Payment
129
 *
130
 * @since  1.0
131
 *
132
 * @param  array $payment_data Arguments passed.
133
 *
134
 * @return int|bool Payment ID if payment is inserted, false otherwise.
135
 */
136
function give_insert_payment( $payment_data = array() ) {
137
138
	if ( empty( $payment_data ) ) {
139
		return false;
140
	}
141
142
	/**
143
	 * Fire the filter on donation data before insert.
144
	 *
145
	 * @since 1.8.15
146
	 *
147
	 * @param array $payment_data Arguments passed.
148
	 */
149
	$payment_data = apply_filters( 'give_pre_insert_payment', $payment_data );
150
151
	$payment    = new Give_Payment();
152
	$gateway    = ! empty( $payment_data['gateway'] ) ? $payment_data['gateway'] : '';
153
	$gateway    = empty( $gateway ) && isset( $_POST['give-gateway'] ) ? $_POST['give-gateway'] : $gateway;
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
154
	$form_id    = isset( $payment_data['give_form_id'] ) ? $payment_data['give_form_id'] : 0;
155
	$price_id   = give_get_payment_meta_price_id( $payment_data );
156
	$form_title = isset( $payment_data['give_form_title'] ) ? $payment_data['give_form_title'] : get_the_title( $form_id );
157
158
	// Set properties.
159
	$payment->total          = $payment_data['price'];
160
	$payment->status         = ! empty( $payment_data['status'] ) ? $payment_data['status'] : 'pending';
161
	$payment->currency       = ! empty( $payment_data['currency'] ) ? $payment_data['currency'] : give_get_currency( $payment_data['give_form_id'], $payment_data );
162
	$payment->user_info      = $payment_data['user_info'];
163
	$payment->gateway        = $gateway;
164
	$payment->form_title     = $form_title;
165
	$payment->form_id        = $form_id;
166
	$payment->price_id       = $price_id;
167
	$payment->donor_id       = ( ! empty( $payment_data['donor_id'] ) ? $payment_data['donor_id'] : '' );
168
	$payment->user_id        = $payment_data['user_info']['id'];
169
	$payment->email          = $payment_data['user_email'];
170
	$payment->first_name     = $payment_data['user_info']['first_name'];
171
	$payment->last_name      = $payment_data['user_info']['last_name'];
172
	$payment->email          = $payment_data['user_info']['email'];
173
	$payment->ip             = give_get_ip();
174
	$payment->key            = $payment_data['purchase_key'];
175
	$payment->mode           = ( ! empty( $payment_data['mode'] ) ? (string) $payment_data['mode'] : ( give_is_test_mode() ? 'test' : 'live' ) );
176
	$payment->parent_payment = ! empty( $payment_data['parent'] ) ? absint( $payment_data['parent'] ) : '';
177
178
	// Add the donation.
179
	$args = array(
180
		'price'    => $payment->total,
181
		'price_id' => $payment->price_id,
182
	);
183
184
	$payment->add_donation( $payment->form_id, $args );
185
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
186
187
	// Set date if present.
188
	if ( isset( $payment_data['post_date'] ) ) {
189
		$payment->date = $payment_data['post_date'];
190
	}
191
192
	// Handle sequential payments.
193
	if ( give_get_option( 'enable_sequential' ) ) {
194
		$number          = give_get_next_payment_number();
195
		$payment->number = give_format_payment_number( $number );
196
		update_option( 'give_last_payment_number', $number );
197
	}
198
199
	// Save payment.
200
	$payment->save();
201
202
	/**
203
	 * Fires while inserting payments.
204
	 *
205
	 * @since 1.0
206
	 *
207
	 * @param int   $payment_id   The payment ID.
208
	 * @param array $payment_data Arguments passed.
209
	 */
210
	do_action( 'give_insert_payment', $payment->ID, $payment_data );
211
212
	// Return payment ID upon success.
213
	if ( ! empty( $payment->ID ) ) {
214
		return $payment->ID;
215
	}
216
217
	// Return false if no payment was inserted.
218
	return false;
219
220
}
221
222
/**
223
 * Create payment.
224
 *
225
 * @param $payment_data
226
 *
227
 * @return bool|int
228
 */
229
function give_create_payment( $payment_data ) {
230
231
	$form_id  = intval( $payment_data['post_data']['give-form-id'] );
232
	$price_id = isset( $payment_data['post_data']['give-price-id'] ) ? $payment_data['post_data']['give-price-id'] : '';
233
234
	// Collect payment data.
235
	$insert_payment_data = array(
236
		'price'           => $payment_data['price'],
237
		'give_form_title' => $payment_data['post_data']['give-form-title'],
238
		'give_form_id'    => $form_id,
239
		'give_price_id'   => $price_id,
240
		'date'            => $payment_data['date'],
241
		'user_email'      => $payment_data['user_email'],
242
		'purchase_key'    => $payment_data['purchase_key'],
243
		'currency'        => give_get_currency( $form_id, $payment_data ),
244
		'user_info'       => $payment_data['user_info'],
245
		'status'          => 'pending',
246
		'gateway'         => 'paypal',
247
	);
248
249
	/**
250
	 * Filter the payment params.
251
	 *
252
	 * @since 1.8
253
	 *
254
	 * @param array $insert_payment_data
255
	 */
256
	$insert_payment_data = apply_filters( 'give_create_payment', $insert_payment_data );
257
258
	// Record the pending payment.
259
	return give_insert_payment( $insert_payment_data );
260
}
261
262
/**
263
 * Updates a payment status.
264
 *
265
 * @param  int    $payment_id Payment ID.
266
 * @param  string $new_status New Payment Status. Default is 'publish'.
267
 *
268
 * @since  1.0
269
 *
270
 * @return bool
271
 */
272
function give_update_payment_status( $payment_id, $new_status = 'publish' ) {
273
274
	$updated = false;
275
	$payment = new Give_Payment( $payment_id );
276
277
	if ( $payment && $payment->ID > 0 ) {
278
279
		$payment->status = $new_status;
280
		$updated         = $payment->save();
281
282
	}
283
284
	return $updated;
285
}
286
287
288
/**
289
 * Deletes a Donation
290
 *
291
 * @since  1.0
292
 *
293
 * @param  int  $payment_id   Payment ID (default: 0).
294
 * @param  bool $update_donor If we should update the donor stats (default:true).
295
 *
296
 * @return void
297
 */
298
function give_delete_donation( $payment_id = 0, $update_donor = true ) {
299
	$payment = new Give_Payment( $payment_id );
300
301
	// Bailout.
302
	if( ! $payment->ID ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
303
		return;
304
	}
305
306
	$amount   = give_donation_amount( $payment_id );
307
	$status   = $payment->post_status;
308
	$donor_id = give_get_payment_donor_id( $payment_id );
309
	$donor    = new Give_Donor( $donor_id );
0 ignored issues
show
Documentation introduced by
$donor_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
310
311
	// Only undo donations that aren't these statuses.
312
	$dont_undo_statuses = apply_filters( 'give_undo_donation_statuses', array(
313
		'pending',
314
		'cancelled',
315
	) );
316
317
	if ( ! in_array( $status, $dont_undo_statuses ) ) {
318
		give_undo_donation( $payment_id );
319
	}
320
321
	// Only undo donations that aren't these statuses.
322
	$status_to_decrease_stats = apply_filters( 'give_decrease_donor_statuses', array( 'publish' ) );
323
324
	if ( in_array( $status, $status_to_decrease_stats ) ) {
325
326
		// Only decrease earnings if they haven't already been decreased (or were never increased for this payment).
327
		give_decrease_total_earnings( $amount );
328
329
		// @todo: Refresh only range related stat cache
330
		give_delete_donation_stats();
331
332
		if ( $donor->id && $update_donor ) {
333
334
			// Decrement the stats for the donor.
335
			$donor->decrease_donation_count();
336
			$donor->decrease_value( $amount );
337
338
		}
339
	}
340
341
	/**
342
	 * Fires before deleting payment.
343
	 *
344
	 * @param int $payment_id Payment ID.
345
	 *
346
	 * @since 1.0
347
	 */
348
	do_action( 'give_payment_delete', $payment_id );
349
350
	if ( $donor->id && $update_donor ) {
351
		// Remove the payment ID from the donor.
352
		$donor->remove_payment( $payment_id );
353
	}
354
355
	// Remove the payment.
356
	wp_delete_post( $payment_id, true );
357
358
	// Remove related sale log entries.
359
	Give()->logs->delete_logs( $payment_id );
360
361
	/**
362
	 * Fires after payment deleted.
363
	 *
364
	 * @param int $payment_id Payment ID.
365
	 *
366
	 * @since 1.0
367
	 */
368
	do_action( 'give_payment_deleted', $payment_id );
369
}
370
371
/**
372
 * Undo Donation
373
 *
374
 * Undoes a donation, including the decrease of donations and earning stats.
375
 * Used for when refunding or deleting a donation.
376
 *
377
 * @param  int $payment_id Payment ID.
378
 *
379
 * @since  1.0
380
 *
381
 * @return void
382
 */
383
function give_undo_donation( $payment_id ) {
384
385
	$payment = new Give_Payment( $payment_id );
386
387
	$maybe_decrease_earnings = apply_filters( 'give_decrease_earnings_on_undo', true, $payment, $payment->form_id );
388
	if ( true === $maybe_decrease_earnings ) {
389
		// Decrease earnings.
390
		give_decrease_form_earnings( $payment->form_id, $payment->total );
391
	}
392
393
	$maybe_decrease_donations = apply_filters( 'give_decrease_donations_on_undo', true, $payment, $payment->form_id );
394
	if ( true === $maybe_decrease_donations ) {
395
		// Decrease donation count.
396
		give_decrease_donation_count( $payment->form_id );
397
	}
398
399
}
400
401
402
/**
403
 * Count Payments
404
 *
405
 * Returns the total number of payments recorded.
406
 *
407
 * @param  array $args Arguments passed.
408
 *
409
 * @since  1.0
410
 *
411
 * @return object $stats Contains the number of payments per payment status.
412
 */
413
function give_count_payments( $args = array() ) {
414
	// Backward compatibility.
415
	if( ! empty( $args['start-date'] ) ) {
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...
416
		$args['start_date'] = $args['start-date'];
417
		unset( $args['start-date'] );
418
	}
419
420
	if( ! empty( $args['end-date'] ) ) {
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...
421
		$args['end_date'] = $args['end-date'];
422
		unset( $args['end-date'] );
423
	}
424
425
	if( ! empty( $args['form_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...
426
		$args['give_forms'] = $args['form_id'];
427
		unset( $args['form_id'] );
428
	}
429
430
	// Extract all donations
431
	$args['number']   = - 1;
432
	$args['group_by'] = 'post_status';
433
	$args['count']    = 'true';
434
435
	$donations_obj = new Give_Payments_Query( $args );
436
	$donations_count = $donations_obj->get_payment_by_group();
437
438
	return (object) apply_filters( 'give_count_payments', $donations_count, $args, $donations_obj );
439
}
440
441
442
/**
443
 * Check For Existing Payment
444
 *
445
 * @param  int $payment_id Payment ID.
446
 *
447
 * @since  1.0
448
 *
449
 * @return bool $exists True if payment exists, false otherwise.
450
 */
451
function give_check_for_existing_payment( $payment_id ) {
452
	$exists  = false;
453
	$payment = new Give_Payment( $payment_id );
454
455
	if ( $payment_id === $payment->ID && 'publish' === $payment->status ) {
456
		$exists = true;
457
	}
458
459
	return $exists;
460
}
461
462
/**
463
 * Get Payment Status
464
 *
465
 * @param WP_Post|Give_Payment|int $payment      Payment object or payment ID.
466
 * @param bool                     $return_label Whether to return the translated status label instead of status value.
467
 *                                               Default false.
468
 *
469
 * @since 1.0
470
 *
471
 * @return bool|mixed True if payment status exists, false otherwise.
472
 */
473
function give_get_payment_status( $payment, $return_label = false ) {
474
475
	if ( is_numeric( $payment ) ) {
476
477
		$payment = new Give_Payment( $payment );
478
479
		if ( ! $payment->ID > 0 ) {
480
			return false;
481
		}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
482
483
	}
484
485
	if ( ! is_object( $payment ) || ! isset( $payment->post_status ) ) {
486
		return false;
487
	}
488
489
	$statuses = give_get_payment_statuses();
490
491
	if ( ! is_array( $statuses ) || empty( $statuses ) ) {
492
		return false;
493
	}
494
495
	// Get payment object if not already given.
496
	$payment = $payment instanceof Give_Payment ? $payment : new Give_Payment( $payment->ID );
497
498
	if ( array_key_exists( $payment->status, $statuses ) ) {
499
		if ( true === $return_label ) {
500
			// Return translated status label.
501
			return $statuses[ $payment->status ];
502
		} else {
503
			// Account that our 'publish' status is labeled 'Complete'
504
			$post_status = 'publish' === $payment->status ? 'Complete' : $payment->post_status;
505
506
			// Make sure we're matching cases, since they matter
507
			return array_search( strtolower( $post_status ), array_map( 'strtolower', $statuses ) );
508
		}
509
	}
510
511
	return false;
512
}
513
514
/**
515
 * Retrieves all available statuses for payments.
516
 *
517
 * @since  1.0
518
 *
519
 * @return array $payment_status All the available payment statuses.
520
 */
521
function give_get_payment_statuses() {
522
	$payment_statuses = array(
523
		'pending'     => __( 'Pending', 'give' ),
524
		'publish'     => __( 'Complete', 'give' ),
525
		'refunded'    => __( 'Refunded', 'give' ),
526
		'failed'      => __( 'Failed', 'give' ),
527
		'cancelled'   => __( 'Cancelled', 'give' ),
528
		'abandoned'   => __( 'Abandoned', 'give' ),
529
		'preapproval' => __( 'Pre-Approved', 'give' ),
530
		'processing'  => __( 'Processing', 'give' ),
531
		'revoked'     => __( 'Revoked', 'give' ),
532
	);
533
534
	return apply_filters( 'give_payment_statuses', $payment_statuses );
535
}
536
537
/**
538
 * Get Payment Status Keys
539
 *
540
 * Retrieves keys for all available statuses for payments
541
 *
542
 * @since 1.0
543
 *
544
 * @return array $payment_status All the available payment statuses.
545
 */
546
function give_get_payment_status_keys() {
547
	$statuses = array_keys( give_get_payment_statuses() );
548
	asort( $statuses );
549
550
	return array_values( $statuses );
551
}
552
553
/**
554
 * Get Earnings By Date
555
 *
556
 * @param int $day       Day number. Default is null.
557
 * @param int $month_num Month number. Default is null.
558
 * @param int $year      Year number. Default is null.
559
 * @param int $hour      Hour number. Default is null.
560
 *
561
 * @since 1.0
562
 *
563
 * @return int $earnings Earnings
564
 */
565
function give_get_earnings_by_date( $day = null, $month_num, $year = null, $hour = null ) {
566
	// This is getting deprecated soon. Use Give_Payment_Stats with the get_earnings() method instead.
567
568
	global $wpdb;
569
	$meta_table = __give_v20_bc_table_details( 'payment' );
0 ignored issues
show
Unused Code introduced by
$meta_table is not used, you could remove the assignment.

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

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

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

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

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