Test Failed
Push — backup/issues/1132 ( b1d18b )
by Ravinder
05:29
created

Give_Payment::update_meta()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 3
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
1
<?php
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 );
0 ignored issues
show
Bug introduced by
It seems like $payment_id defined by parameter $payment_id on line 376 can also be of type boolean; however, Give_Payment::setup_payment() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
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' ) {
0 ignored issues
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
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
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();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->get_meta() of type * is incompatible with the declared type array of property $payment_meta.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
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();
0 ignored issues
show
Documentation Bug introduced by
The property $form_id was declared of type string, but $this->setup_form_id() is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
537
		$this->price_id   = $this->setup_price_id();
538
		$this->key        = $this->setup_payment_key();
539
		$this->number     = $this->setup_payment_number();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->setup_payment_number() can also be of type integer. However, the property $number is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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
		// @todo: payment data exist here only for backward compatibility
610
		// issue: https://github.com/WordImpress/Give/issues/1132
611
		$payment_data = array(
612
			'price'        => $this->total,
613
			'date'         => $this->date,
614
			'user_email'   => $this->email,
615
			'purchase_key' => $this->key,
616
			'form_title'   => $this->form_title,
617
			'form_id'      => $this->form_id,
618
			'price_id'     => $this->price_id,
619
			'currency'     => $this->currency,
620
			'user_info'    => array(
621
				'id'         => $this->user_id,
622
				'email'      => $this->email,
623
				'first_name' => $this->first_name,
624
				'last_name'  => $this->last_name,
625
				'address'    => $this->address,
626
			),
627
			'status'       => $this->status,
628
		);
629
630
		$args = apply_filters( 'give_insert_payment_args', array(
631
			'post_title'    => $payment_title,
632
			'post_status'   => $this->status,
633
			'post_type'     => 'give_payment',
634
			'post_date'     => ! empty( $this->date ) ? $this->date : null,
635
			'post_date_gmt' => ! empty( $this->date ) ? get_gmt_from_date( $this->date ) : null,
636
			'post_parent'   => $this->parent_payment,
637
		), $payment_data );
638
639
		// Create a blank payment
640
		$payment_id = wp_insert_post( $args );
641
642
		if ( ! empty( $payment_id ) ) {
643
644
			$this->ID  = $payment_id;
645
			$this->_ID = $payment_id;
646
647
			$donor = new stdClass;
648
649
			if ( did_action( 'give_pre_process_donation' ) && is_user_logged_in() ) {
650
				$donor = new Give_Donor( get_current_user_id(), true );
651
652
				// Donor is logged in but used a different email to purchase with so assign to their donor record.
653
				if ( ! empty( $donor->id ) && $this->email != $donor->email ) {
654
					$donor->add_email( $this->email );
655
				}
656
			}
657
658
			if ( empty( $donor->id ) ) {
659
				$donor = new Give_Donor( $this->email );
0 ignored issues
show
Documentation introduced by
$this->email is of type string, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
660
			}
661
662
			if ( empty( $donor->id ) ) {
663
664
				$donor_data = array(
665
					'name'    => ! is_email( $payment_title ) ? $this->first_name . ' ' . $this->last_name : '',
666
					'email'   => $this->email,
667
					'user_id' => $this->user_id,
668
				);
669
670
				$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...
671
672
			}
673
674
			$this->customer_id            = $donor->id;
675
			$this->pending['customer_id'] = $this->customer_id;
676
			$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...
677
678
			$this->payment_meta = apply_filters( 'give_payment_meta', $this->payment_meta, $payment_data );
679
680
			$this->new = true;
681
		}// End if().
682
683
		return $this->ID;
684
685
	}
686
687
	/**
688
	 * Save
689
	 *
690
	 * Once items have been set, an update is needed to save them to the database.
691
	 *
692
	 * @access public
693
	 *
694
	 * @return bool  True of the save occurred, false if it failed or wasn't needed
695
	 */
696
	public function save() {
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;
0 ignored issues
show
Documentation Bug introduced by
It seems like $payment_id can also be of type boolean. However, the property $ID is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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
									$this->delete_sales_logs();
761
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
762
										$form = new Give_Donate_Form( $item['id'] );
763
										$form->decrease_sales( $quantity );
764
										$form->decrease_earnings( $item['amount'] );
765
766
										$total_decrease += $item['amount'];
767
									}
768
									break;
769
770
							}// End switch().
771
						}// End foreach().
772
						break;
773
774
					case 'status':
775
						$this->update_status( $this->status );
776
						break;
777
778
					case 'gateway':
779
						$this->update_meta( '_give_payment_gateway', $this->gateway );
780
						break;
781
782
					case 'mode':
783
						$this->update_meta( '_give_payment_mode', $this->mode );
784
						break;
785
786
					case 'transaction_id':
787
						$this->update_meta( '_give_payment_transaction_id', $this->transaction_id );
788
						break;
789
790
					case 'ip':
791
						$this->update_meta( '_give_payment_donor_ip', $this->ip );
792
						break;
793
794
					case 'customer_id':
795
						$this->update_meta( '_give_payment_donor_id', $this->customer_id );
796
						break;
797
798
					// case 'user_id':
799
					// 	$this->update_meta( '_give_payment_user_id', $this->user_id );
800
					// 	break;
801
802
					case 'form_title':
803
						$this->update_meta( '_give_payment_form_title', $this->form_title );
804
						break;
805
806
					case 'form_id':
807
						$this->update_meta( '_give_payment_form_id', $this->form_id );
808
						break;
809
810
					case 'price_id':
811
						$this->update_meta( '_give_payment_price_id', $this->price_id );
812
						break;
813
814
					case 'first_name':
815
						$this->update_meta( '_give_donor_billing_first_name', $this->first_name );
