Completed
Push — issues/1132 ( 578281...f0f195 )
by Ravinder
18:50
created

Give_Payment   D

Complexity

Total Complexity 199

Size/Duplication

Total Lines 2072
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 0
loc 2072
rs 4.4102
c 0
b 0
f 0
wmc 199
lcom 1
cbo 5

59 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
A __get() 0 14 2
A __set() 0 15 4
A __isset() 0 7 2
B setup_payment() 0 90 6
A update_payment_setup() 0 3 1
F insert_payment() 0 104 20
D save() 0 253 42
C add_donation() 0 80 12
B remove_donation() 0 30 4
A add_note() 0 8 2
A increase_subtotal() 0 6 1
A decrease_subtotal() 0 10 2
A recalculate_total() 0 3 1
C update_status() 0 76 12
A refund() 0 7 1
A get_meta() 0 19 1
A update_meta() 0 15 2
B process_refund() 0 43 4
A process_failure() 0 3 1
B process_pending() 0 28 4
B process_cancelled() 0 28 4
B process_revoked() 0 28 4
B maybe_alter_stats() 0 24 5
A delete_sales_logs() 0 15 1
A setup_completed_date() 0 11 4
A setup_mode() 0 3 1
A setup_total() 0 14 4
A setup_subtotal() 0 5 1
A setup_currency() 0 8 2
A setup_gateway() 0 5 1
A setup_transaction_id() 0 10 2
A setup_ip() 0 5 1
A setup_donor_id() 0 5 1
A setup_user_id() 0 10 3
A setup_email() 0 9 2
C setup_user_info() 0 56 11
B setup_address() 0 28 2
A setup_form_title() 0 6 1
A setup_form_id() 0 6 1
A setup_price_id() 0 5 1
A setup_payment_key() 0 5 1
A setup_payment_number() 0 16 3
A array_convert() 0 3 1
A is_completed() 0 3 2
A get_completed_date() 0 3 1
A get_subtotal() 0 3 1
A get_currency() 0 3 1
A get_gateway() 0 3 1
A get_transaction_id() 0 3 1
A get_ip() 0 3 1
A get_donor_id() 0 3 1
A get_user_id() 0 3 1
A get_email() 0 3 1
A get_user_info() 0 3 1
A get_address() 0 3 1
A get_key() 0 3 1
A get_form_id() 0 3 1
A get_number() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Give_Payment often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Give_Payment, and based on these observations, apply Extract Interface, too.

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 55 and the first side effect is on line 14.

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

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

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

Loading history...
2
/**
3
 * Payments
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Give_Payment
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.5
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Give_Payment Class
19
 *
20
 * This class is for working with payments in Give.
21
 *
22
 * @property int        $ID
23
 * @property bool       $new
24
 * @property string     $number
25
 * @property string     $mode
26
 * @property string     $key
27
 * @property string     $form_title
28
 * @property string|int $form_id
29
 * @property string|int $price_id
30
 * @property string|int $total
31
 * @property string|int $subtotal
32
 * @property string|int $fees
33
 * @property string|int $fees_total
34
 * @property string     $post_status
35
 * @property string     $date
36
 * @property string     $postdate
37
 * @property string     $status
38
 * @property string     $email
39
 * @property array      $payment_meta
40
 * @property string     $customer_id
41
 * @property string     $completed_date
42
 * @property string     $currency
43
 * @property string     $ip
44
 * @property array      $user_info
45
 * @property string     $gateway
46
 * @property string     $user_id
47
 * @property string     $first_name
48
 * @property string     $last_name
49
 * @property string     $parent_payment
50
 * @property string     $transaction_id
51
 * @property string     $old_status
52
 *
53
 * @since 1.5
54
 */
