Test Failed
Push — issues/2397 ( d6aef6...240f10 )
by Ravinder
03:57
created

functions.php ➔ give_count_payments()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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