816
						break;
817
818
					case 'last_name':
819
						$this->update_meta( '_give_donor_billing_last_name', $this->last_name );
820
						break;
821
822
					case 'currency':
823
						$this->update_meta( '_give_payment_currency', $this->currency );
824
						break;
825
826
					case 'address':
827
						if( ! empty( $this->address ) ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
828
							foreach ( $this->address as $address_name => $address ) {
829
								switch ( $address_name ) {
830
									case 'line1':
831
										$this->update_meta( '_give_donor_billing_address1', $address );
832
										break;
833
834
									case 'line2':
835
										$this->update_meta( '_give_donor_billing_address2', $address );
836
										break;
837
838
									default:
839
										$this->update_meta( "_give_donor_billing_{$address_name}", $address );
840
								}
841
							}
842
						}
843
						break;
844
845
					case 'email':
846
						$this->update_meta( '_give_payment_donor_email', $this->email );
847
						break;
848
849
					case 'key':
850
						$this->update_meta( '_give_payment_purchase_key', $this->key );
851
						break;
852
853
					case 'number':
854
						$this->update_meta( '_give_payment_number', $this->number );
855
						break;
856
857
					case 'date':
858
						$args = array(
859
							'ID'        => $this->ID,
860
							'post_date' => $this->date,
861
							'edit_date' => true,
862
						);
863
864
						wp_update_post( $args );
865
						break;
866
867
					case 'completed_date':
868
						$this->update_meta( '_give_completed_date', $this->completed_date );
869
						break;
870
871
					case 'parent_payment':
872
						$args = array(
873
							'ID'          => $this->ID,
874
							'post_parent' => $this->parent_payment,
875
						);
876
877
						wp_update_post( $args );
878
						break;
879
880
					default:
881
						/**
882
						 * Fires while saving payment.
883
						 *
884
						 * @since 1.7
885
						 *
886
						 * @param Give_Payment $this Payment object.
887
						 */
888
						do_action( 'give_payment_save', $this, $key );
889
						break;
890
				}// End switch().
891
			}// End foreach().
892
893
			if ( 'pending' !== $this->status ) {
894
895
				$donor = new Give_Donor( $this->customer_id );
0 ignored issues
show
Documentation introduced by
$this->customer_id is of type integer, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
896
897
				$total_change = $total_increase - $total_decrease;
898
				if ( $total_change < 0 ) {
899
900
					$total_change = - ( $total_change );
901
					// Decrease the donor's donation stats.
902
					$donor->decrease_value( $total_change );
903
					give_decrease_total_earnings( $total_change );
904
905
				} elseif ( $total_change > 0 ) {
906
907
					// Increase the donor's donation stats.
908
					$donor->increase_value( $total_change );
909
					give_increase_total_earnings( $total_change );
910
911
				}
912
			}
913
914
			$this->update_meta( '_give_payment_total', give_sanitize_amount_for_db( $this->total ) );
915
916
			$this->pending = array();
917
			$saved         = true;
918
		}// End if().
919
920
		if ( true === $saved ) {
921
			$this->setup_payment( $this->ID );
922
		}
923
924
		return $saved;
925
	}
926
927
	/**
928
	 * Add a donation to a given payment
929
	 *
930
	 * @since  1.5
931
	 * @access public
932
	 *
933
	 * @param  int   $form_id The donation form to add
934
	 * @param  array $args Other arguments to pass to the function
935
	 * @param  array $options List of donation options
936
	 *
937
	 * @return bool           True when successful, false otherwise
938
	 */
939
	public function add_donation( $form_id = 0, $args = array(), $options = array() ) {
940
941
		$donation = new Give_Donate_Form( $form_id );
0 ignored issues
show
Documentation introduced by
$form_id is of type integer, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
942
943
		// Bail if this post isn't a give donation form.
944
		if ( ! $donation || $donation->post_type !== 'give_forms' ) {
0 ignored issues
show
introduced by
Found "!== '". Use Yoda Condition checks, you must
Loading history...
945
			return false;
946
		}
947
948
		// Set some defaults.
949
		$defaults = array(
950
			'price'    => false,
951
			'price_id' => false,
952
		);
953
954
		$args = wp_parse_args( apply_filters( 'give_payment_add_donation_args', $args, $donation->ID ), $defaults );
955
956
		// Allow overriding the price.
957
		if ( false !== $args['price'] ) {
958
			$item_price = $args['price'];
959
		} else {
960
961
			// Deal with variable pricing.
962
			if ( give_has_variable_prices( $donation->ID ) ) {
963
				$prices     = maybe_unserialize( give_get_meta( $form_id, '_give_donation_levels', true ) );
964
				$item_price = '';
965
				// Loop through prices.
966 View Code Duplication
				foreach ( $prices as $price ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
967
					// Find a match between price_id and level_id.
968
					// First verify array keys exists THEN make the match.
969
					if ( ( isset( $args['price_id'] ) && isset( $price['_give_id']['level_id'] ) )
970
					     && $args['price_id'] == $price['_give_id']['level_id']
971
					) {
972
						$item_price = $price['_give_amount'];
973
					}
974
				}
975
				// Fallback to the lowest price point.
976
				if ( $item_price == '' ) {
977
					$item_price       = give_get_lowest_price_option( $donation->ID );
978
					$args['price_id'] = give_get_lowest_price_id( $donation->ID );
979
				}
980
			} else {
981
				// Simple form price.
982
				$item_price = give_get_form_price( $donation->ID );
983
			}
984
		}
985
986
		// Sanitizing the price here so we don't have a dozen calls later.
987
		$item_price = give_maybe_sanitize_amount( $item_price );
988
		$total      = round( $item_price, give_currency_decimal_filter() );
989
990
		// Add Options.
991
		$default_options = array();
992
		if ( false !== $args['price_id'] ) {
993
			$default_options['price_id'] = (int) $args['price_id'];
994
		}
995
		$options = wp_parse_args( $options, $default_options );
996
997
		// Do not allow totals to go negative.
998
		if ( $total < 0 ) {
999
			$total = 0;
1000
		}
1001
1002
		$donation = array(
1003
			'name'     => $donation->post_title,
1004
			'id'       => $donation->ID,
1005
			'price'    => round( $total, give_currency_decimal_filter() ),
1006
			'subtotal' => round( $total, give_currency_decimal_filter() ),
1007
			'price_id' => $args['price_id'],
1008
			'action'   => 'add',
1009
			'options'  => $options,
1010
		);
1011
1012
		$this->pending['donations'][] = $donation;
1013
1014
		$this->increase_subtotal( $total );
1015
1016
		return true;
1017
1018
	}