55
final class Give_Payment {
56
57
	/**
58
	 * The Payment ID.
59
	 *
60
	 * @since  1.5
61
	 *
62
	 * @var    int
63
	 */
64
	public $ID = 0;
65
66
	/**
67
	 * Protected non-read $_ID.
68
	 *
69
	 * @var int
70
	 */
71
	protected $_ID = 0;
72
73
	/**
74
	 * Identify if the payment is a new one or existing.
75
	 *
76
	 * @since  1.5
77
	 * @access protected
78
	 *
79
	 * @var    boolean
80
	 */
81
	protected $new = false;
82
83
	/**
84
	 * The Payment number (for use with sequential payments).
85
	 *
86
	 * @since  1.5
87
	 * @access protected
88
	 *
89
	 * @var    string
90
	 */
91
	protected $number = '';
92
93
	/**
94
	 * The Gateway mode the payment was made in.
95
	 *
96
	 * @since  1.5
97
	 * @access protected
98
	 *
99
	 * @var    string
100
	 */
101
	protected $mode = 'live';
102
103
	/**
104
	 * The unique donation payment key.
105
	 *
106
	 * @since  1.5
107
	 * @access protected
108
	 *
109
	 * @var    string
110
	 */
111
	protected $key = '';
112
113
	/**
114
	 * The Donation Form Title
115
	 *
116
	 * @since  1.5
117
	 * @access protected
118
	 *
119
	 * @var    string
120
	 */
121
	protected $form_title = 0;
122
123
	/**
124
	 * The Donation Form ID
125
	 *
126
	 * @since  1.5
127
	 * @access protected
128
	 *
129
	 * @var    string
130
	 */
131
	protected $form_id = 0;
132
133
	/**
134
	 * The Donation Form Price ID
135
	 *
136
	 * @since  1.5
137
	 * @access protected
138
	 *
139
	 * @var    string|int
140
	 */
141
	protected $price_id = 0;
142
143
	/**
144
	 * The total amount of the donation payment.
145
	 *
146
	 * @since  1.5
147
	 * @access protected
148
	 *
149
	 * @var    float
150
	 */
151
	protected $total = 0.00;
152
153
	/**
154
	 * The Subtotal fo the payment.
155
	 *
156
	 * @since  1.5
157
	 * @access protected
158
	 *
159
	 * @var    float
160
	 */
161
	protected $subtotal = 0;
162
163
	/**
164
	 * The date the payment was created
165
	 *
166
	 * @since  1.5
167
	 * @access protected
168
	 *
169
	 * @var    string
170
	 */
171
	protected $date = '';
172
173
	/**
174
	 * The date the payment post was created.
175
	 *
176
	 * @var string
177
	 */
178
	protected $post_date = '';
179
180
	/**
181
	 * The date the payment was marked as 'complete'.
182
	 *
183
	 * @since  1.5
184
	 * @access protected
185
	 *
186
	 * @var    string
187
	 */
188
	protected $completed_date = '';
189
190
	/**
191
	 * The status of the donation payment.
192
	 *
193
	 * @since  1.5
194
	 * @access protected
195
	 *
196
	 * @var    string
197
	 */
198
	protected $status = 'pending';
199
200
	/**
201
	 * @var string
202
	 */
203
	protected $post_status = 'pending'; // Same as $status but here for backwards compat
204
205
	/**
206
	 * When updating, the old status prior to the change
207
	 *
208
	 * @since  1.5
209
	 * @access protected
210
	 *
211
	 * @var    string
212
	 */
213
	protected $old_status = '';
214
215
	/**
216
	 * The display name of the current payment status.
217
	 *
218
	 * @since  1.5
219
	 * @access protected
220
	 *
221
	 * @var    string
222
	 */
223
	protected $status_nicename = '';
224
225
	/**
226
	 * The donor ID that made the payment.
227
	 *
228
	 * @since  1.5
229
	 * @access protected
230
	 *
231
	 * @var    integer
232
	 */
233
	protected $customer_id = null;
234
235
	/**
236
	 * The User ID (if logged in) that made the payment
237
	 *
238
	 * @since  1.5
239
	 * @access protected
240
	 *
241
	 * @var    integer
242
	 */
243
	protected $user_id = 0;
244
245
	/**
246
	 * The first name of the payee
247
	 *
248
	 * @since  1.5
249
	 * @access protected
250
	 *
251
	 * @var    string
252
	 */
253
	protected $first_name = '';
254
255
	/**
256
	 * The last name of the payee
257
	 *
258
	 * @since  1.5
259
	 * @access protected
260
	 *
261
	 * @var    string
262
	 */
263
	protected $last_name = '';
264
265
	/**
266
	 * The email used for the payment
267
	 *
268
	 * @since  1.5
269
	 * @access protected
270
	 *
271
	 * @var    string
272
	 */
273
	protected $email = '';
274
275
	/**
276
	 * Legacy (not to be accessed) array of user information
277
	 *
278
	 * @since  1.5
279
	 * @access private
280
	 *
281
	 * @var    array
282
	 */
283
	private $user_info = array();
284
285
	/**
286
	 * Legacy (not to be accessed) payment meta array
287
	 *
288
	 * @since  1.5
289
	 * @access private
290
	 *
291
	 * @var    array
292
	 */
293
	private $payment_meta = array();
294
295
	/**
296
	 * The physical address used for the payment if provided
297
	 *
298
	 * @since  1.5
299
	 * @access protected
300
	 *
301
	 * @var    array
302
	 */
303
	protected $address = array();
304
305
	/**
306
	 * The transaction ID returned by the gateway
307
	 *
308
	 * @since  1.5
309
	 * @access protected
310
	 *
311
	 * @var    string
312
	 */
313
	protected $transaction_id = '';
314
315
	/**
316
	 * IP Address payment was made from
317
	 *
318
	 * @since  1.5
319
	 * @access protected
320
	 *
321
	 * @var    string
322
	 */
323
	protected $ip = '';
324
325
	/**
326
	 * The gateway used to process the payment
327
	 *
328
	 * @since  1.5
329
	 * @access protected
330
	 *
331
	 * @var    string
332
	 */
333
	protected $gateway = '';
334
335
	/**
336
	 * The the payment was made with
337
	 *
338
	 * @since  1.5
339
	 * @access protected
340
	 *
341
	 * @var    string
342
	 */
343
	protected $currency = '';
344
345
	/**
346
	 * Array of items that have changed since the last save() was run.
347
	 * This is for internal use, to allow fewer update_payment_meta calls to be run.
348
	 *
349
	 * @since  1.5
350
	 * @access private
351
	 *
352
	 * @var    array
353
	 */
354
	private $pending;
355
356
	/**
357
	 * The parent payment (if applicable)
358
	 *
359
	 * @since  1.5
360
	 * @access protected
361
	 *
362
	 * @var    integer
363
	 */
364
	protected $parent_payment = 0;
365
366
	/**
367
	 * Setup the Give Payments class
368
	 *
369
	 * @since  1.5
370
	 * @access public
371
	 *
372
	 * @param  int|bool $payment_id A given payment
373
	 *
374
	 * @return mixed void|false
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
375
	 */
376
	public function __construct( $payment_id = false ) {
377
378
		if ( empty( $payment_id ) ) {
379
			return false;
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
380
		}
381
382
		$this->setup_payment( $payment_id );
383
	}
384
385
	/**
386
	 * Magic GET function.
387
	 *
388
	 * @since  1.5
389
	 * @access public
390
	 *
391
	 * @param  string $key The property.
392
	 *
393
	 * @return mixed        The value.
394
	 */
395
	public function __get( $key ) {
396
397
		if ( method_exists( $this, 'get_' . $key ) ) {
398
399
			$value = call_user_func( array( $this, 'get_' . $key ) );
400
401
		} else {
402
403
			$value = $this->$key;
404
405
		}
406
407
		return $value;
408
	}
409
410
	/**
411
	 * Magic SET function
412
	 *
413
	 * Sets up the pending array for the save method
414
	 *
415
	 * @since  1.5
416
	 * @access public
417
	 *
418
	 * @param  string $key   The property name
419
	 * @param  mixed  $value The value of the property
420
	 */
421
	public function __set( $key, $value ) {
422
		$ignore = array( '_ID' );
423
424
		if ( $key === 'status' ) {
425
			$this->old_status = $this->status;
426
		}
427
428
		if ( ! in_array( $key, $ignore ) ) {
429
			$this->pending[ $key ] = $value;
430
		}
431
432
		if ( '_ID' !== $key ) {
433
			$this->$key = $value;
434
		}
435
	}
436
437
	/**
438
	 * Magic ISSET function, which allows empty checks on protected elements
439
	 *
440
	 * @since  1.5
441
	 * @access public
442
	 *
443
	 * @param  string $name The attribute to get
444
	 *
445
	 * @return boolean       If the item is set or not
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|null?

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

Loading history...
446
	 */
447
	public function __isset( $name ) {
448
		if ( property_exists( $this, $name ) ) {
449
			return false === empty( $this->$name );
450
		} else {
451
			return null;
452
		}
453
	}
454
455
	/**
456
	 * Setup payment properties
457
	 *
458
	 * @since  1.5
459
	 * @access private
460
	 *
461
	 * @param  int $payment_id The payment ID
462
	 *
463
	 * @return bool            If the setup was successful or not
464
	 */
465
	private function setup_payment( $payment_id ) {
466
		$this->pending = array();
467
468
		if ( empty( $payment_id ) ) {
469
			return false;
470
		}
471
472
		$payment = get_post( $payment_id );
473
474
		if ( ! $payment || is_wp_error( $payment ) ) {
475
			return false;
476
		}
477
478
		if ( 'give_payment' !== $payment->post_type ) {
479
			return false;
480
		}
481
482
		/**
483
		 * Fires before payment setup.
484
		 *
485
		 * Allow extensions to perform actions before the payment is loaded.
486
		 *
487
		 * @since 1.5
488
		 *
489
		 * @param Give_Payment $this       Payment object.
490
		 * @param int          $payment_id The ID of the payment.
491
		 */
492
		do_action( 'give_pre_setup_payment', $this, $payment_id );
493
494
		// Primary Identifier.
495
		$this->ID = absint( $payment_id );
496
497
		// Protected ID that can never be changed.
498
		$this->_ID = absint( $payment_id );
499
500
		// We have a payment, get the generic payment_meta item to reduce calls to it.
501
		$this->payment_meta = $this->get_meta();
502
503
		// Status and Dates.
504
		$this->date           = $payment->post_date;
505
		$this->post_date      = $payment->post_date;
506
		$this->completed_date = $this->setup_completed_date();
507
		$this->status         = $payment->post_status;
508
		$this->post_status    = $this->status;
509
		$this->mode           = $this->setup_mode();
510
		$this->parent_payment = $payment->post_parent;
511
512
		$all_payment_statuses  = give_get_payment_statuses();
513
		$this->status_nicename = array_key_exists( $this->status, $all_payment_statuses ) ? $all_payment_statuses[ $this->status ] : ucfirst( $this->status );
514
515
		// Currency Based.
516
		$this->total      = $this->setup_total();
517
		$this->subtotal   = $this->setup_subtotal();
518
		$this->currency   = $this->setup_currency();
519
520
		// Gateway based.
521
		$this->gateway        = $this->setup_gateway();
522
		$this->transaction_id = $this->setup_transaction_id();
523
524
		// User based.
525
		$this->ip          = $this->setup_ip();
526
		$this->customer_id = $this->setup_donor_id();
527
		$this->user_id     = $this->setup_user_id();
528
		$this->email       = $this->setup_email();
529
		$this->user_info   = $this->setup_user_info();
530
		$this->address     = $this->setup_address();
531
		$this->first_name  = $this->user_info['first_name'];
532
		$this->last_name   = $this->user_info['last_name'];
533
534
		// Other Identifiers.
535
		$this->form_title = $this->setup_form_title();
536
		$this->form_id    = $this->setup_form_id();
537
		$this->price_id   = $this->setup_price_id();
538
		$this->key        = $this->setup_payment_key();
539
		$this->number     = $this->setup_payment_number();
540
541
		/**
542
		 * Fires after payment setup.
543
		 *
544
		 * Allow extensions to add items to this object via hook.
545
		 *
546
		 * @since 1.5
547
		 *
548
		 * @param Give_Payment $this       Payment object.
549
		 * @param int          $payment_id The ID of the payment.
550
		 */
551
		do_action( 'give_setup_payment', $this, $payment_id );
552
553
		return true;
554
	}
555
556
	/**
557
	 * Payment class object is storing various meta value in object parameter.
558
	 * So if user is updating payment meta but not updating payment object, then payment meta values will not reflect/changes on payment meta automatically
559
	 * and you can still access payment meta old value in any old payment object ( previously created ) which can cause to show or save wrong payment data.
560
	 * To prevent that user can use this function after updating any payment meta value ( in bulk or single update ).
561
	 *
562
	 * @since  1.6
563
	 * @access public
564
	 *
565
	 * @param  int $payment_id Payment ID.
566
	 *
567
	 * @return void
568
	 */
569
	public function update_payment_setup( $payment_id ) {
570
		$this->setup_payment( $payment_id );
571
	}
572
573
	/**
574
	 * Create the base of a payment.
575
	 *
576
	 * @since  1.5
577
	 * @access private
578
	 *
579
	 * @return int|bool False on failure, the payment ID on success.
580
	 */
581
	private function insert_payment() {
582
583
		// Construct the payment title.
584
		$payment_title = '';
585
		if ( ! empty( $this->first_name ) && ! empty( $this->last_name ) ) {
586
			$payment_title = $this->first_name . ' ' . $this->last_name;
587
		} elseif ( ! empty( $this->first_name ) && empty( $this->last_name ) ) {
588
			$payment_title = $this->first_name;
589
		} elseif ( ! empty( $this->email ) && is_email( $this->email ) ) {
590
			$payment_title = $this->email;
591
		}
592
593
		// Set Key.
594
		if ( empty( $this->key ) ) {
595
596
			$auth_key             = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
597
			$this->key            = strtolower( md5( $this->email . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'give', true ) ) );  // Unique key
598
			$this->pending['key'] = $this->key;
599
		}
600
601
		// Set IP.
602
		if ( empty( $this->ip ) ) {
603
604
			$this->ip            = give_get_ip();
605
			$this->pending['ip'] = $this->ip;
606
607
		}
608
609
		$payment_data = array(
610
			'price'        => $this->total,
611
			'date'         => $this->date,
612
			'user_email'   => $this->email,
613
			'purchase_key' => $this->key,
614
			'form_title'   => $this->form_title,
615
			'form_id'      => $this->form_id,
616
			'price_id'     => $this->price_id,
617
			'currency'     => $this->currency,
618
			'user_info'    => array(
619
				'id'         => $this->user_id,
620
				'email'      => $this->email,
621
				'first_name' => $this->first_name,
622
				'last_name'  => $this->last_name,
623
				'address'    => $this->address,
624
			),
625
			'status'       => $this->status,
626
		);
627
628
		$args = apply_filters( 'give_insert_payment_args', array(
629
			'post_title'    => $payment_title,
630
			'post_status'   => $this->status,
631
			'post_type'     => 'give_payment',
632
			'post_date'     => ! empty( $this->date ) ? $this->date : null,
633
			'post_date_gmt' => ! empty( $this->date ) ? get_gmt_from_date( $this->date ) : null,
634
			'post_parent'   => $this->parent_payment,
635
		), $payment_data );
636
637
		// Create a blank payment
638
		$payment_id = wp_insert_post( $args );
639
640
		if ( ! empty( $payment_id ) ) {
641
642
			$this->ID  = $payment_id;
643
			$this->_ID = $payment_id;
644
645
			$donor = new stdClass;
646
647
			if ( did_action( 'give_pre_process_donation' ) && is_user_logged_in() ) {
648
				$donor = new Give_Donor( get_current_user_id(), true );
649
650
				// Donor is logged in but used a different email to purchase with so assign to their donor record.
651
				if ( ! empty( $donor->id ) && $this->email != $donor->email ) {
652
					$donor->add_email( $this->email );
653
				}
654
			}
655
656
			if ( empty( $donor->id ) ) {
657
				$donor = new Give_Donor( $this->email );
658
			}
659
660
			if ( empty( $donor->id ) ) {
661
662
				$donor_data = array(
663
					'name'    => ! is_email( $payment_title ) ? $this->first_name . ' ' . $this->last_name : '',
664
					'email'   => $this->email,
665
					'user_id' => $this->user_id,
666
				);
667
668
				$donor->create( $donor_data );
0 ignored issues
show
Bug introduced by
The method create does only exist in Give_Donor, but not in stdClass.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
669
670
			}
671
672
			$this->customer_id            = $donor->id;
673
			$this->pending['customer_id'] = $this->customer_id;
674
			$donor->attach_payment( $this->ID, false );
0 ignored issues
show
Bug introduced by
The method attach_payment does only exist in Give_Donor, but not in stdClass.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
675
676
			$this->payment_meta = apply_filters( 'give_payment_meta', $this->payment_meta, $payment_data );
677
678
			$this->update_meta( '_give_payment_meta', $this->payment_meta );
679
			$this->new = true;
680
		}// End if().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
681
682
		return $this->ID;
683
684
	}
