Completed
Push — issues/1132 ( bd8c69...897d14 )
by Ravinder
35:40 queued 15:29
created

Give_Payment::setup_address()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 12
nc 2
nop 0
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 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
		// Flush cache before saving payment.
423
		Give_Cache::delete_group( 'donation', $this->ID );
424
425
		$ignore = array( '_ID' );
426
427
		if ( $key === 'status' ) {
428
			$this->old_status = $this->status;
429
		}
430
431
		if ( ! in_array( $key, $ignore ) ) {
432
			$this->pending[ $key ] = $value;
433
		}
434
435
		if ( '_ID' !== $key ) {
436
			$this->$key = $value;
437
		}
438
	}
439
440
	/**
441
	 * Magic ISSET function, which allows empty checks on protected elements
442
	 *
443
	 * @since  1.5
444
	 * @access public
445
	 *
446
	 * @param  string $name The attribute to get
447
	 *
448
	 * @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...
449
	 */
450
	public function __isset( $name ) {
451
		if ( property_exists( $this, $name ) ) {
452
			return false === empty( $this->$name );
453
		} else {
454
			return null;
455
		}
456
	}
457
458
	/**
459
	 * Setup payment properties
460
	 *
461
	 * @since  1.5
462
	 * @access private
463
	 *
464
	 * @param  int $payment_id The payment ID
465
	 *
466
	 * @return bool            If the setup was successful or not
467
	 */
468
	private function setup_payment( $payment_id ) {
469
		$this->pending = array();
470
471
		if ( empty( $payment_id ) ) {
472
			return false;
473
		}
474
475
		$payment = get_post( $payment_id );
476
477
		if ( ! $payment || is_wp_error( $payment ) ) {
478
			return false;
479
		}
480
481
		if ( 'give_payment' !== $payment->post_type ) {
482
			return false;
483
		}
484
485
		/**
486
		 * Fires before payment setup.
487
		 *
488
		 * Allow extensions to perform actions before the payment is loaded.
489
		 *
490
		 * @since 1.5
491
		 *
492
		 * @param Give_Payment $this       Payment object.
493
		 * @param int          $payment_id The ID of the payment.
494
		 */
495
		do_action( 'give_pre_setup_payment', $this, $payment_id );
496
497
		// Primary Identifier.
498
		$this->ID = absint( $payment_id );
499
500
		// Protected ID that can never be changed.
501
		$this->_ID = absint( $payment_id );
502
503
		// We have a payment, get the generic payment_meta item to reduce calls to it.
504
		$this->payment_meta = $this->get_meta();
505
506
		// Status and Dates.
507
		$this->date           = $payment->post_date;
508
		$this->post_date      = $payment->post_date;
509
		$this->completed_date = $this->setup_completed_date();
510
		$this->status         = $payment->post_status;
511
		$this->post_status    = $this->status;
512
		$this->mode           = $this->setup_mode();
513
		$this->parent_payment = $payment->post_parent;
514
515
		$all_payment_statuses  = give_get_payment_statuses();
516
		$this->status_nicename = array_key_exists( $this->status, $all_payment_statuses ) ? $all_payment_statuses[ $this->status ] : ucfirst( $this->status );
517
518
		// Currency Based.
519
		$this->total      = $this->setup_total();
520
		$this->subtotal   = $this->setup_subtotal();
521
		$this->currency   = $this->setup_currency();
522
523
		// Gateway based.
524
		$this->gateway        = $this->setup_gateway();
525
		$this->transaction_id = $this->setup_transaction_id();
526
527
		// User based.
528
		$this->ip          = $this->setup_ip();
529
		$this->customer_id = $this->setup_donor_id();
530
		$this->user_id     = $this->setup_user_id();
531
		$this->email       = $this->setup_email();
532
		$this->user_info   = $this->setup_user_info();
533
		$this->address     = $this->setup_address();
534
		$this->first_name  = $this->user_info['first_name'];
535
		$this->last_name   = $this->user_info['last_name'];
536
537
		// Other Identifiers.
538
		$this->form_title = $this->setup_form_title();
539
		$this->form_id    = $this->setup_form_id();
540
		$this->price_id   = $this->setup_price_id();
541
		$this->key        = $this->setup_payment_key();
542
		$this->number     = $this->setup_payment_number();
543
544
		/**
545
		 * Fires after payment setup.
546
		 *
547
		 * Allow extensions to add items to this object via hook.
548
		 *
549
		 * @since 1.5
550
		 *
551
		 * @param Give_Payment $this       Payment object.
552
		 * @param int          $payment_id The ID of the payment.
553
		 */
554
		do_action( 'give_setup_payment', $this, $payment_id );
555
556
		return true;
557
	}
558
559
	/**
560
	 * Payment class object is storing various meta value in object parameter.
561
	 * So if user is updating payment meta but not updating payment object, then payment meta values will not reflect/changes on payment meta automatically
562
	 * 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.
563
	 * To prevent that user can use this function after updating any payment meta value ( in bulk or single update ).
564
	 *
565
	 * @since  1.6
566
	 * @access public
567
	 *
568
	 * @param  int $payment_id Payment ID.
569
	 *
570
	 * @return void
571
	 */
572
	public function update_payment_setup( $payment_id ) {
573
		$this->setup_payment( $payment_id );
574
	}
575
576
	/**
577
	 * Create the base of a payment.
578
	 *
579
	 * @since  1.5
580
	 * @access private
581
	 *
582
	 * @return int|bool False on failure, the payment ID on success.
583
	 */