1019
1020
	/**
1021
	 * Remove a donation from the payment
1022
	 *
1023
	 * @since  1.5
1024
	 * @access public
1025
	 *
1026
	 * @param  int   $form_id The form ID to remove
1027
	 * @param  array $args Arguments to pass to identify (quantity, amount, price_id)
1028
	 *
1029
	 * @return bool           If the item was removed or not
1030
	 */
1031
	public function remove_donation( $form_id, $args = array() ) {
1032
1033
		// Set some defaults.
1034
		$defaults = array(
1035
			'quantity' => 1,
1036
			'price'    => false,
1037
			'price_id' => false,
1038
		);
1039
		$args     = wp_parse_args( $args, $defaults );
1040
1041
		$form = new Give_Donate_Form( $form_id );
0 ignored issues
show
Documentation introduced by
$form_id is of type integer, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1042
1043
		// Bail if this post isn't a valid give donation form.
1044
		if ( ! $form || $form->post_type !== 'give_forms' ) {
0 ignored issues
show
introduced by
Found "!== '". Use Yoda Condition checks, you must
Loading history...
1045
			return false;
1046
		}
1047
1048
		$pending_args             = $args;
1049
		$pending_args['id']       = $form_id;
1050
		$pending_args['amount']   = $this->total;
1051
		$pending_args['price_id'] = false !== $args['price_id'] ? (int) $args['price_id'] : false;
1052
		$pending_args['quantity'] = $args['quantity'];
1053
		$pending_args['action']   = 'remove';
1054
1055
		$this->pending['donations'][] = $pending_args;
1056
1057
		$this->decrease_subtotal( $this->total );
1058
1059
		return true;
1060
	}
1061
1062
1063
	/**
1064
	 * Add a note to a payment
1065
	 *
1066
	 * @since  1.5
1067
	 * @access public
1068
	 *
1069
	 * @param  string $note The note to add
1070
	 *
1071
	 * @return void
1072
	 */
1073
	public function add_note( $note = false ) {
1074
		// Bail if no note specified.
1075
		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...
1076
			return false;
1077
		}
1078
1079
		give_insert_payment_note( $this->ID, $note );
1080
	}
1081
1082
	/**
1083
	 * Increase the payment's subtotal
1084
	 *
1085
	 * @since  1.5
1086
	 * @access private
1087
	 *
1088
	 * @param  float $amount The amount to increase the payment subtotal by.
1089
	 *
1090
	 * @return void
1091
	 */
1092
	private function increase_subtotal( $amount = 0.00 ) {
1093
		$amount         = (float) $amount;
1094
		$this->subtotal += $amount;
1095
1096
		$this->recalculate_total();
1097
	}
1098
1099
	/**
1100
	 * Decrease the payment's subtotal.
1101
	 *
1102
	 * @since  1.5
1103
	 * @access private
1104
	 *
1105
	 * @param  float $amount The amount to decrease the payment subtotal by.
1106
	 *
1107
	 * @return void
1108
	 */
1109
	private function decrease_subtotal( $amount = 0.00 ) {
1110
		$amount         = (float) $amount;
1111
		$this->subtotal -= $amount;
1112
1113
		if ( $this->subtotal < 0 ) {
1114
			$this->subtotal = 0;
0 ignored issues
show
Documentation Bug introduced by
The property $subtotal was declared of type double, but 0 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1115
		}
1116
1117
		$this->recalculate_total();
1118
	}
1119
1120
	/**
1121
	 * Set or update the total for a payment.
1122
	 *
1123
	 * @since  1.5
1124
	 * @access private
1125
	 *
1126
	 * @return void
1127
	 */
1128
	private function recalculate_total() {
1129
		$this->total = $this->subtotal;
1130
	}
1131
1132
	/**
1133
	 * Set the payment status and run any status specific changes necessary.
1134
	 *
1135
	 * @since  1.5
1136
	 * @access public
1137
	 *
1138
	 * @param  string|bool $status The status to set the payment to.
1139
	 *
1140
	 * @return bool   $updated Returns if the status was successfully updated.
1141
	 */