685
686
	/**
687
	 * Save
688
	 *
689
	 * Once items have been set, an update is needed to save them to the database.
690
	 *
691
	 * @access public
692
	 *
693
	 * @return bool  True of the save occurred, false if it failed or wasn't needed
694
	 */
695
	public function save() {
696
697
		$saved = false;
698
699
		// Must have an ID.
700
		if ( empty( $this->ID ) ) {
701
702
			$payment_id = $this->insert_payment();
703
704
			if ( false === $payment_id ) {
705
				$saved = false;
706
			} else {
707
				$this->ID = $payment_id;
708
			}
709
		}
710
711
		// Set ID if not matching.
712
		if ( $this->ID !== $this->_ID ) {
713
			$this->ID = $this->_ID;
714
		}
715
716
		// If we have something pending, let's save it.
717
		if ( ! empty( $this->pending ) ) {
718
719
			$total_increase = 0;
720
			$total_decrease = 0;
721
722
			foreach ( $this->pending as $key => $value ) {
723
724
				switch ( $key ) {
725
726
					case 'donations':
727
						// Update totals for pending donations.
728
						foreach ( $this->pending[ $key ] as $item ) {
729
730
							$quantity = isset( $item['quantity'] ) ? $item['quantity'] : 1;
731
							$price_id = isset( $item['price_id'] ) ? $item['price_id'] : 0;
732
733
							switch ( $item['action'] ) {
734
735
								case 'add':
736
737
									$price = $item['price'];
738
739
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
740
741
										// Add sales logs.
742
										$log_date = date_i18n( 'Y-m-d G:i:s', current_time( 'timestamp' ) );
743
744
										$y = 0;
745
										while ( $y < $quantity ) {
746
747
											give_record_donation_in_log( $item['id'], $this->ID, $price_id, $log_date );
748
											$y ++;
749
										}
750
751
										$form = new Give_Donate_Form( $item['id'] );
752
										$form->increase_sales( $quantity );
753
										$form->increase_earnings( $price );
754
755
										$total_increase += $price;
756
									}
757
									break;
758
759
								case 'remove':
760
									$log_args = array(
761
										'post_type'   => 'give_log',
762
										'post_parent' => $item['id'],
763
										'numberposts' => $quantity,
764
										'meta_query'  => array(
765
											array(
766
												'key'     => '_give_log_payment_id',
767
												'value'   => $this->ID,
768
												'compare' => '=',
769
											),
770
											array(
771
												'key'     => '_give_log_price_id',
772
												'value'   => $price_id,
773
												'compare' => '=',
774
											),
775
										),
776
									);
777
778
									$found_logs = get_posts( $log_args );
779
									foreach ( $found_logs as $log ) {
780
										wp_delete_post( $log->ID, true );
781
									}
782
783
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
784
										$form = new Give_Donate_Form( $item['id'] );
785
										$form->decrease_sales( $quantity );
786
										$form->decrease_earnings( $item['amount'] );
787
788
										$total_decrease += $item['amount'];
789
									}
790
									break;
791
792
							}// End switch().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
793
						}// End foreach().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
794
						break;
795
796
					case 'status':
797
						$this->update_status( $this->status );
798
						break;
799
800
					case 'gateway':
801
						$this->update_meta( '_give_payment_gateway', $this->gateway );
802
						break;
803
804
					case 'mode':
805
						$this->update_meta( '_give_payment_mode', $this->mode );
806
						break;
807
808
					case 'transaction_id':
809
						$this->update_meta( '_give_payment_transaction_id', $this->transaction_id );
810
						break;
811
812
					case 'ip':
813
						$this->update_meta( '_give_payment_donor_ip', $this->ip );
814
						break;
815
816
					case 'customer_id':
817
						$this->update_meta( '_give_payment_donor_id', $this->customer_id );
818
						break;
819
820
					// case 'user_id':
821
					// 	$this->update_meta( '_give_payment_user_id', $this->user_id );
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
822
					// 	break;
823
824
					case 'form_title':
825
						$this->update_meta( '_give_payment_form_title', $this->form_title );
826
						break;
827
828
					case 'form_id':
829
						$this->update_meta( '_give_payment_form_id', $this->form_id );
830
						break;
831
832
					case 'price_id':
833
						$this->update_meta( '_give_payment_price_id', $this->price_id );
834
						break;
835
836
					case 'first_name':
837
						$this->user_info['first_name'] = $this->first_name;
838
						break;
839
840
					case 'last_name':
841
						$this->user_info['last_name'] = $this->last_name;
842
						break;
843
844
					case 'address':
845
						$this->user_info['address'] = $this->address;
846
						break;
847
848
					case 'email':
849
						$this->update_meta( '_give_payment_donor_email', $this->email );
850
						break;
851
852
					case 'key':
853
						$this->update_meta( '_give_payment_purchase_key', $this->key );
854
						break;
855
856
					case 'number':
857
						$this->update_meta( '_give_payment_number', $this->number );
858
						break;
859
860
					case 'date':
861
						$args = array(
862
							'ID'        => $this->ID,
863
							'post_date' => $this->date,
864
							'edit_date' => true,
865
						);
866
867
						wp_update_post( $args );
868
						break;
869
870
					case 'completed_date':
871
						$this->update_meta( '_give_completed_date', $this->completed_date );
872
						break;
873
874
					case 'parent_payment':
875
						$args = array(
876
							'ID'          => $this->ID,
877
							'post_parent' => $this->parent_payment,
878
						);
879
880
						wp_update_post( $args );
881
						break;
882
883
					default:
884
						/**
885
						 * Fires while saving payment.
886
						 *
887
						 * @since 1.7
888
						 *
889
						 * @param Give_Payment $this Payment object.
890
						 */
891
						do_action( 'give_payment_save', $this, $key );
892
						break;
893
				}// End switch().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
894
			}// End foreach().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