584
	private function insert_payment() {
585
586
		// Construct the payment title.
587
		$payment_title = '';
588
		if ( ! empty( $this->first_name ) && ! empty( $this->last_name ) ) {
589
			$payment_title = $this->first_name . ' ' . $this->last_name;
590
		} elseif ( ! empty( $this->first_name ) && empty( $this->last_name ) ) {
591
			$payment_title = $this->first_name;
592
		} elseif ( ! empty( $this->email ) && is_email( $this->email ) ) {
593
			$payment_title = $this->email;
594
		}
595
596
		// Set Key.
597
		if ( empty( $this->key ) ) {
598
599
			$auth_key             = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
600
			$this->key            = strtolower( md5( $this->email . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'give', true ) ) );  // Unique key
601
			$this->pending['key'] = $this->key;
602
		}
603
604
		// Set IP.
605
		if ( empty( $this->ip ) ) {
606
607
			$this->ip            = give_get_ip();
608
			$this->pending['ip'] = $this->ip;
609
610
		}
611
612
		$payment_data = array(
613
			'price'        => $this->total,
614
			'date'         => $this->date,
615
			'user_email'   => $this->email,
616
			'purchase_key' => $this->key,
617
			'form_title'   => $this->form_title,
618
			'form_id'      => $this->form_id,
619
			'price_id'     => $this->price_id,
620
			'currency'     => $this->currency,
621
			'user_info'    => array(
622
				'id'         => $this->user_id,
623
				'email'      => $this->email,
624
				'first_name' => $this->first_name,
625
				'last_name'  => $this->last_name,
626
				'address'    => $this->address,
627
			),
628
			'status'       => $this->status,
629
		);
630
631
		$args = apply_filters( 'give_insert_payment_args', array(
632
			'post_title'    => $payment_title,
633
			'post_status'   => $this->status,
634
			'post_type'     => 'give_payment',
635
			'post_date'     => ! empty( $this->date ) ? $this->date : null,
636
			'post_date_gmt' => ! empty( $this->date ) ? get_gmt_from_date( $this->date ) : null,
637
			'post_parent'   => $this->parent_payment,
638
		), $payment_data );
639
640
		// Create a blank payment
641
		$payment_id = wp_insert_post( $args );
642
643
		if ( ! empty( $payment_id ) ) {
644
645
			$this->ID  = $payment_id;
646
			$this->_ID = $payment_id;
647
648
			$donor = new stdClass;
649
650
			if ( did_action( 'give_pre_process_donation' ) && is_user_logged_in() ) {
651
				$donor = new Give_Donor( get_current_user_id(), true );
652
653
				// Donor is logged in but used a different email to purchase with so assign to their donor record.
654
				if ( ! empty( $donor->id ) && $this->email != $donor->email ) {
655
					$donor->add_email( $this->email );
656
				}
657
			}
658
659
			if ( empty( $donor->id ) ) {
660
				$donor = new Give_Donor( $this->email );
661
			}
662
663
			if ( empty( $donor->id ) ) {
664
665
				$donor_data = array(
666
					'name'    => ! is_email( $payment_title ) ? $this->first_name . ' ' . $this->last_name : '',
667
					'email'   => $this->email,
668
					'user_id' => $this->user_id,
669
				);
670
671
				$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...
672
673
			}
674
675
			$this->customer_id            = $donor->id;
676
			$this->pending['customer_id'] = $this->customer_id;
677
			$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...
678
679
			$this->payment_meta = apply_filters( 'give_payment_meta', $this->payment_meta, $payment_data );
680
681
			$this->update_meta( '_give_payment_meta', $this->payment_meta );
682
			$this->new = true;
683
		}// 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...
684
685
		return $this->ID;
686
687
	}
688
689
	/**
690
	 * Save
691
	 *
692
	 * Once items have been set, an update is needed to save them to the database.
693
	 *
694
	 * @access public
695
	 *
696
	 * @return bool  True of the save occurred, false if it failed or wasn't needed
697
	 */