1142
	public function update_status( $status = false ) {
1143
1144
		// standardize the 'complete(d)' status.
1145
		if ( $status == 'completed' || $status == 'complete' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
1146
			$status = 'publish';
1147
		}
1148
1149
		$old_status = ! empty( $this->old_status ) ? $this->old_status : false;
1150
1151
		if ( $old_status === $status ) {
1152
			return false; // Don't permit status changes that aren't changes.
1153
		}
1154
1155
		$do_change = apply_filters( 'give_should_update_payment_status', true, $this->ID, $status, $old_status );
1156
1157
		$updated = false;
1158
1159
		if ( $do_change ) {
1160
1161
			/**
1162
			 * Fires before changing payment status.
1163
			 *
1164
			 * @since 1.5
1165
			 *
1166
			 * @param int $payment_id Payments ID.
1167
			 * @param string $status The new status.
1168
			 * @param string $old_status The old status.
1169
			 */
1170
			do_action( 'give_before_payment_status_change', $this->ID, $status, $old_status );
1171
1172
			$update_fields = array(
1173
				'ID'          => $this->ID,
1174
				'post_status' => $status,
1175
				'edit_date'   => current_time( 'mysql' ),
1176
			);
1177
1178
			$updated = wp_update_post( apply_filters( 'give_update_payment_status_fields', $update_fields ) );
1179
1180
			$all_payment_statuses  = give_get_payment_statuses();
1181
			$this->status_nicename = array_key_exists( $status, $all_payment_statuses ) ? $all_payment_statuses[ $status ] : ucfirst( $status );
1182
1183
			// Process any specific status functions.
1184
			switch ( $status ) {
1185
				case 'refunded':
1186
					$this->process_refund();
1187
					break;
1188
				case 'failed':
1189
					$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...
1190
					break;
1191
				case 'pending':
1192
					$this->process_pending();
1193
					break;
1194
				case 'cancelled':
1195
					$this->process_cancelled();
1196
					break;
1197
				case 'revoked':
1198
					$this->process_revoked();
1199
					break;
1200
			}
1201
1202
			/**
1203
			 * Fires after changing payment status.
1204
			 *
1205
			 * @since 1.5
1206
			 *
1207
			 * @param int $payment_id Payment ID.
1208
			 * @param string $status The new status.
1209
			 * @param string $old_status The old status.
1210
			 */
1211
			do_action( 'give_update_payment_status', $this->ID, $status, $old_status );
1212
1213
		}// End if().
1214
1215
		return $updated;
1216
1217
	}
1218
1219
	/**
1220
	 * Change the status of the payment to refunded, and run the necessary changes
1221
	 *
1222
	 * @since  1.5
1223
	 * @access public
1224
	 *
1225
	 * @return void
1226
	 */
1227
	public function refund() {
1228
		$this->old_status        = $this->status;
1229
		$this->status            = 'refunded';
1230
		$this->pending['status'] = $this->status;
1231
1232
		$this->save();
1233
	}
1234
1235
	/**
1236
	 * Get a post meta item for the payment
1237
	 *
1238
	 * @since  1.5
1239
	 * @access public
1240
	 *
1241
	 * @param  string  $meta_key The Meta Key
1242
	 * @param  boolean $single Return single item or array
1243
	 *
1244
	 * @return mixed             The value from the post meta
1245
	 */
1246
	public function get_meta( $meta_key = '_give_payment_meta', $single = true ) {
1247
1248
		$meta = give_get_meta( $this->ID, $meta_key, $single );
1249
1250
		/**
1251
		 * Filter the specific meta key value.
1252
		 *
1253
		 * @since 1.5
1254
		 */
1255
		$meta = apply_filters( "give_get_payment_meta_{$meta_key}", $meta, $this->ID );
1256
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1257
1258
		/**
1259
		 * Filter the all meta keys.
1260
		 *
1261
		 * @since 1.5
1262
		 */
1263
		return apply_filters( 'give_get_payment_meta', $meta, $this->ID, $meta_key );
1264
	}
1265
1266
	/**
1267
	 * Update the post meta
1268
	 *
1269
	 * @since  1.5
1270
	 * @access public
1271
	 *
1272
	 * @param  string $meta_key The meta key to update
1273
	 * @param  string $meta_value The meta value
1274
	 * @param  string $prev_value Previous meta value
1275
	 *
1276
	 * @return int|bool           Meta ID if the key didn't exist, true on successful update, false on failure
1277
	 */
1278
	public function update_meta( $meta_key = '', $meta_value = '', $prev_value = '' ) {
1279
		if ( empty( $meta_key ) ) {
1280
			return false;
1281
		}
1282
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1283
1284
		/**
1285
		 * Filter the single meta key while updating
1286
		 *
1287
		 * @since 1.5
1288
		 */
1289
		$meta_value = apply_filters( "give_update_payment_meta_{$meta_key}", $meta_value, $this->ID );
1290
1291
		return give_update_meta( $this->ID, $meta_key, $meta_value, $prev_value );
1292
	}
1293
1294
	/**
1295
	 * When a payment is set to a status of 'refunded' process the necessary actions to reduce stats
1296
	 *
1297
	 * @since  1.5
1298
	 * @access private
1299
	 *
1300
	 * @return void
1301
	 */
1302 View Code Duplication
	private function process_refund() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1303
		$process_refund = true;
1304
1305
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1306
		if ( 'publish' != $this->old_status || 'refunded' != $this->status ) {
1307
			$process_refund = false;
1308
		}
1309
1310
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1311
		$process_refund = apply_filters( 'give_should_process_refund', $process_refund, $this );
1312
1313
		if ( false === $process_refund ) {
1314
			return;
1315
		}
1316
1317
		/**
1318
		 * Fires before refunding payment.
1319
		 *
1320
		 * @since 1.5
1321
		 *
1322
		 * @param Give_Payment $this Payment object.
1323
		 */
1324
		do_action( 'give_pre_refund_payment', $this );
1325
1326
		$decrease_earnings       = apply_filters( 'give_decrease_store_earnings_on_refund', true, $this );
1327
		$decrease_customer_value = apply_filters( 'give_decrease_customer_value_on_refund', true, $this );
1328
		$decrease_purchase_count = apply_filters( 'give_decrease_customer_purchase_count_on_refund', true, $this );
1329
1330
		$this->maybe_alter_stats( $decrease_earnings, $decrease_customer_value, $decrease_purchase_count );
1331
		$this->delete_sales_logs();
1332
1333
		// @todo: Refresh only range related stat cache