895
896
			if ( 'pending' !== $this->status ) {
897
898
				$donor = new Give_Donor( $this->customer_id );
899
900
				$total_change = $total_increase - $total_decrease;
901
				if ( $total_change < 0 ) {
902
903
					$total_change = - ( $total_change );
904
					// Decrease the donor's donation stats.
905
					$donor->decrease_value( $total_change );
906
					give_decrease_total_earnings( $total_change );
907
908
				} elseif ( $total_change > 0 ) {
909
910
					// Increase the donor's donation stats.
911
					$donor->increase_value( $total_change );
912
					give_increase_total_earnings( $total_change );
913
914
				}
915
			}
916
917
			$this->update_meta( '_give_payment_total', $this->total );
918
919
			$new_meta = array(
920
				'form_title' => $this->form_title,
921
				'form_id'    => $this->form_id,
922
				'price_id'   => $this->price_id,
923
				'currency'   => $this->currency,
924
				'user_info'  => $this->user_info,
925
			);
926
927
			$meta        = $this->get_meta();
928
			$merged_meta = array_merge( $meta, $new_meta );
929
930
			// Only save the payment meta if it's changed.
931
			if ( md5( serialize( $meta ) ) !== md5( serialize( $merged_meta ) ) ) {
932
				$updated = $this->update_meta( '_give_payment_meta', $merged_meta );
933
				if ( false !== $updated ) {
934
					$saved = true;
935
				}
936
			}
937
938
			$this->pending = array();
939
			$saved         = true;
940
		}// End if().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
941
942
		if ( true === $saved ) {
943
			$this->setup_payment( $this->ID );
944
		}
945
946
		return $saved;
947
	}
948
949
	/**
950
	 * Add a donation to a given payment
951
	 *
952
	 * @since  1.5
953
	 * @access public
954
	 *
955
	 * @param  int   $form_id The donation form to add
956
	 * @param  array $args Other arguments to pass to the function
957
	 * @param  array $options List of donation options
958
	 *
959
	 * @return bool           True when successful, false otherwise
960
	 */
961
	public function add_donation( $form_id = 0, $args = array(), $options = array() ) {
962
963
		$donation = new Give_Donate_Form( $form_id );
964
965
		// Bail if this post isn't a give donation form.
966
		if ( ! $donation || $donation->post_type !== 'give_forms' ) {
0 ignored issues
show
Documentation introduced by
The property post_type does not exist on object<Give_Donate_Form>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
967
			return false;
968
		}
969
970
		// Set some defaults.
971
		$defaults = array(
972
			'price'    => false,
973
			'price_id' => false,
974
		);
975
976
		$args = wp_parse_args( apply_filters( 'give_payment_add_donation_args', $args, $donation->ID ), $defaults );
977
978
		// Allow overriding the price.
979
		if ( false !== $args['price'] ) {
980
			$item_price = $args['price'];
981
		} else {
982
983
			// Deal with variable pricing.
984
			if ( give_has_variable_prices( $donation->ID ) ) {
985
				$prices     = maybe_unserialize( give_get_meta( $form_id, '_give_donation_levels', true ) );
986
				$item_price = '';
987
				// Loop through prices.
988
				foreach ( $prices as $price ) {
989
					// Find a match between price_id and level_id.
990
					// First verify array keys exists THEN make the match.
991
					if ( ( isset( $args['price_id'] ) && isset( $price['_give_id']['level_id'] ) )
992
					     && $args['price_id'] == $price['_give_id']['level_id']
993
					) {
994
						$item_price = $price['_give_amount'];
995
					}
996
				}
997
				// Fallback to the lowest price point.
998
				if ( $item_price == '' ) {
999
					$item_price       = give_get_lowest_price_option( $donation->ID );
1000
					$args['price_id'] = give_get_lowest_price_id( $donation->ID );
1001
				}
1002
			} else {
1003
				// Simple form price.
1004
				$item_price = give_get_form_price( $donation->ID );
1005
			}
1006
		}
1007
1008
		// Sanitizing the price here so we don't have a dozen calls later.
1009
		$item_price = give_sanitize_amount( $item_price );
1010
		$total      = round( $item_price, give_currency_decimal_filter() );
1011
1012
		// Add Options.
1013
		$default_options = array();
1014
		if ( false !== $args['price_id'] ) {
1015
			$default_options['price_id'] = (int) $args['price_id'];
1016
		}
1017
		$options = wp_parse_args( $options, $default_options );
1018
1019
		// Do not allow totals to go negative.
1020
		if ( $total < 0 ) {
1021
			$total = 0;
1022
		}
1023
1024
		$donation = array(
1025
			'name'     => $donation->post_title,
1026
			'id'       => $donation->ID,
1027
			'price'    => round( $total, give_currency_decimal_filter() ),
1028
			'subtotal' => round( $total, give_currency_decimal_filter() ),
1029
			'price_id' => $args['price_id'],
1030
			'action'   => 'add',
1031
			'options'  => $options,
1032
		);
1033
1034
		$this->pending['donations'][] = $donation;
1035
1036
		$this->increase_subtotal( $total );
1037
1038
		return true;
1039
1040
	}
1041
1042
	/**
1043
	 * Remove a donation from the payment
1044
	 *
1045
	 * @since  1.5
1046
	 * @access public
1047
	 *
1048
	 * @param  int   $form_id The form ID to remove
1049
	 * @param  array $args Arguments to pass to identify (quantity, amount, price_id)
1050
	 *
1051
	 * @return bool           If the item was removed or not
1052
	 */
1053
	public function remove_donation( $form_id, $args = array() ) {
1054
1055
		// Set some defaults.
1056
		$defaults = array(
1057
			'quantity' => 1,
1058
			'price'    => false,
1059
			'price_id' => false,
1060
		);
1061
		$args     = wp_parse_args( $args, $defaults );
1062
1063
		$form = new Give_Donate_Form( $form_id );
1064
1065
		// Bail if this post isn't a valid give donation form.
1066
		if ( ! $form || $form->post_type !== 'give_forms' ) {
0 ignored issues
show
Documentation introduced by
The property post_type does not exist on object<Give_Donate_Form>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1067
			return false;
1068
		}
1069
1070
		$pending_args             = $args;
1071
		$pending_args['id']       = $form_id;
1072
		$pending_args['amount']   = $this->total;
1073
		$pending_args['price_id'] = false !== $args['price_id'] ? (int) $args['price_id'] : false;
1074
		$pending_args['quantity'] = $args['quantity'];
1075
		$pending_args['action']   = 'remove';
1076
1077
		$this->pending['donations'][] = $pending_args;
1078
1079
		$this->decrease_subtotal( $this->total );
1080
1081
		return true;
1082
	}