698
	public function save() {
699
		// flush cache before saving payment.
700
		Give_Cache::delete_group( 'donation', $this->ID );
701
702
		$saved = false;
703
704
		// Must have an ID.
705
		if ( empty( $this->ID ) ) {
706
707
			$payment_id = $this->insert_payment();
708
709
			if ( false === $payment_id ) {
710
				$saved = false;
711
			} else {
712
				$this->ID = $payment_id;
713
			}
714
		}
715
716
		// Set ID if not matching.
717
		if ( $this->ID !== $this->_ID ) {
718
			$this->ID = $this->_ID;
719
		}
720
721
		// If we have something pending, let's save it.
722
		if ( ! empty( $this->pending ) ) {
723
724
			$total_increase = 0;
725
			$total_decrease = 0;
726
727
			foreach ( $this->pending as $key => $value ) {
728
729
				switch ( $key ) {
730
731
					case 'donations':
732
						// Update totals for pending donations.
733
						foreach ( $this->pending[ $key ] as $item ) {
734
735
							$quantity = isset( $item['quantity'] ) ? $item['quantity'] : 1;
736
							$price_id = isset( $item['price_id'] ) ? $item['price_id'] : 0;
737
738
							switch ( $item['action'] ) {
739
740
								case 'add':
741
742
									$price = $item['price'];
743
744
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
745
746
										// Add sales logs.
747
										$log_date = date_i18n( 'Y-m-d G:i:s', current_time( 'timestamp' ) );
748
749
										$y = 0;
750
										while ( $y < $quantity ) {
751
752
											give_record_donation_in_log( $item['id'], $this->ID, $price_id, $log_date );
753
											$y ++;
754
										}
755
756
										$form = new Give_Donate_Form( $item['id'] );
757
										$form->increase_sales( $quantity );
758
										$form->increase_earnings( $price );
759
760
										$total_increase += $price;
761
									}
762
									break;
763
764
								case 'remove':
765
									$log_args = array(
766
										'post_type'   => 'give_log',
767
										'post_parent' => $item['id'],
768
										'numberposts' => $quantity,
769
										'meta_query'  => array(
770
											array(
771
												'key'     => '_give_log_payment_id',
772
												'value'   => $this->ID,
773
												'compare' => '=',
774
											),
775
											array(
776
												'key'     => '_give_log_price_id',
777
												'value'   => $price_id,
778
												'compare' => '=',
779
											),
780
										),
781
									);
782
783
									$found_logs = get_posts( $log_args );
784
									foreach ( $found_logs as $log ) {
785
										wp_delete_post( $log->ID, true );
786
									}
787
788
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
789
										$form = new Give_Donate_Form( $item['id'] );
790
										$form->decrease_sales( $quantity );
791
										$form->decrease_earnings( $item['amount'] );
792
793
										$total_decrease += $item['amount'];
794
									}
795
									break;
796
797
							}// 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...
798
						}// 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...
799
						break;
800
801
					case 'status':
802
						$this->update_status( $this->status );
803
						break;
804
805
					case 'gateway':
806
						$this->update_meta( '_give_payment_gateway', $this->gateway );
807
						break;
808
809
					case 'mode':
810
						$this->update_meta( '_give_payment_mode', $this->mode );
811
						break;
812
813
					case 'transaction_id':
814
						$this->update_meta( '_give_payment_transaction_id', $this->transaction_id );
815
						break;
816
817
					case 'ip':
818
						$this->update_meta( '_give_payment_donor_ip', $this->ip );
819
						break;
820
821
					case 'customer_id':
822
						$this->update_meta( '_give_payment_donor_id', $this->customer_id );
823
						break;
824
825
					// case 'user_id':
826
					// 	$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...
827
					// 	break;
828
829
					case 'form_title':
830
						$this->update_meta( '_give_payment_form_title', $this->form_title );
831
						break;
832
833
					case 'form_id':
834
						$this->update_meta( '_give_payment_form_id', $this->form_id );
835
						break;
836
837
					case 'price_id':
838
						$this->update_meta( '_give_payment_price_id', $this->price_id );
839
						break;
840
841
					case 'first_name':
842
						$this->user_info['first_name'] = $this->first_name;
843
						break;
844
845
					case 'last_name':
846
						$this->user_info['last_name'] = $this->last_name;
847
						break;
848
849
					case 'address':
850
						$this->user_info['address'] = $this->address;
851
						break;
852
853
					case 'email':
854
						$this->update_meta( '_give_payment_donor_email', $this->email );
855
						break;
856
857
					case 'key':
858
						$this->update_meta( '_give_payment_purchase_key', $this->key );
859
						break;
860
861
					case 'number':
862
						$this->update_meta( '_give_payment_number', $this->number );
863
						break;
864
865
					case 'date':
866
						$args = array(
867
							'ID'        => $this->ID,
868
							'post_date' => $this->date,
869
							'edit_date' => true,
870
						);
871
872
						wp_update_post( $args );
873
						break;
874
875
					case 'completed_date':
876
						$this->update_meta( '_give_completed_date', $this->completed_date );
877
						break;
878
879
					case 'parent_payment':
880
						$args = array(
881
							'ID'          => $this->ID,
882
							'post_parent' => $this->parent_payment,
883
						);
884
885
						wp_update_post( $args );
886
						break;
887
888
					default:
889
						/**
890
						 * Fires while saving payment.
891
						 *
892
						 * @since 1.7
893
						 *
894
						 * @param Give_Payment $this Payment object.
895
						 */
896
						do_action( 'give_payment_save', $this, $key );
897
						break;
898
				}// 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...
899
			}// 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...
900
901
			if ( 'pending' !== $this->status ) {
902
903
				$donor = new Give_Donor( $this->customer_id );
904
905
				$total_change = $total_increase - $total_decrease;
906
				if ( $total_change < 0 ) {
907
908
					$total_change = - ( $total_change );
909
					// Decrease the donor's donation stats.
910
					$donor->decrease_value( $total_change );
911
					give_decrease_total_earnings( $total_change );
912
913
				} elseif ( $total_change > 0 ) {
914
915
					// Increase the donor's donation stats.
916
					$donor->increase_value( $total_change );
917
					give_increase_total_earnings( $total_change );
918
919
				}
920
			}
921
922
			$this->update_meta( '_give_payment_total', $this->total );
923
924
			$new_meta = array(
925
				'form_title' => $this->form_title,
926
				'form_id'    => $this->form_id,
927
				'price_id'   => $this->price_id,
928
				'currency'   => $this->currency,
929
				'user_info'  => $this->user_info,
930
			);
931
932
			$meta        = $this->get_meta();
933
			$merged_meta = array_merge( $meta, $new_meta );
934
935
			// Only save the payment meta if it's changed.
936
			if ( md5( serialize( $meta ) ) !== md5( serialize( $merged_meta ) ) ) {
937
				$updated = $this->update_meta( '_give_payment_meta', $merged_meta );
938
				if ( false !== $updated ) {
939
					$saved = true;
940
				}
941
			}
942
943
			$this->pending = array();
944
			$saved         = true;
945
		}// 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...
946
947
		if ( true === $saved ) {
948
			$this->setup_payment( $this->ID );
949
		}
950
951
		return $saved;
952
	}