1334
		give_delete_donation_stats();
1335
1336
		/**
1337
		 * Fires after refunding payment.
1338
		 *
1339
		 * @since 1.5
1340
		 *
1341
		 * @param Give_Payment $this Payment object.
1342
		 */
1343
		do_action( 'give_post_refund_payment', $this );
1344
	}
1345
1346
	/**
1347
	 * Process when a payment is set to failed
1348
	 *
1349
	 * @since  1.5
1350
	 * @access private
1351
	 *
1352
	 * @return void
1353
	 */
1354
	private function process_failure() {
1355
1356
	}
1357
1358
	/**
1359
	 * Process when a payment moves to pending
1360
	 *
1361
	 * @since  1.5
1362
	 * @access private
1363
	 *
1364
	 * @return void
1365
	 */
1366 View Code Duplication
	private function process_pending() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1367
		$process_pending = true;
1368
1369
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1370
		if ( 'publish' != $this->old_status || 'pending' != $this->status ) {
1371
			$process_pending = false;
1372
		}
1373
1374
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1375
		$process_pending = apply_filters( 'give_should_process_pending', $process_pending, $this );
1376
1377
		if ( false === $process_pending ) {
1378
			return;
1379
		}
1380
1381
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_pending', true, $this );
1382
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_pending', true, $this );
1383
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_pending', true, $this );
1384
1385
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1386
		$this->delete_sales_logs();
1387
1388
		$this->completed_date = false;
0 ignored issues
show
Documentation Bug introduced by
The property $completed_date was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1389
		$this->update_meta( '_give_completed_date', '' );
1390
1391
		// @todo: Refresh only range related stat cache
1392
		give_delete_donation_stats();
1393
	}
1394
1395
	/**
1396
	 * Process when a payment moves to cancelled.
1397
	 *
1398
	 * @since  1.5
1399
	 * @access private
1400
	 *
1401
	 * @return void
1402
	 */
1403 View Code Duplication
	private function process_cancelled() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1404
		$process_cancelled = true;
1405
1406
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1407
		if ( 'publish' != $this->old_status || 'cancelled' != $this->status ) {
1408
			$process_cancelled = false;
1409
		}
1410
1411
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1412
		$process_cancelled = apply_filters( 'give_should_process_cancelled', $process_cancelled, $this );
1413
1414
		if ( false === $process_cancelled ) {
1415
			return;
1416
		}
1417
1418
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_cancelled', true, $this );
1419
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_cancelled', true, $this );
1420
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_cancelled', true, $this );
1421
1422
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1423
		$this->delete_sales_logs();
1424
1425
		$this->completed_date = false;
0 ignored issues
show
Documentation Bug introduced by
The property $completed_date was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1426
		$this->update_meta( '_give_completed_date', '' );
1427
1428
		// @todo: Refresh only range related stat cache
1429
		give_delete_donation_stats();
1430
	}
1431
1432
	/**
1433
	 * Process when a payment moves to revoked.
1434
	 *
1435
	 * @since  1.5
1436
	 * @return void
1437
	 */
1438 View Code Duplication
	private function process_revoked() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1439
		$process_revoked = true;
1440
1441
		// If the payment was not in publish, don't decrement stats as they were never incremented.
1442
		if ( 'publish' != $this->old_status || 'revoked' != $this->status ) {
1443
			$process_revoked = false;
1444
		}
1445
1446
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1447
		$process_revoked = apply_filters( 'give_should_process_revoked', $process_revoked, $this );
1448
1449
		if ( false === $process_revoked ) {
1450
			return;
1451
		}
1452
1453
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_revoked', true, $this );
1454
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_revoked', true, $this );
1455
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_revoked', true, $this );
1456
1457
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1458
		$this->delete_sales_logs();
1459
1460
		$this->completed_date = false;
0 ignored issues
show
Documentation Bug introduced by
The property $completed_date was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1461
		$this->update_meta( '_give_completed_date', '' );
1462
1463
		// @todo: Refresh only range related stat cache
1464
		give_delete_donation_stats();
1465
	}
1466
1467
	/**
1468
	 * Used during the process of moving to refunded or pending, to decrement stats
1469
	 *
1470
	 * @since  1.5
1471
	 * @access private
1472
	 *
1473
	 * @param  bool $alter_store_earnings If the method should alter the store earnings
1474
	 * @param  bool $alter_customer_value If the method should reduce the donor value
1475
	 * @param  bool $alter_customer_purchase_count If the method should reduce the donor's purchase count
1476
	 *
1477
	 * @return void
1478
	 */
1479
	private function maybe_alter_stats( $alter_store_earnings, $alter_customer_value, $alter_customer_purchase_count ) {
1480
1481
		give_undo_donation( $this->ID );
1482
1483
		// Decrease store earnings.
1484
		if ( true === $alter_store_earnings ) {
1485
			give_decrease_total_earnings( $this->total );
1486
		}
1487
1488
		// Decrement the stats for the donor.
1489
		if ( ! empty( $this->customer_id ) ) {
1490
1491
			$donor = new Give_Donor( $this->customer_id );
0 ignored issues
show
Documentation introduced by
$this->customer_id is of type integer, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1492
1493
			if ( true === $alter_customer_value ) {
1494
				$donor->decrease_value( $this->total );
1495
			}
1496
1497
			if ( true === $alter_customer_purchase_count ) {
1498
				$donor->decrease_donation_count();
1499
			}
1500
		}
1501
1502
	}
1503
1504
	/**
1505
	 * Delete sales logs for this donation
1506
	 *
1507
	 * @since  1.5
1508
	 * @access private
1509
	 *
1510
	 * @return void
1511
	 */
1512
	private function delete_sales_logs() {
1513
		// Remove related sale log entries.
1514
		Give()->logs->delete_logs( $this->ID );
1515
	}