1083
1084
1085
	/**
1086
	 * Add a note to a payment
1087
	 *
1088
	 * @since  1.5
1089
	 * @access public
1090
	 *
1091
	 * @param  string $note The note to add
1092
	 *
1093
	 * @return void
0 ignored issues
show
Documentation introduced by
Should the return type not be false|null?

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

Loading history...
1094
	 */
1095
	public function add_note( $note = false ) {
1096
		// Bail if no note specified.
1097
		if ( ! $note ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $note of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1098
			return false;
1099
		}
1100
1101
		give_insert_payment_note( $this->ID, $note );
1102
	}
1103
1104
	/**
1105
	 * Increase the payment's subtotal
1106
	 *
1107
	 * @since  1.5
1108
	 * @access private
1109
	 *
1110
	 * @param  float $amount The amount to increase the payment subtotal by.
1111
	 *
1112
	 * @return void
1113
	 */
1114
	private function increase_subtotal( $amount = 0.00 ) {
1115
		$amount         = (float) $amount;
1116
		$this->subtotal += $amount;
1117
1118
		$this->recalculate_total();
1119
	}
1120
1121
	/**
1122
	 * Decrease the payment's subtotal.
1123
	 *
1124
	 * @since  1.5
1125
	 * @access private
1126
	 *
1127
	 * @param  float $amount The amount to decrease the payment subtotal by.
1128
	 *
1129
	 * @return void
1130
	 */
1131
	private function decrease_subtotal( $amount = 0.00 ) {
1132
		$amount         = (float) $amount;
1133
		$this->subtotal -= $amount;
1134
1135
		if ( $this->subtotal < 0 ) {
1136
			$this->subtotal = 0;
1137
		}
1138
1139
		$this->recalculate_total();
1140
	}
1141
1142
	/**
1143
	 * Set or update the total for a payment.
1144
	 *
1145
	 * @since  1.5
1146
	 * @access private
1147
	 *
1148
	 * @return void
1149
	 */
1150
	private function recalculate_total() {
1151
		$this->total = $this->subtotal;
1152
	}
1153
1154
	/**
1155
	 * Set the payment status and run any status specific changes necessary.
1156
	 *
1157
	 * @since  1.5
1158
	 * @access public
1159
	 *
1160
	 * @param  string|bool $status The status to set the payment to.
1161
	 *
1162
	 * @return bool   $updated Returns if the status was successfully updated.
1163
	 */
1164
	public function update_status( $status = false ) {
1165
1166
		// standardize the 'complete(d)' status.
1167
		if ( $status == 'completed' || $status == 'complete' ) {
1168
			$status = 'publish';
1169
		}
1170
1171
		$old_status = ! empty( $this->old_status ) ? $this->old_status : false;
1172
1173
		if ( $old_status === $status ) {
1174
			return false; // Don't permit status changes that aren't changes.
1175
		}
1176
1177
		$do_change = apply_filters( 'give_should_update_payment_status', true, $this->ID, $status, $old_status );
1178
1179
		$updated = false;
1180
1181
		if ( $do_change ) {
1182
1183
			/**
1184
			 * Fires before changing payment status.
1185
			 *
1186
			 * @since 1.5
1187
			 *
1188
			 * @param int $payment_id Payments ID.
1189
			 * @param string $status The new status.
1190
			 * @param string $old_status The old status.
1191
			 */
1192
			do_action( 'give_before_payment_status_change', $this->ID, $status, $old_status );
1193
1194
			$update_fields = array(
1195
				'ID'          => $this->ID,
1196
				'post_status' => $status,
1197
				'edit_date'   => current_time( 'mysql' ),
1198
			);
1199
1200
			$updated = wp_update_post( apply_filters( 'give_update_payment_status_fields', $update_fields ) );
1201
1202
			$all_payment_statuses  = give_get_payment_statuses();
1203
			$this->status_nicename = array_key_exists( $status, $all_payment_statuses ) ? $all_payment_statuses[ $status ] : ucfirst( $status );
1204
1205
			// Process any specific status functions.
1206
			switch ( $status ) {
1207
				case 'refunded':
1208
					$this->process_refund();
1209
					break;
1210
				case 'failed':
1211
					$this->process_failure();
0 ignored issues
show
Unused Code introduced by
The call to the method Give_Payment::process_failure() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
1212
					break;
1213
				case 'pending':
1214
					$this->process_pending();
1215
					break;
1216
				case 'cancelled':
1217
					$this->process_cancelled();
1218
					break;
1219
				case 'revoked':
1220
					$this->process_revoked();
1221
					break;
1222
			}
1223
1224
			/**
1225
			 * Fires after changing payment status.
1226
			 *
1227
			 * @since 1.5
1228
			 *
1229
			 * @param int $payment_id Payment ID.
1230
			 * @param string $status The new status.
1231
			 * @param string $old_status The old status.
1232
			 */
1233
			do_action( 'give_update_payment_status', $this->ID, $status, $old_status );
1234
1235
		}// End if().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1236
1237
		return $updated;
1238
1239
	}
1240
1241
	/**
1242
	 * Change the status of the payment to refunded, and run the necessary changes
1243
	 *
1244
	 * @since  1.5
1245
	 * @access public
1246
	 *
1247
	 * @return void
1248
	 */
1249
	public function refund() {
1250
		$this->old_status        = $this->status;
1251
		$this->status            = 'refunded';
1252
		$this->pending['status'] = $this->status;
1253
1254
		$this->save();
1255
	}
1256
1257
	/**
1258
	 * Get a post meta item for the payment
1259
	 *
1260
	 * @since  1.5
1261
	 * @access public
1262
	 *
1263
	 * @param  string  $meta_key The Meta Key
1264
	 * @param  boolean $single Return single item or array
1265
	 *
1266
	 * @return mixed             The value from the post meta
1267
	 */
1268
	public function get_meta( $meta_key = '_give_payment_meta', $single = true ) {
1269
1270
		$meta = give_get_meta( $this->ID, $meta_key, $single );
1271
1272
		/**
1273
		 * Filter the specific meta key value.
1274
		 *
1275
		 * @since 1.5
1276
		 */
1277
		$meta = apply_filters( "give_get_payment_meta_{$meta_key}", $meta, $this->ID );
1278
1279
1280
		/**
1281
		 * Filter the all meta keys.
1282
		 *
1283
		 * @since 1.5
1284
		 */
1285
		return apply_filters( 'give_get_payment_meta', $meta, $this->ID, $meta_key );
1286
	}
1287
1288
	/**
1289
	 * Update the post meta
1290
	 *
1291
	 * @since  1.5
1292
	 * @access public
1293
	 *
1294
	 * @param  string $meta_key The meta key to update
1295
	 * @param  string $meta_value The meta value
1296
	 * @param  string $prev_value Previous meta value
1297
	 *
1298
	 * @return int|bool           Meta ID if the key didn't exist, true on successful update, false on failure
1299
	 */
1300
	public function update_meta( $meta_key = '', $meta_value = '', $prev_value = '' ) {
1301
		if ( empty( $meta_key ) ) {
1302
			return false;
1303
		}
1304
1305
1306
		/**
1307
		 * Filter the single meta key while updating
1308
		 *
1309
		 * @since 1.5
1310
		 */
1311
		$meta_value = apply_filters( "give_update_payment_meta_{$meta_key}", $meta_value, $this->ID );
1312
1313
		return give_update_meta( $this->ID, $meta_key, $meta_value, $prev_value );
1314
	}
1315
1316
	/**
1317
	 * When a payment is set to a status of 'refunded' process the necessary actions to reduce stats
1318
	 *
1319
	 * @since  1.5
1320
	 * @access private
1321
	 *
1322
	 * @return void
1323
	 */