953
954
	/**
955
	 * Add a donation to a given payment
956
	 *
957
	 * @since  1.5
958
	 * @access public
959
	 *
960
	 * @param  int   $form_id The donation form to add
961
	 * @param  array $args Other arguments to pass to the function
962
	 * @param  array $options List of donation options
963
	 *
964
	 * @return bool           True when successful, false otherwise
965
	 */
966
	public function add_donation( $form_id = 0, $args = array(), $options = array() ) {
967
968
		$donation = new Give_Donate_Form( $form_id );
969
970
		// Bail if this post isn't a give donation form.
971
		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...
972
			return false;
973
		}
974
975
		// Set some defaults.
976
		$defaults = array(
977
			'price'    => false,
978
			'price_id' => false,
979
		);
980
981
		$args = wp_parse_args( apply_filters( 'give_payment_add_donation_args', $args, $donation->ID ), $defaults );
982
983
		// Allow overriding the price.
984
		if ( false !== $args['price'] ) {
985
			$item_price = $args['price'];
986
		} else {
987
988
			// Deal with variable pricing.
989
			if ( give_has_variable_prices( $donation->ID ) ) {
990
				$prices     = maybe_unserialize( give_get_meta( $form_id, '_give_donation_levels', true ) );
991
				$item_price = '';
992
				// Loop through prices.
993
				foreach ( $prices as $price ) {
994
					// Find a match between price_id and level_id.
995
					// First verify array keys exists THEN make the match.
996
					if ( ( isset( $args['price_id'] ) && isset( $price['_give_id']['level_id'] ) )
997
					     && $args['price_id'] == $price['_give_id']['level_id']
998
					) {
999
						$item_price = $price['_give_amount'];
1000
					}
1001
				}
1002
				// Fallback to the lowest price point.
1003
				if ( $item_price == '' ) {
1004
					$item_price       = give_get_lowest_price_option( $donation->ID );
1005
					$args['price_id'] = give_get_lowest_price_id( $donation->ID );
1006
				}
1007
			} else {
1008
				// Simple form price.
1009
				$item_price = give_get_form_price( $donation->ID );
1010
			}
1011
		}
1012
1013
		// Sanitizing the price here so we don't have a dozen calls later.
1014
		$item_price = give_sanitize_amount( $item_price );
1015
		$total      = round( $item_price, give_currency_decimal_filter() );
1016
1017
		// Add Options.
1018
		$default_options = array();
1019
		if ( false !== $args['price_id'] ) {
1020
			$default_options['price_id'] = (int) $args['price_id'];
1021
		}
1022
		$options = wp_parse_args( $options, $default_options );
1023
1024
		// Do not allow totals to go negative.
1025
		if ( $total < 0 ) {
1026
			$total = 0;
1027
		}
1028
1029
		$donation = array(
1030
			'name'     => $donation->post_title,
1031
			'id'       => $donation->ID,
1032
			'price'    => round( $total, give_currency_decimal_filter() ),
1033
			'subtotal' => round( $total, give_currency_decimal_filter() ),
1034
			'price_id' => $args['price_id'],
1035
			'action'   => 'add',
1036
			'options'  => $options,
1037
		);
1038
1039
		$this->pending['donations'][] = $donation;
1040
1041
		$this->increase_subtotal( $total );
1042
1043
		return true;
1044
1045
	}
1046
1047
	/**
1048
	 * Remove a donation from the payment
1049
	 *
1050
	 * @since  1.5
1051
	 * @access public
1052
	 *
1053
	 * @param  int   $form_id The form ID to remove
1054
	 * @param  array $args Arguments to pass to identify (quantity, amount, price_id)
1055
	 *
1056
	 * @return bool           If the item was removed or not
1057
	 */
1058
	public function remove_donation( $form_id, $args = array() ) {
1059
1060
		// Set some defaults.
1061
		$defaults = array(
1062
			'quantity' => 1,
1063
			'price'    => false,
1064
			'price_id' => false,
1065
		);
1066
		$args     = wp_parse_args( $args, $defaults );
1067
1068
		$form = new Give_Donate_Form( $form_id );
1069
1070
		// Bail if this post isn't a valid give donation form.
1071
		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...
1072
			return false;
1073
		}
1074
1075
		$pending_args             = $args;
1076
		$pending_args['id']       = $form_id;
1077
		$pending_args['amount']   = $this->total;
1078
		$pending_args['price_id'] = false !== $args['price_id'] ? (int) $args['price_id'] : false;
1079
		$pending_args['quantity'] = $args['quantity'];
1080
		$pending_args['action']   = 'remove';
1081
1082
		$this->pending['donations'][] = $pending_args;
1083
1084
		$this->decrease_subtotal( $this->total );
1085
1086
		return true;
1087
	}
1088
1089
1090
	/**
1091
	 * Add a note to a payment
1092
	 *
1093
	 * @since  1.5
1094
	 * @access public
1095
	 *
1096
	 * @param  string $note The note to add
1097
	 *
1098
	 * @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...
1099
	 */
1100
	public function add_note( $note = false ) {
1101
		// Bail if no note specified.
1102
		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...
1103
			return false;
1104
		}
1105
1106
		give_insert_payment_note( $this->ID, $note );
1107
	}
1108
1109
	/**
1110
	 * Increase the payment's subtotal
1111
	 *
1112
	 * @since  1.5
1113
	 * @access private
1114
	 *
1115
	 * @param  float $amount The amount to increase the payment subtotal by.
1116
	 *
1117
	 * @return void
1118
	 */
1119
	private function increase_subtotal( $amount = 0.00 ) {
1120
		$amount         = (float) $amount;
1121
		$this->subtotal += $amount;
1122
1123
		$this->recalculate_total();
1124
	}