1516
1517
	/**
1518
	 * Setup functions only, these are not to be used by developers.
1519
	 * These functions exist only to allow the setup routine to be backwards compatible with our old
1520
	 * helper functions.
1521
	 *
1522
	 * These will run whenever setup_payment is called, which should only be called once.
1523
	 * To update an attribute, update it directly instead of re-running the setup routine
1524
	 */
1525
1526
	/**
1527
	 * Setup the payment completed date
1528
	 *
1529
	 * @since  1.5
1530
	 * @access private
1531
	 *
1532
	 * @return string The date the payment was completed
1533
	 */
1534
	private function setup_completed_date() {
1535
		$payment = get_post( $this->ID );
1536
1537
		if ( 'pending' == $payment->post_status || 'preapproved' == $payment->post_status ) {
1538
			return false; // This payment was never completed.
1539
		}
1540
1541
		$date = ( $date = $this->get_meta( '_give_completed_date', true ) ) ? $date : $payment->modified_date;
1542
1543
		return $date;
1544
	}
1545
1546
	/**
1547
	 * Setup the payment mode
1548
	 *
1549
	 * @since  1.5
1550
	 * @access private
1551
	 *
1552
	 * @return string The payment mode
1553
	 */
1554
	private function setup_mode() {
1555
		return $this->get_meta( '_give_payment_mode' );
1556
	}
1557
1558
	/**
1559
	 * Setup the payment total
1560
	 *
1561
	 * @since  1.5
1562
	 * @access private
1563
	 *
1564
	 * @return float The payment total
1565
	 */
1566
	private function setup_total() {
1567
		$amount = $this->get_meta( '_give_payment_total', true );
1568
1569
		return round( floatval( $amount ), give_currency_decimal_filter() );
1570
	}
1571
1572
	/**
1573
	 * Setup the payment subtotal
1574
	 *
1575
	 * @since  1.5
1576
	 * @access private
1577
	 *
1578
	 * @return float The subtotal of the payment
1579
	 */
1580
	private function setup_subtotal() {
1581
		$subtotal = $this->total;
1582
1583
		return $subtotal;
1584
	}
1585
1586
	/**
1587
	 * Setup the currency code
1588
	 *
1589
	 * @since  1.5
1590
	 * @since  2.0 Set currency from _give_payment_currency meta key
1591
	 * @access private
1592
	 *
1593
	 * @return string The currency for the payment
1594
	 */
1595
	private function setup_currency() {
1596
		$currency = $this->get_meta( '_give_payment_currency', true );
1597
		$currency = ! empty( $currency ) ?
1598
			$currency :
1599
			apply_filters( 'give_payment_currency_default', give_get_currency(), $this );
1600
1601
		return $currency;
1602
	}
1603
1604
	/**
1605
	 * Setup the gateway used for the payment
1606
	 *
1607
	 * @since  1.5
1608
	 * @access private
1609
	 *
1610
	 * @return string The gateway
1611
	 */
1612
	private function setup_gateway() {
1613
		$gateway = $this->get_meta( '_give_payment_gateway', true );
1614
1615
		return $gateway;
1616
	}
1617
1618
	/**
1619
	 * Setup the donation ID
1620
	 *
1621
	 * @since  1.5
1622
	 * @access private
1623
	 *
1624
	 * @return string The donation ID
1625
	 */
1626
	private function setup_transaction_id() {
1627
		$transaction_id = $this->get_meta( '_give_payment_transaction_id', true );
1628
1629
		if ( empty( $transaction_id ) ) {
1630
			$gateway        = $this->gateway;
1631
			$transaction_id = apply_filters( "give_get_payment_transaction_id-{$gateway}", $this->ID );
1632
		}
1633
1634
		return $transaction_id;
1635
	}
1636
1637
	/**
1638
	 * Setup the IP Address for the payment
1639
	 *
1640
	 * @since  1.5
1641
	 * @since  2.0 Set ip address from _give_payment_donor_ip meta key
1642
	 * @access private
1643
	 *
1644
	 * @return string The IP address for the payment
1645
	 */
1646
	private function setup_ip() {
1647
		$ip = $this->get_meta( '_give_payment_donor_ip', true );
1648
1649
		return $ip;
1650
	}
1651
1652
	/**
1653
	 * Setup the donor ID.
1654
	 *
1655
	 * @since  1.5
1656
	 * @since  2.0 Set id from _give_payment_donor_id meta key
1657
	 * @access private
1658
	 *
1659
	 * @return int The Donor ID.
1660
	 */
1661
	private function setup_donor_id() {
1662
		$donor_id = $this->get_meta( '_give_payment_donor_id', true );
1663
1664
		return $donor_id;
1665
	}
1666
1667
	/**
1668
	 * Setup the User ID associated with the donation
1669
	 *
1670
	 * @since  1.5
1671
	 * @since  2.0 Get user id connect to donor from donor table instead of payment meta.
1672
	 *
1673
	 * @access private
1674
	 *
1675
	 * @return int The User ID
1676
	 */
1677
	private function setup_user_id() {
1678
1679
		$donor   = Give()->customers->get_customer_by( 'id', $this->customer_id );
1680
		$user_id = $donor ? absint( $donor->user_id ) : 0;
1681
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1682
1683
		return $user_id;
1684
	}
1685
1686
	/**
1687
	 * Setup the email address for the donation.
1688
	 *
1689
	 * @since  1.5
1690
	 * @since  2.0 Set email from _give_payment_donor_email meta key
1691
	 *
1692
	 * @access private
1693
	 *
1694
	 * @return string The email address for the payment.
1695
	 */