1324
	private function process_refund() {
1325
		$process_refund = true;
1326
1327
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1328
		if ( 'publish' != $this->old_status || 'refunded' != $this->status ) {
1329
			$process_refund = false;
1330
		}
1331
1332
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1333
		$process_refund = apply_filters( 'give_should_process_refund', $process_refund, $this );
1334
1335
		if ( false === $process_refund ) {
1336
			return;
1337
		}
1338
1339
		/**
1340
		 * Fires before refunding payment.
1341
		 *
1342
		 * @since 1.5
1343
		 *
1344
		 * @param Give_Payment $this Payment object.
1345
		 */
1346
		do_action( 'give_pre_refund_payment', $this );
1347
1348
		$decrease_earnings       = apply_filters( 'give_decrease_store_earnings_on_refund', true, $this );
1349
		$decrease_customer_value = apply_filters( 'give_decrease_customer_value_on_refund', true, $this );
1350
		$decrease_purchase_count = apply_filters( 'give_decrease_customer_purchase_count_on_refund', true, $this );
1351
1352
		$this->maybe_alter_stats( $decrease_earnings, $decrease_customer_value, $decrease_purchase_count );
1353
		$this->delete_sales_logs();
1354
1355
		// @todo: Refresh only range related stat cache
1356
		give_delete_donation_stats();
1357
1358
		/**
1359
		 * Fires after refunding payment.
1360
		 *
1361
		 * @since 1.5
1362
		 *
1363
		 * @param Give_Payment $this Payment object.
1364
		 */
1365
		do_action( 'give_post_refund_payment', $this );
1366
	}
1367
1368
	/**
1369
	 * Process when a payment is set to failed
1370
	 *
1371
	 * @since  1.5
1372
	 * @access private
1373
	 *
1374
	 * @return void
1375
	 */
1376
	private function process_failure() {
1377
1378
	}
1379
1380
	/**
1381
	 * Process when a payment moves to pending
1382
	 *
1383
	 * @since  1.5
1384
	 * @access private
1385
	 *
1386
	 * @return void
1387
	 */
1388
	private function process_pending() {
1389
		$process_pending = true;
1390
1391
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1392
		if ( 'publish' != $this->old_status || 'pending' != $this->status ) {
1393
			$process_pending = false;
1394
		}
1395
1396
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1397
		$process_pending = apply_filters( 'give_should_process_pending', $process_pending, $this );
1398
1399
		if ( false === $process_pending ) {
1400
			return;
1401
		}
1402
1403
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_pending', true, $this );
1404
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_pending', true, $this );
1405
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_pending', true, $this );
1406
1407
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1408
		$this->delete_sales_logs();
1409
1410
		$this->completed_date = false;
1411
		$this->update_meta( '_give_completed_date', '' );
1412
1413
		// @todo: Refresh only range related stat cache
1414
		give_delete_donation_stats();
1415
	}
1416
1417
	/**
1418
	 * Process when a payment moves to cancelled.
1419
	 *
1420
	 * @since  1.5
1421
	 * @access private
1422
	 *
1423
	 * @return void
1424
	 */
1425
	private function process_cancelled() {
1426
		$process_cancelled = true;
1427
1428
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1429
		if ( 'publish' != $this->old_status || 'cancelled' != $this->status ) {
1430
			$process_cancelled = false;
1431
		}
1432
1433
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1434
		$process_cancelled = apply_filters( 'give_should_process_cancelled', $process_cancelled, $this );
1435
1436
		if ( false === $process_cancelled ) {
1437
			return;
1438
		}
1439
1440
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_cancelled', true, $this );
1441
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_cancelled', true, $this );
1442
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_cancelled', true, $this );
1443
1444
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1445
		$this->delete_sales_logs();
1446
1447
		$this->completed_date = false;
1448
		$this->update_meta( '_give_completed_date', '' );
1449
1450
		// @todo: Refresh only range related stat cache
1451
		give_delete_donation_stats();
1452
	}
1453
1454
	/**
1455
	 * Process when a payment moves to revoked.
1456
	 *
1457
	 * @since  1.5
1458
	 * @return void
1459
	 */
1460
	private function process_revoked() {
1461
		$process_revoked = true;
1462
1463
		// If the payment was not in publish, don't decrement stats as they were never incremented.
1464
		if ( 'publish' != $this->old_status || 'revoked' != $this->status ) {
1465
			$process_revoked = false;
1466
		}
1467
1468
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1469
		$process_revoked = apply_filters( 'give_should_process_revoked', $process_revoked, $this );
1470
1471
		if ( false === $process_revoked ) {
1472
			return;
1473
		}
1474
1475
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_revoked', true, $this );
1476
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_revoked', true, $this );
1477
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_revoked', true, $this );
1478
1479
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1480
		$this->delete_sales_logs();
1481
1482
		$this->completed_date = false;
1483
		$this->update_meta( '_give_completed_date', '' );
1484
1485
		// @todo: Refresh only range related stat cache
1486
		give_delete_donation_stats();
1487
	}
1488
1489
	/**
1490
	 * Used during the process of moving to refunded or pending, to decrement stats
1491
	 *
1492
	 * @since  1.5
1493
	 * @access private
1494
	 *
1495
	 * @param  bool $alter_store_earnings If the method should alter the store earnings
1496
	 * @param  bool $alter_customer_value If the method should reduce the donor value
1497
	 * @param  bool $alter_customer_purchase_count If the method should reduce the donor's purchase count
1498
	 *
1499
	 * @return void
1500
	 */
1501
	private function maybe_alter_stats( $alter_store_earnings, $alter_customer_value, $alter_customer_purchase_count ) {
1502
1503
		give_undo_donation( $this->ID );
1504
1505
		// Decrease store earnings.
1506
		if ( true === $alter_store_earnings ) {
1507
			give_decrease_total_earnings( $this->total );
1508
		}
1509
1510
		// Decrement the stats for the donor.
1511
		if ( ! empty( $this->customer_id ) ) {
1512
1513
			$donor = new Give_Donor( $this->customer_id );
1514
1515
			if ( true === $alter_customer_value ) {
1516
				$donor->decrease_value( $this->total );
1517
			}
1518
1519
			if ( true === $alter_customer_purchase_count ) {
1520
				$donor->decrease_donation_count();
1521
			}
1522
		}
1523
1524
	}
1525
1526
	/**
1527
	 * Delete sales logs for this donation
1528
	 *
1529
	 * @since  1.5
1530
	 * @access private
1531
	 *
1532
	 * @return void
1533
	 */
1534
	private function delete_sales_logs() {
1535
		global $give_logs;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

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

1. Pass all data via parameters

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

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

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

    public function myFunction() {
        // Do something
    }
}
Loading history...
1536
1537
		// Remove related sale log entries.
1538
		$give_logs->delete_logs(
1539
			null,
1540
			'sale',
1541
			array(
1542
				array(
1543
					'key'   => '_give_log_payment_id',
1544
					'value' => $this->ID,
1545
				),
1546
			)
1547
		);
1548
	}
1549
1550
	/**
1551
	 * Setup functions only, these are not to be used by developers.
1552
	 * These functions exist only to allow the setup routine to be backwards compatible with our old
1553
	 * helper functions.
1554
	 *
1555
	 * These will run whenever setup_payment is called, which should only be called once.
1556
	 * To update an attribute, update it directly instead of re-running the setup routine
1557
	 */
1558
1559
	/**
1560
	 * Setup the payment completed date
1561
	 *
1562
	 * @since  1.5
1563
	 * @access private
1564
	 *
1565
	 * @return string The date the payment was completed
1566
	 */
1567
	private function setup_completed_date() {
1568
		$payment = get_post( $this->ID );
1569
1570
		if ( 'pending' == $payment->post_status || 'preapproved' == $payment->post_status ) {
1571
			return false; // This payment was never completed.
1572
		}
1573
1574
		$date = ( $date = $this->get_meta( '_give_completed_date', true ) ) ? $date : $payment->modified_date;
1575
1576
		return $date;
1577
	}
1578
1579
	/**
1580
	 * Setup the payment mode
1581
	 *
1582
	 * @since  1.5
1583
	 * @access private
1584
	 *
1585
	 * @return string The payment mode
1586
	 */
1587
	private function setup_mode() {
1588
		return $this->get_meta( '_give_payment_mode' );
1589
	}