1125
1126
	/**
1127
	 * Decrease the payment's subtotal.
1128
	 *
1129
	 * @since  1.5
1130
	 * @access private
1131
	 *
1132
	 * @param  float $amount The amount to decrease the payment subtotal by.
1133
	 *
1134
	 * @return void
1135
	 */
1136
	private function decrease_subtotal( $amount = 0.00 ) {
1137
		$amount         = (float) $amount;
1138
		$this->subtotal -= $amount;
1139
1140
		if ( $this->subtotal < 0 ) {
1141
			$this->subtotal = 0;
1142
		}
1143
1144
		$this->recalculate_total();
1145
	}
1146
1147
	/**
1148
	 * Set or update the total for a payment.
1149
	 *
1150
	 * @since  1.5
1151
	 * @access private
1152
	 *
1153
	 * @return void
1154
	 */
1155
	private function recalculate_total() {
1156
		$this->total = $this->subtotal;
1157
	}
1158
1159
	/**
1160
	 * Set the payment status and run any status specific changes necessary.
1161
	 *
1162
	 * @since  1.5
1163
	 * @access public
1164
	 *
1165
	 * @param  string|bool $status The status to set the payment to.
1166
	 *
1167
	 * @return bool   $updated Returns if the status was successfully updated.
1168
	 */
1169
	public function update_status( $status = false ) {
1170
1171
		// standardize the 'complete(d)' status.
1172
		if ( $status == 'completed' || $status == 'complete' ) {
1173
			$status = 'publish';
1174
		}
1175
1176
		$old_status = ! empty( $this->old_status ) ? $this->old_status : false;
1177
1178
		if ( $old_status === $status ) {
1179
			return false; // Don't permit status changes that aren't changes.
1180
		}
1181
1182
		$do_change = apply_filters( 'give_should_update_payment_status', true, $this->ID, $status, $old_status );
1183
1184
		$updated = false;
1185
1186
		if ( $do_change ) {
1187
1188
			/**
1189
			 * Fires before changing payment status.
1190
			 *
1191
			 * @since 1.5
1192
			 *
1193
			 * @param int $payment_id Payments ID.
1194
			 * @param string $status The new status.
1195
			 * @param string $old_status The old status.
1196
			 */
1197
			do_action( 'give_before_payment_status_change', $this->ID, $status, $old_status );
1198
1199
			$update_fields = array(
1200
				'ID'          => $this->ID,
1201
				'post_status' => $status,
1202
				'edit_date'   => current_time( 'mysql' ),
1203
			);
1204
1205
			$updated = wp_update_post( apply_filters( 'give_update_payment_status_fields', $update_fields ) );
1206
1207
			$all_payment_statuses  = give_get_payment_statuses();
1208
			$this->status_nicename = array_key_exists( $status, $all_payment_statuses ) ? $all_payment_statuses[ $status ] : ucfirst( $status );
1209
1210
			// Process any specific status functions.
1211
			switch ( $status ) {
1212
				case 'refunded':
1213
					$this->process_refund();
1214
					break;
1215
				case 'failed':
1216
					$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...
1217
					break;
1218
				case 'pending':
1219
					$this->process_pending();
1220
					break;
1221
				case 'cancelled':
1222
					$this->process_cancelled();
1223
					break;
1224
				case 'revoked':
1225
					$this->process_revoked();
1226
					break;
1227
			}
1228
1229
			/**
1230
			 * Fires after changing payment status.
1231
			 *
1232
			 * @since 1.5
1233
			 *
1234
			 * @param int $payment_id Payment ID.
1235
			 * @param string $status The new status.
1236
			 * @param string $old_status The old status.
1237
			 */
1238
			do_action( 'give_update_payment_status', $this->ID, $status, $old_status );
1239
1240
		}// 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...
1241
1242
		return $updated;
1243
1244
	}
1245
1246
	/**
1247
	 * Change the status of the payment to refunded, and run the necessary changes
1248
	 *
1249
	 * @since  1.5
1250
	 * @access public
1251
	 *
1252
	 * @return void
1253
	 */
1254
	public function refund() {
1255
		$this->old_status        = $this->status;
1256
		$this->status            = 'refunded';
1257
		$this->pending['status'] = $this->status;
1258
1259
		$this->save();
1260
	}
1261
1262
	/**
1263
	 * Get a post meta item for the payment
1264
	 *
1265
	 * @since  1.5
1266
	 * @access public
1267
	 *
1268
	 * @param  string  $meta_key The Meta Key
1269
	 * @param  boolean $single Return single item or array
1270
	 *
1271
	 * @return mixed             The value from the post meta
1272
	 */
1273
	public function get_meta( $meta_key = '_give_payment_meta', $single = true ) {
1274
1275
		$meta = give_get_meta( $this->ID, $meta_key, $single );
1276
1277
		/**
1278
		 * Filter the specific meta key value.
1279
		 *
1280
		 * @since 1.5
1281
		 */
1282
		$meta = apply_filters( "give_get_payment_meta_{$meta_key}", $meta, $this->ID );
1283
1284
1285
		/**
1286
		 * Filter the all meta keys.
1287
		 *
1288
		 * @since 1.5
1289
		 */
1290
		return apply_filters( 'give_get_payment_meta', $meta, $this->ID, $meta_key );
1291
	}
1292
1293
	/**
1294
	 * Update the post meta
1295
	 *
1296
	 * @since  1.5
1297
	 * @access public
1298
	 *
1299
	 * @param  string $meta_key The meta key to update
1300
	 * @param  string $meta_value The meta value
1301
	 * @param  string $prev_value Previous meta value
1302
	 *
1303
	 * @return int|bool           Meta ID if the key didn't exist, true on successful update, false on failure
1304
	 */