1696
	private function setup_email() {
1697
		$email = $this->get_meta( '_give_payment_donor_email', true );
1698
1699
		if ( empty( $email ) && $this->customer_id ) {
1700
			$email = Give()->donors->get_column( 'email', $this->customer_id );
1701
		}
1702
1703
		return $email;
1704
	}
1705
1706
	/**
1707
	 * Setup the user info.
1708
	 *
1709
	 * @since  1.5
1710
	 * @access private
1711
	 *
1712
	 * @return array The user info associated with the payment.
1713
	 */
1714
	private function setup_user_info() {
1715
		$defaults = array(
1716
			'first_name' => $this->first_name,
1717
			'last_name'  => $this->last_name,
1718
		);
1719
1720
		$user_info = isset( $this->payment_meta['user_info'] ) ? maybe_unserialize( $this->payment_meta['user_info'] ) : array();
1721
		$user_info = wp_parse_args( $user_info, $defaults );
1722
1723
		if ( empty( $user_info ) ) {
1724
			// Get the donor, but only if it's been created.
1725
			$donor = new Give_Donor( $this->customer_id );
0 ignored issues
show
Documentation introduced by
$this->customer_id is of type integer, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1726
1727
			if ( $donor->id > 0 ) {
1728
				$name      = explode( ' ', $donor->name, 2 );
1729
				$user_info = array(
1730
					'first_name' => $name[0],
1731
					'last_name'  => $name[1],
1732
					'email'      => $donor->email,
1733
					'discount'   => 'none',
1734
				);
1735
			}
1736
		} else {
1737
			// Get the donor, but only if it's been created.
1738
			$donor = new Give_Donor( $this->customer_id );
0 ignored issues
show
Documentation introduced by
$this->customer_id is of type integer, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1739
			if ( $donor->id > 0 ) {
1740
				foreach ( $user_info as $key => $value ) {
1741
					if ( ! empty( $value ) ) {
1742
						continue;
1743
					}
1744
1745
					switch ( $key ) {
1746
						case 'first_name':
1747
							$name = explode( ' ', $donor->name, 2 );
1748
1749
							$user_info[ $key ] = $name[0];
1750
							break;
1751
1752
						case 'last_name':
1753
							$name      = explode( ' ', $donor->name, 2 );
1754
							$last_name = ! empty( $name[1] ) ? $name[1] : '';
1755
1756
							$user_info[ $key ] = $last_name;
1757
							break;
1758
1759
						case 'email':
1760
							$user_info[ $key ] = $donor->email;
1761
							break;
1762
					}
1763
				}
1764
			}
1765
		}// End if().
1766
1767
		return $user_info;
1768
1769
	}
1770
1771
	/**
1772
	 * Setup the Address for the payment.
1773
	 *
1774
	 * @since  1.5
1775
	 * @access private
1776
	 *
1777
	 * @return array The Address information for the payment.
1778
	 */
1779
	private function setup_address() {
1780
		$address['line1']   = give_get_meta( $this->ID, '_give_donor_billing_address1', true, '' );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1781
		$address['line2']   = give_get_meta( $this->ID, '_give_donor_billing_address2', true, '' );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1782
		$address['city']    = give_get_meta( $this->ID, '_give_donor_billing_city', true, '' );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1783
		$address['state']   = give_get_meta( $this->ID, '_give_donor_billing_state', true, '' );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1784
		$address['zip']     = give_get_meta( $this->ID, '_give_donor_billing_zip', true, '' );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1785
		$address['country'] = give_get_meta( $this->ID, '_give_donor_billing_country', true, '' );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1786
1787
		return $address;
1788
	}
1789
1790
	/**
1791
	 * Setup the form title.
1792
	 *
1793
	 * @since  1.5
1794
	 * @access private
1795
	 *
1796
	 * @return string The Form Title.
1797
	 */
1798
	private function setup_form_title() {
1799
1800
		$form_id = $this->get_meta( '_give_payment_form_title', true );
1801
1802
		return $form_id;
1803
	}
1804
1805
	/**
1806
	 * Setup the form ID.
1807
	 *
1808
	 * @since  1.5
1809
	 * @access private
1810
	 *
1811
	 * @return int The Form ID
1812
	 */
1813
	private function setup_form_id() {
1814
1815
		$form_id = $this->get_meta( '_give_payment_form_id', true );
1816
1817
		return $form_id;
1818
	}
1819
1820
	/**
1821
	 * Setup the price ID.
1822
	 *
1823
	 * @since  1.5
1824
	 * @access private
1825
	 *
1826
	 * @return int The Form Price ID.
1827
	 */
1828
	private function setup_price_id() {
1829
		$price_id = $this->get_meta( '_give_payment_price_id', true );
1830
1831
		return $price_id;
1832
	}
1833
1834
	/**
1835
	 * Setup the payment key.
1836
	 *
1837
	 * @since  1.5
1838
	 * @access private
1839
	 *
1840
	 * @return string The Payment Key.
1841
	 */
1842
	private function setup_payment_key() {
1843
		$key = $this->get_meta( '_give_payment_purchase_key', true );
1844
1845
		return $key;
1846
	}
1847
1848
	/**
1849
	 * Setup the payment number.
1850
	 *
1851
	 * @since  1.5
1852
	 * @access private
1853
	 *
1854
	 * @return int|string Integer by default, or string if sequential order numbers is enabled.
1855
	 */
1856
	private function setup_payment_number() {
1857
		$number = $this->ID;
1858
1859
		if ( give_get_option( 'enable_sequential' ) ) {
1860
1861
			$number = $this->get_meta( '_give_payment_number', true );
1862
1863
			if ( ! $number ) {
1864
1865
				$number = $this->ID;
1866
1867
			}
1868
		}
1869
1870
		return $number;
1871
	}