1590
1591
	/**
1592
	 * Setup the payment total
1593
	 *
1594
	 * @since  1.5
1595
	 * @access private
1596
	 *
1597
	 * @return float The payment total
1598
	 */
1599
	private function setup_total() {
1600
		$amount = $this->get_meta( '_give_payment_total', true );
1601
1602
		if ( empty( $amount ) && '0.00' != $amount ) {
1603
			$meta = $this->get_meta( '_give_payment_meta', true );
1604
			$meta = maybe_unserialize( $meta );
1605
1606
			if ( isset( $meta['amount'] ) ) {
1607
				$amount = $meta['amount'];
1608
			}
1609
		}
1610
1611
		return round( floatval( $amount ), give_currency_decimal_filter() );
1612
	}
1613
1614
	/**
1615
	 * Setup the payment subtotal
1616
	 *
1617
	 * @since  1.5
1618
	 * @access private
1619
	 *
1620
	 * @return float The subtotal of the payment
1621
	 */
1622
	private function setup_subtotal() {
1623
		$subtotal = $this->total;
1624
1625
		return $subtotal;
1626
	}
1627
1628
	/**
1629
	 * Setup the currency code
1630
	 *
1631
	 * @since  1.5
1632
	 * @since  2.0 Set currency from _give_payment_currency meta key
1633
	 * @access private
1634
	 *
1635
	 * @return string The currency for the payment
1636
	 */
1637
	private function setup_currency() {
1638
		$currency = $this->get_meta( '_give_payment_currency', true );
1639
		$currency = ! empty( $currency ) ?
1640
			$currency :
1641
			apply_filters( 'give_payment_currency_default', give_get_currency(), $this );
1642
1643
		return $currency;
1644
	}
1645
1646
	/**
1647
	 * Setup the gateway used for the payment
1648
	 *
1649
	 * @since  1.5
1650
	 * @access private
1651
	 *
1652
	 * @return string The gateway
1653
	 */
1654
	private function setup_gateway() {
1655
		$gateway = $this->get_meta( '_give_payment_gateway', true );
1656
1657
		return $gateway;
1658
	}
1659
1660
	/**
1661
	 * Setup the donation ID
1662
	 *
1663
	 * @since  1.5
1664
	 * @access private
1665
	 *
1666
	 * @return string The donation ID
1667
	 */
1668
	private function setup_transaction_id() {
1669
		$transaction_id = $this->get_meta( '_give_payment_transaction_id', true );
1670
1671
		if ( empty( $transaction_id ) ) {
1672
			$gateway        = $this->gateway;
1673
			$transaction_id = apply_filters( "give_get_payment_transaction_id-{$gateway}", $this->ID );
1674
		}
1675
1676
		return $transaction_id;
1677
	}
1678
1679
	/**
1680
	 * Setup the IP Address for the payment
1681
	 *
1682
	 * @since  1.5
1683
	 * @since  2.0 Set ip address from _give_payment_donor_ip meta key
1684
	 * @access private
1685
	 *
1686
	 * @return string The IP address for the payment
1687
	 */
1688
	private function setup_ip() {
1689
		$ip = $this->get_meta( '_give_payment_donor_ip', true );
1690
1691
		return $ip;
1692
	}
1693
1694
	/**
1695
	 * Setup the donor ID.
1696
	 *
1697
	 * @since  1.5
1698
	 * @since  2.0 Set id from _give_payment_donor_id meta key
1699
	 * @access private
1700
	 *
1701
	 * @return int The Donor ID.
1702
	 */
1703
	private function setup_donor_id() {
1704
		$donor_id = $this->get_meta( '_give_payment_donor_id', true );
1705
1706
		return $donor_id;
1707
	}
1708
1709
	/**
1710
	 * Setup the User ID associated with the donation
1711
	 *
1712
	 * @since  1.5
1713
	 * @since  2.0 Get user id connect to donor from donor table instead of payment meta.
1714
	 *
1715
	 * @access private
1716
	 *
1717
	 * @return int The User ID
1718
	 */
1719
	private function setup_user_id() {
1720
		if ( ! ( $user_id = Give_Cache::payment( $this->ID, 'user_id' ) ) ) {
1721
			$donor   = Give()->customers->get_customer_by( 'id', $this->customer_id );
0 ignored issues
show
Bug introduced by
The property customers does not seem to exist in Give.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1722
			$user_id = $donor ? absint( $donor->user_id ) : 0;
1723
1724
			Give_Cache::payment( $this->ID, 'user_id', $user_id );
1725
		}
1726
1727
		return $user_id;
1728
	}
1729
1730
	/**
1731
	 * Setup the email address for the donation.
1732
	 *
1733
	 * @since  1.5
1734
	 * @since  2.0 Set email from _give_payment_donor_email meta key
1735
	 *
1736
	 * @access private
1737
	 *
1738
	 * @return string The email address for the payment.
1739
	 */
1740
	private function setup_email() {
1741
		$email = $this->get_meta( '_give_payment_donor_email', true );
1742
1743
		if ( empty( $email ) ) {
1744
			$email = Give()->donors->get_column( 'email', $this->customer_id );
1745
		}
1746
1747
		return $email;
1748
	}
1749
1750
	/**
1751
	 * Setup the user info.
1752
	 *
1753
	 * @since  1.5
1754
	 * @access private
1755
	 *
1756
	 * @return array The user info associated with the payment.
1757
	 */
1758
	private function setup_user_info() {
1759
		$defaults = array(
1760
			'first_name' => $this->first_name,
1761
			'last_name'  => $this->last_name,
1762
		);
1763
1764
		$user_info = isset( $this->payment_meta['user_info'] ) ? maybe_unserialize( $this->payment_meta['user_info'] ) : array();
1765
		$user_info = wp_parse_args( $user_info, $defaults );
1766
1767
		if ( empty( $user_info ) ) {
1768
			// Get the donor, but only if it's been created.
1769
			$donor = new Give_Donor( $this->customer_id );
1770
1771
			if ( $donor->id > 0 ) {
1772
				$name      = explode( ' ', $donor->name, 2 );
1773
				$user_info = array(
1774
					'first_name' => $name[0],
1775
					'last_name'  => $name[1],
1776
					'email'      => $donor->email,
1777
					'discount'   => 'none',
1778
				);
1779
			}
1780
		} else {
1781
			// Get the donor, but only if it's been created.
1782
			$donor = new Give_Donor( $this->customer_id );
1783
			if ( $donor->id > 0 ) {
1784
				foreach ( $user_info as $key => $value ) {
1785
					if ( ! empty( $value ) ) {
1786
						continue;
1787
					}
1788
1789
					switch ( $key ) {
1790
						case 'first_name':
1791
							$name = explode( ' ', $donor->name, 2 );
1792
1793
							$user_info[ $key ] = $name[0];
1794
							break;
1795
1796
						case 'last_name':
1797
							$name      = explode( ' ', $donor->name, 2 );
1798
							$last_name = ! empty( $name[1] ) ? $name[1] : '';
1799
1800
							$user_info[ $key ] = $last_name;
1801
							break;
1802
1803
						case 'email':
1804
							$user_info[ $key ] = $donor->email;
1805
							break;
1806
					}
1807
				}
1808
			}
1809
		}// End if().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1810
1811
		return $user_info;
1812
1813
	}
1814
1815
	/**
1816
	 * Setup the Address for the payment.
1817
	 *
1818
	 * @since  1.5
1819
	 * @access private
1820
	 *
1821
	 * @return array The Address information for the payment.
1822
	 */
1823
	private function setup_address() {
1824
		// Get address from cache.
1825
		if ( ! ( $address = Give_Cache::payment( $this->ID, 'address' ) ) ) {
1826
			$address['line1']   = give_get_meta( $this->ID, '_give_donor_billing_address1', true );
1827
			$address['line2']   = give_get_meta( $this->ID, '_give_donor_billing_address2', true );
1828
			$address['city']    = give_get_meta( $this->ID, '_give_donor_billing_city', true );
1829
			$address['state']   = give_get_meta( $this->ID, '_give_donor_billing_state', true );
1830
			$address['zip']     = give_get_meta( $this->ID, '_give_donor_billing_zip', true );
1831
			$address['country'] = give_get_meta( $this->ID, '_give_donor_billing_country', true );
1832
1833
			// Save address to cache.
1834
			Give_Cache::payment( $this->ID, 'address', $address );
1835
		}
1836
1837
		$address = wp_parse_args(
1838
			$address,
1839
			array(
1840
				'line1'   => '',
1841
				'line2'   => '',
1842
				'city'    => '',
1843
				'country' => '',
1844
				'state'   => '',
1845
				'zip'     => '',
1846
			)
1847
		);
1848
1849
		return $address;
1850
	}