1305
	public function update_meta( $meta_key = '', $meta_value = '', $prev_value = '' ) {
1306
		if ( empty( $meta_key ) ) {
1307
			return false;
1308
		}
1309
1310
1311
		/**
1312
		 * Filter the single meta key while updating
1313
		 *
1314
		 * @since 1.5
1315
		 */
1316
		$meta_value = apply_filters( "give_update_payment_meta_{$meta_key}", $meta_value, $this->ID );
1317
1318
		return give_update_meta( $this->ID, $meta_key, $meta_value, $prev_value );
1319
	}
1320
1321
	/**
1322
	 * When a payment is set to a status of 'refunded' process the necessary actions to reduce stats
1323
	 *
1324
	 * @since  1.5
1325
	 * @access private
1326
	 *
1327
	 * @return void
1328
	 */
1329
	private function process_refund() {
1330
		$process_refund = true;
1331
1332
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1333
		if ( 'publish' != $this->old_status || 'refunded' != $this->status ) {
1334
			$process_refund = false;
1335
		}
1336
1337
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1338
		$process_refund = apply_filters( 'give_should_process_refund', $process_refund, $this );
1339
1340
		if ( false === $process_refund ) {
1341
			return;
1342
		}
1343
1344
		/**
1345
		 * Fires before refunding payment.
1346
		 *
1347
		 * @since 1.5
1348
		 *
1349
		 * @param Give_Payment $this Payment object.
1350
		 */
1351
		do_action( 'give_pre_refund_payment', $this );
1352
1353
		$decrease_earnings       = apply_filters( 'give_decrease_store_earnings_on_refund', true, $this );
1354
		$decrease_customer_value = apply_filters( 'give_decrease_customer_value_on_refund', true, $this );
1355
		$decrease_purchase_count = apply_filters( 'give_decrease_customer_purchase_count_on_refund', true, $this );
1356
1357
		$this->maybe_alter_stats( $decrease_earnings, $decrease_customer_value, $decrease_purchase_count );
1358
		$this->delete_sales_logs();
1359
1360
		// @todo: Refresh only range related stat cache
1361
		give_delete_donation_stats();
1362
1363
		/**
1364
		 * Fires after refunding payment.
1365
		 *
1366
		 * @since 1.5
1367
		 *
1368
		 * @param Give_Payment $this Payment object.
1369
		 */
1370
		do_action( 'give_post_refund_payment', $this );
1371
	}
1372
1373
	/**
1374
	 * Process when a payment is set to failed
1375
	 *
1376
	 * @since  1.5
1377
	 * @access private
1378
	 *
1379
	 * @return void
1380
	 */
1381
	private function process_failure() {
1382
1383
	}
1384
1385
	/**
1386
	 * Process when a payment moves to pending
1387
	 *
1388
	 * @since  1.5
1389
	 * @access private
1390
	 *
1391
	 * @return void
1392
	 */
1393
	private function process_pending() {
1394
		$process_pending = true;
1395
1396
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1397
		if ( 'publish' != $this->old_status || 'pending' != $this->status ) {
1398
			$process_pending = false;
1399
		}
1400
1401
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1402
		$process_pending = apply_filters( 'give_should_process_pending', $process_pending, $this );
1403
1404
		if ( false === $process_pending ) {
1405
			return;
1406
		}
1407
1408
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_pending', true, $this );
1409
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_pending', true, $this );
1410
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_pending', true, $this );
1411
1412
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1413
		$this->delete_sales_logs();
1414
1415
		$this->completed_date = false;
1416
		$this->update_meta( '_give_completed_date', '' );
1417
1418
		// @todo: Refresh only range related stat cache
1419
		give_delete_donation_stats();
1420
	}
1421
1422
	/**
1423
	 * Process when a payment moves to cancelled.
1424
	 *
1425
	 * @since  1.5
1426
	 * @access private
1427
	 *
1428
	 * @return void
1429
	 */
1430
	private function process_cancelled() {
1431
		$process_cancelled = true;
1432
1433
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1434
		if ( 'publish' != $this->old_status || 'cancelled' != $this->status ) {
1435
			$process_cancelled = false;
1436
		}
1437
1438
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1439
		$process_cancelled = apply_filters( 'give_should_process_cancelled', $process_cancelled, $this );
1440
1441
		if ( false === $process_cancelled ) {
1442
			return;
1443
		}
1444
1445
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_cancelled', true, $this );
1446
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_cancelled', true, $this );
1447
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_cancelled', true, $this );
1448
1449
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1450
		$this->delete_sales_logs();
1451
1452
		$this->completed_date = false;
1453
		$this->update_meta( '_give_completed_date', '' );
1454
1455
		// @todo: Refresh only range related stat cache
1456
		give_delete_donation_stats();
1457
	}
1458
1459
	/**
1460
	 * Process when a payment moves to revoked.
1461
	 *
1462
	 * @since  1.5
1463
	 * @return void
1464
	 */
1465
	private function process_revoked() {
1466
		$process_revoked = true;
1467
1468
		// If the payment was not in publish, don't decrement stats as they were never incremented.
1469
		if ( 'publish' != $this->old_status || 'revoked' != $this->status ) {
1470
			$process_revoked = false;
1471
		}
1472
1473
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1474
		$process_revoked = apply_filters( 'give_should_process_revoked', $process_revoked, $this );
1475
1476
		if ( false === $process_revoked ) {
1477
			return;
1478
		}
1479
1480
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_revoked', true, $this );
1481
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_revoked', true, $this );
1482
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_revoked', true, $this );
1483
1484
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1485
		$this->delete_sales_logs();
1486
1487
		$this->completed_date = false;
1488
		$this->update_meta( '_give_completed_date', '' );
1489
1490
		// @todo: Refresh only range related stat cache
1491
		give_delete_donation_stats();
1492
	}