1872
1873
	/**
1874
	 * Converts this object into an array for special cases.
1875
	 *
1876
	 * @access public
1877
	 *
1878
	 * @return array The payment object as an array.
1879
	 */
1880
	public function array_convert() {
1881
		return get_object_vars( $this );
1882
	}
1883
1884
1885
	/**
1886
	 * Flag to check if donation is completed or not.
1887
	 *
1888
	 * @since  1.8
1889
	 * @access public
1890
	 *
1891
	 * @return bool
1892
	 */
1893
	public function is_completed() {
1894
		return ( 'publish' === $this->status && $this->completed_date );
1895
	}
1896
1897
	/**
1898
	 * Retrieve payment completion date.
1899
	 *
1900
	 * @since  1.5
1901
	 * @access private
1902
	 *
1903
	 * @return string Date payment was completed.
1904
	 */
1905
	private function get_completed_date() {
1906
		return apply_filters( 'give_payment_completed_date', $this->completed_date, $this->ID, $this );
1907
	}
1908
1909
	/**
1910
	 * Retrieve payment subtotal.
1911
	 *
1912
	 * @since  1.5
1913
	 * @access private
1914
	 *
1915
	 * @return float Payment subtotal.
1916
	 */
1917
	private function get_subtotal() {
1918
		return apply_filters( 'give_get_payment_subtotal', $this->subtotal, $this->ID, $this );
1919
	}
1920
1921
	/**
1922
	 * Retrieve payment currency.
1923
	 *
1924
	 * @since  1.5
1925
	 * @access private
1926
	 *
1927
	 * @return string Payment currency code.
1928
	 */
1929
	private function get_currency() {
1930
		return apply_filters( 'give_payment_currency_code', $this->currency, $this->ID, $this );
1931
	}
1932
1933
	/**
1934
	 * Retrieve payment gateway.
1935
	 *
1936
	 * @since  1.5
1937
	 * @access private
1938
	 *
1939
	 * @return string Gateway used.
1940
	 */
1941
	private function get_gateway() {
1942
		return apply_filters( 'give_payment_gateway', $this->gateway, $this->ID, $this );
1943
	}
1944
1945
	/**
1946
	 * Retrieve donation ID.
1947
	 *
1948
	 * @since  1.5
1949
	 * @access private
1950
	 *
1951
	 * @return string Donation ID from merchant processor.
1952
	 */
1953
	private function get_transaction_id() {
1954
		return apply_filters( 'give_get_payment_transaction_id', $this->transaction_id, $this->ID, $this );
1955
	}
1956
1957
	/**
1958
	 * Retrieve payment IP
1959
	 *
1960
	 * @since  1.5
1961
	 * @access private
1962
	 *
1963
	 * @return string Payment IP address
1964
	 */
1965
	private function get_ip() {
1966
		return apply_filters( 'give_payment_user_ip', $this->ip, $this->ID, $this );
1967
	}
1968
1969
	/**
1970
	 * Retrieve payment donor ID.
1971
	 *
1972
	 * @since  1.5
1973
	 * @access private
1974
	 *
1975
	 * @return int Payment donor ID.
1976
	 */
1977
	private function get_donor_id() {
1978
		return apply_filters( 'give_payment_customer_id', $this->customer_id, $this->ID, $this );
1979
	}
1980
1981
	/**
1982
	 * Retrieve payment user ID.
1983
	 *
1984
	 * @since  1.5
1985
	 * @access private
1986
	 *
1987
	 * @return int Payment user ID.
1988
	 */
1989
	private function get_user_id() {
1990
		return apply_filters( 'give_payment_user_id', $this->user_id, $this->ID, $this );
1991
	}
1992
1993
	/**
1994
	 * Retrieve payment email.
1995
	 *
1996
	 * @since  1.5
1997
	 * @access private
1998
	 *
1999
	 * @return string Payment donor email.
2000
	 */
2001
	private function get_email() {
2002
		return apply_filters( 'give_payment_user_email', $this->email, $this->ID, $this );
2003
	}
2004
2005
	/**
2006
	 * Retrieve payment user info.
2007
	 *
2008
	 * @since  1.5
2009
	 * @access private
2010
	 *
2011
	 * @return array Payment user info.
2012
	 */
2013
	private function get_user_info() {
2014
		return apply_filters( 'give_payment_meta_user_info', $this->user_info, $this->ID, $this );
2015
	}
2016
2017
	/**
2018
	 * Retrieve payment billing address.
2019
	 *
2020
	 * @since  1.5
2021
	 * @access private
2022
	 *
2023
	 * @return array Payment billing address.
2024
	 */
2025
	private function get_address() {
2026
		return apply_filters( 'give_payment_address', $this->address, $this->ID, $this );
2027
	}
2028
2029
	/**
2030
	 * Retrieve payment key.
2031
	 *
2032
	 * @since  1.5
2033
	 * @access private
2034
	 *
2035
	 * @return string Payment key.
2036
	 */
2037
	private function get_key() {
2038
		return apply_filters( 'give_payment_key', $this->key, $this->ID, $this );
2039
	}
2040
2041
	/**
2042
	 * Retrieve payment form id
2043
	 *
2044
	 * @since  1.5
2045
	 * @access private
2046
	 *
2047
	 * @return string Payment form id
2048
	 */
2049
	private function get_form_id() {
2050
		return apply_filters( 'give_payment_form_id', $this->form_id, $this->ID, $this );
2051
	}
2052
2053
	/**
2054
	 * Retrieve payment number
2055
	 *
2056
	 * @since  1.5
2057
	 * @access private
2058
	 *
2059
	 * @return int|string Payment number
2060
	 */
2061
	private function get_number() {
2062
		return apply_filters( 'give_payment_number', $this->number, $this->ID, $this );
2063
	}
2064
}
2065