1851
1852
	/**
1853
	 * Setup the form title.
1854
	 *
1855
	 * @since  1.5
1856
	 * @access private
1857
	 *
1858
	 * @return string The Form Title.
1859
	 */
1860
	private function setup_form_title() {
1861
1862
		$form_id = $this->get_meta( '_give_payment_form_title', true );
1863
1864
		return $form_id;
1865
	}
1866
1867
	/**
1868
	 * Setup the form ID.
1869
	 *
1870
	 * @since  1.5
1871
	 * @access private
1872
	 *
1873
	 * @return int The Form ID
1874
	 */
1875
	private function setup_form_id() {
1876
1877
		$form_id = $this->get_meta( '_give_payment_form_id', true );
1878
1879
		return $form_id;
1880
	}
1881
1882
	/**
1883
	 * Setup the price ID.
1884
	 *
1885
	 * @since  1.5
1886
	 * @access private
1887
	 *
1888
	 * @return int The Form Price ID.
1889
	 */
1890
	private function setup_price_id() {
1891
		$price_id = $this->get_meta( '_give_payment_price_id', true );
1892
1893
		return $price_id;
1894
	}
1895
1896
	/**
1897
	 * Setup the payment key.
1898
	 *
1899
	 * @since  1.5
1900
	 * @access private
1901
	 *
1902
	 * @return string The Payment Key.
1903
	 */
1904
	private function setup_payment_key() {
1905
		$key = $this->get_meta( '_give_payment_purchase_key', true );
1906
1907
		return $key;
1908
	}
1909
1910
	/**
1911
	 * Setup the payment number.
1912
	 *
1913
	 * @since  1.5
1914
	 * @access private
1915
	 *
1916
	 * @return int|string Integer by default, or string if sequential order numbers is enabled.
1917
	 */
1918
	private function setup_payment_number() {
1919
		$number = $this->ID;
1920
1921
		if ( give_get_option( 'enable_sequential' ) ) {
1922
1923
			$number = $this->get_meta( '_give_payment_number', true );
1924
1925
			if ( ! $number ) {
1926
1927
				$number = $this->ID;
1928
1929
			}
1930
		}
1931
1932
		return $number;
1933
	}
1934
1935
	/**
1936
	 * Converts this object into an array for special cases.
1937
	 *
1938
	 * @access public
1939
	 *
1940
	 * @return array The payment object as an array.
1941
	 */
1942
	public function array_convert() {
1943
		return get_object_vars( $this );
1944
	}
1945
1946
1947
	/**
1948
	 * Flag to check if donation is completed or not.
1949
	 *
1950
	 * @since  1.8
1951
	 * @access public
1952
	 *
1953
	 * @return bool
1954
	 */
1955
	public function is_completed() {
1956
		return ( 'publish' === $this->status && $this->completed_date );
1957
	}
1958
1959
	/**
1960
	 * Retrieve payment completion date.
1961
	 *
1962
	 * @since  1.5
1963
	 * @access private
1964
	 *
1965
	 * @return string Date payment was completed.
1966
	 */
1967
	private function get_completed_date() {
1968
		return apply_filters( 'give_payment_completed_date', $this->completed_date, $this->ID, $this );
1969
	}
1970
1971
	/**
1972
	 * Retrieve payment subtotal.
1973
	 *
1974
	 * @since  1.5
1975
	 * @access private
1976
	 *
1977
	 * @return float Payment subtotal.
1978
	 */
1979
	private function get_subtotal() {
1980
		return apply_filters( 'give_get_payment_subtotal', $this->subtotal, $this->ID, $this );
1981
	}
1982
1983
	/**
1984
	 * Retrieve payment currency.
1985
	 *
1986
	 * @since  1.5
1987
	 * @access private
1988
	 *
1989
	 * @return string Payment currency code.
1990
	 */
1991
	private function get_currency() {
1992
		return apply_filters( 'give_payment_currency_code', $this->currency, $this->ID, $this );
1993
	}
1994
1995
	/**
1996
	 * Retrieve payment gateway.
1997
	 *
1998
	 * @since  1.5
1999
	 * @access private
2000
	 *
2001
	 * @return string Gateway used.
2002
	 */
2003
	private function get_gateway() {
2004
		return apply_filters( 'give_payment_gateway', $this->gateway, $this->ID, $this );
2005
	}
2006
2007
	/**
2008
	 * Retrieve donation ID.
2009
	 *
2010
	 * @since  1.5
2011
	 * @access private
2012
	 *
2013
	 * @return string Donation ID from merchant processor.
2014
	 */
2015
	private function get_transaction_id() {
2016
		return apply_filters( 'give_get_payment_transaction_id', $this->transaction_id, $this->ID, $this );
2017
	}
2018
2019
	/**
2020
	 * Retrieve payment IP
2021
	 *
2022
	 * @since  1.5
2023
	 * @access private
2024
	 *
2025
	 * @return string Payment IP address
2026
	 */
2027
	private function get_ip() {
2028
		return apply_filters( 'give_payment_user_ip', $this->ip, $this->ID, $this );
2029
	}
2030
2031
	/**
2032
	 * Retrieve payment donor ID.
2033
	 *
2034
	 * @since  1.5
2035
	 * @access private
2036
	 *
2037
	 * @return int Payment donor ID.
2038
	 */
2039
	private function get_donor_id() {
2040
		return apply_filters( 'give_payment_customer_id', $this->customer_id, $this->ID, $this );
2041
	}
2042
2043
	/**
2044
	 * Retrieve payment user ID.
2045
	 *
2046
	 * @since  1.5
2047
	 * @access private
2048
	 *
2049
	 * @return int Payment user ID.
2050
	 */
2051
	private function get_user_id() {
2052
		return apply_filters( 'give_payment_user_id', $this->user_id, $this->ID, $this );
2053
	}
2054
2055
	/**
2056
	 * Retrieve payment email.
2057
	 *
2058
	 * @since  1.5
2059
	 * @access private
2060
	 *
2061
	 * @return string Payment donor email.
2062
	 */
2063
	private function get_email() {
2064
		return apply_filters( 'give_payment_user_email', $this->email, $this->ID, $this );
2065
	}
2066
2067
	/**
2068
	 * Retrieve payment user info.
2069
	 *
2070
	 * @since  1.5
2071
	 * @access private
2072
	 *
2073
	 * @return array Payment user info.
2074
	 */
2075
	private function get_user_info() {
2076
		return apply_filters( 'give_payment_meta_user_info', $this->user_info, $this->ID, $this );
2077
	}
2078
2079
	/**
2080
	 * Retrieve payment billing address.
2081
	 *
2082
	 * @since  1.5
2083
	 * @access private
2084
	 *
2085
	 * @return array Payment billing address.
2086
	 */
2087
	private function get_address() {
2088
		return apply_filters( 'give_payment_address', $this->address, $this->ID, $this );
2089
	}
2090
2091
	/**
2092
	 * Retrieve payment key.
2093
	 *
2094
	 * @since  1.5
2095
	 * @access private
2096
	 *
2097
	 * @return string Payment key.
2098
	 */
2099
	private function get_key() {
2100
		return apply_filters( 'give_payment_key', $this->key, $this->ID, $this );
2101
	}
2102
2103
	/**
2104
	 * Retrieve payment form id
2105
	 *
2106
	 * @since  1.5
2107
	 * @access private
2108
	 *
2109
	 * @return string Payment form id
2110
	 */
2111
	private function get_form_id() {
2112
		return apply_filters( 'give_payment_form_id', $this->form_id, $this->ID, $this );
2113
	}
2114
2115
	/**
2116
	 * Retrieve payment number
2117
	 *
2118
	 * @since  1.5
2119
	 * @access private
2120
	 *
2121
	 * @return int|string Payment number
2122
	 */
2123
	private function get_number() {
2124
		return apply_filters( 'give_payment_number', $this->number, $this->ID, $this );
2125
	}
2126
}
2127