1493
1494
	/**
1495
	 * Used during the process of moving to refunded or pending, to decrement stats
1496
	 *
1497
	 * @since  1.5
1498
	 * @access private
1499
	 *
1500
	 * @param  bool $alter_store_earnings If the method should alter the store earnings
1501
	 * @param  bool $alter_customer_value If the method should reduce the donor value
1502
	 * @param  bool $alter_customer_purchase_count If the method should reduce the donor's purchase count
1503
	 *
1504
	 * @return void
1505
	 */
1506
	private function maybe_alter_stats( $alter_store_earnings, $alter_customer_value, $alter_customer_purchase_count ) {
1507
1508
		give_undo_donation( $this->ID );
1509
1510
		// Decrease store earnings.
1511
		if ( true === $alter_store_earnings ) {
1512
			give_decrease_total_earnings( $this->total );
1513
		}
1514
1515
		// Decrement the stats for the donor.
1516
		if ( ! empty( $this->customer_id ) ) {
1517
1518
			$donor = new Give_Donor( $this->customer_id );
1519
1520
			if ( true === $alter_customer_value ) {
1521
				$donor->decrease_value( $this->total );
1522
			}
1523
1524
			if ( true === $alter_customer_purchase_count ) {
1525
				$donor->decrease_donation_count();
1526
			}
1527
		}
1528
1529
	}
1530
1531
	/**
1532
	 * Delete sales logs for this donation
1533
	 *
1534
	 * @since  1.5
1535
	 * @access private
1536
	 *
1537
	 * @return void
1538
	 */
1539
	private function delete_sales_logs() {
1540
		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...
1541
1542
		// Remove related sale log entries.
1543
		$give_logs->delete_logs(
1544
			null,
1545
			'sale',
1546
			array(
1547
				array(
1548
					'key'   => '_give_log_payment_id',
1549
					'value' => $this->ID,
1550
				),
1551
			)
1552
		);
1553
	}
1554
1555
	/**
1556
	 * Setup functions only, these are not to be used by developers.
1557
	 * These functions exist only to allow the setup routine to be backwards compatible with our old
1558
	 * helper functions.
1559
	 *
1560
	 * These will run whenever setup_payment is called, which should only be called once.
1561
	 * To update an attribute, update it directly instead of re-running the setup routine
1562
	 */
1563
1564
	/**
1565
	 * Setup the payment completed date
1566
	 *
1567
	 * @since  1.5
1568
	 * @access private
1569
	 *
1570
	 * @return string The date the payment was completed
1571
	 */
1572
	private function setup_completed_date() {
1573
		$payment = get_post( $this->ID );
1574
1575
		if ( 'pending' == $payment->post_status || 'preapproved' == $payment->post_status ) {
1576
			return false; // This payment was never completed.
1577
		}
1578
1579
		$date = ( $date = $this->get_meta( '_give_completed_date', true ) ) ? $date : $payment->modified_date;
1580
1581
		return $date;
1582
	}
1583
1584
	/**
1585
	 * Setup the payment mode
1586
	 *
1587
	 * @since  1.5
1588
	 * @access private
1589
	 *
1590
	 * @return string The payment mode
1591
	 */
1592
	private function setup_mode() {
1593
		return $this->get_meta( '_give_payment_mode' );
1594
	}
1595
1596
	/**
1597
	 * Setup the payment total
1598
	 *
1599
	 * @since  1.5
1600
	 * @access private
1601
	 *
1602
	 * @return float The payment total
1603
	 */
1604
	private function setup_total() {
1605
		$amount = $this->get_meta( '_give_payment_total', true );
1606
1607
		if ( empty( $amount ) && '0.00' != $amount ) {
1608
			$meta = $this->get_meta( '_give_payment_meta', true );
1609
			$meta = maybe_unserialize( $meta );
1610
1611
			if ( isset( $meta['amount'] ) ) {
1612
				$amount = $meta['amount'];
1613
			}
1614
		}
1615
1616
		return round( floatval( $amount ), give_currency_decimal_filter() );
1617
	}
1618
1619
	/**
1620
	 * Setup the payment subtotal
1621
	 *
1622
	 * @since  1.5
1623
	 * @access private
1624
	 *
1625
	 * @return float The subtotal of the payment
1626
	 */
1627
	private function setup_subtotal() {
1628
		$subtotal = $this->total;
1629
1630
		return $subtotal;
1631
	}
1632
1633
	/**
1634
	 * Setup the currency code
1635
	 *
1636
	 * @since  1.5
1637
	 * @since  2.0 Set currency from _give_payment_currency meta key
1638
	 * @access private
1639
	 *
1640
	 * @return string The currency for the payment
1641
	 */
1642
	private function setup_currency() {
1643
		$currency = $this->get_meta( '_give_payment_currency', true );
1644
		$currency = ! empty( $currency ) ?
1645
			$currency :
1646
			apply_filters( 'give_payment_currency_default', give_get_currency(), $this );
1647
1648
		return $currency;
1649
	}
1650
1651
	/**
1652
	 * Setup the gateway used for the payment
1653
	 *
1654
	 * @since  1.5
1655
	 * @access private
1656
	 *
1657
	 * @return string The gateway
1658
	 */
1659
	private function setup_gateway() {
1660
		$gateway = $this->get_meta( '_give_payment_gateway', true );
1661
1662
		return $gateway;
1663
	}
1664
1665
	/**
1666
	 * Setup the donation ID
1667
	 *
1668
	 * @since  1.5
1669
	 * @access private
1670
	 *
1671
	 * @return string The donation ID
1672
	 */
1673
	private function setup_transaction_id() {
1674
		$transaction_id = $this->get_meta( '_give_payment_transaction_id', true );
1675
1676
		if ( empty( $transaction_id ) ) {
1677
			$gateway        = $this->gateway;
1678
			$transaction_id = apply_filters( "give_get_payment_transaction_id-{$gateway}", $this->ID );
1679
		}
1680
1681
		return $transaction_id;
1682
	}
1683
1684
	/**
1685
	 * Setup the IP Address for the payment
1686
	 *
1687
	 * @since  1.5
1688
	 * @since  2.0 Set ip address from _give_payment_donor_ip meta key
1689
	 * @access private
1690
	 *
1691
	 * @return string The IP address for the payment
1692
	 */
1693
	private function setup_ip() {
1694
		$ip = $this->get_meta( '_give_payment_donor_ip', true );
1695
1696
		return $ip;
1697
	}
1698
1699
	/**
1700
	 * Setup the donor ID.
1701
	 *
1702
	 * @since  1.5
1703
	 * @since  2.0 Set id from _give_payment_donor_id meta key
1704
	 * @access private
1705
	 *
1706
	 * @return int The Donor ID.
1707
	 */
1708
	private function setup_donor_id() {
1709
		$donor_id = $this->get_meta( '_give_payment_donor_id', true );
1710
1711
		return $donor_id;
1712
	}
1713
1714
	/**
1715
	 * Setup the User ID associated with the donation
1716
	 *
1717
	 * @since  1.5
1718
	 * @since  2.0 Get user id connect to donor from donor table instead of payment meta.
1719
	 *
1720
	 * @access private
1721
	 *
1722
	 * @return int The User ID
1723
	 */
1724
	private function setup_user_id() {
1725
		$cache_args = array( 'id' => $this->ID, 'key' => 'user_id' );
1726
		if ( ! ( $user_id = Give_Cache::group( 'donation', $cache_args ) ) ) {
1727
			$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...
1728
			$user_id = $donor ? absint( $donor->user_id ) : 0;
1729
1730
			$cache_args['data'] = $user_id;
1731
			Give_Cache::group( 'donation', $cache_args );
1732
		}
1733
1734
		return $user_id;
1735
	}
1736
1737
	/**
1738
	 * Setup the email address for the donation.
1739
	 *
1740
	 * @since  1.5
1741
	 * @since  2.0 Set email from _give_payment_donor_email meta key
1742
	 *
1743
	 * @access private
1744
	 *
1745
	 * @return string The email address for the payment.
1746
	 */
1747
	private function setup_email() {
1748
		$email = $this->get_meta( '_give_payment_donor_email', true );
1749
1750
		if ( empty( $email ) ) {
1751
			$email = Give()->donors->get_column( 'email', $this->customer_id );
1752
		}
1753
1754
		return $email;
1755
	}
1756
1757
	/**
1758
	 * Setup the user info.
1759
	 *
1760
	 * @since  1.5
1761
	 * @access private
1762
	 *
1763
	 * @return array The user info associated with the payment.
1764
	 */
1765
	private function setup_user_info() {
1766
		$defaults = array(
1767
			'first_name' => $this->first_name,
1768
			'last_name'  => $this->last_name,
1769
		);
1770
1771
		$user_info = isset( $this->payment_meta['user_info'] ) ? maybe_unserialize( $this->payment_meta['user_info'] ) : array();
1772
		$user_info = wp_parse_args( $user_info, $defaults );
1773
1774
		if ( empty( $user_info ) ) {
1775
			// Get the donor, but only if it's been created.
1776
			$donor = new Give_Donor( $this->customer_id );
1777
1778
			if ( $donor->id > 0 ) {
1779
				$name      = explode( ' ', $donor->name, 2 );
1780
				$user_info = array(
1781
					'first_name' => $name[0],
1782
					'last_name'  => $name[1],
1783
					'email'      => $donor->email,
1784
					'discount'   => 'none',
1785
				);
1786
			}
1787
		} else {
1788
			// Get the donor, but only if it's been created.
1789
			$donor = new Give_Donor( $this->customer_id );
1790
			if ( $donor->id > 0 ) {
1791
				foreach ( $user_info as $key => $value ) {
1792
					if ( ! empty( $value ) ) {
1793
						continue;
1794
					}
1795
1796
					switch ( $key ) {
1797
						case 'first_name':
1798
							$name = explode( ' ', $donor->name, 2 );
1799
1800
							$user_info[ $key ] = $name[0];
1801
							break;
1802
1803
						case 'last_name':
1804
							$name      = explode( ' ', $donor->name, 2 );
1805
							$last_name = ! empty( $name[1] ) ? $name[1] : '';
1806
1807
							$user_info[ $key ] = $last_name;
1808
							break;
1809
1810
						case 'email':
1811
							$user_info[ $key ] = $donor->email;
1812
							break;
1813
					}
1814
				}
1815
			}
1816
		}// 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...
1817
1818
		return $user_info;
1819
1820
	}
1821
1822
	/**
1823
	 * Setup the Address for the payment.
1824
	 *
1825
	 * @since  1.5
1826
	 * @access private
1827
	 *
1828
	 * @return array The Address information for the payment.
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|array|WP_Error?

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