Test Failed
Push — issues/370 ( 90279e )
by Ravinder
05:35
created

Give_Payment::get_meta()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 26
Code Lines 8

Duplication

Lines 6
Ratio 23.08 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 2
dl 6
loc 26
rs 8.8571
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     $import
27
 * @property string     $key
28
 * @property string     $form_title
29
 * @property string|int $form_id
30
 * @property string|int $price_id
31
 * @property string|int $total
32
 * @property string|int $subtotal
33
 * @property string|int $fees
34
 * @property string|int $fees_total
35
 * @property string     $post_status
36
 * @property string     $date
37
 * @property string     $postdate
38
 * @property string     $status
39
 * @property string     $email
40
 * @property array      $payment_meta
41
 * @property string     $customer_id
42
 * @property string     $completed_date
43
 * @property string     $currency
44
 * @property string     $ip
45
 * @property array      $user_info
46
 * @property string     $gateway
47
 * @property string     $user_id
48
 * @property string     $first_name
49
 * @property string     $last_name
50
 * @property string     $parent_payment
51
 * @property string     $transaction_id
52
 * @property string     $old_status
53
 *
54
 * @since 1.5
55
 */
56
final class Give_Payment {
57
58
	/**
59
	 * The Payment ID.
60
	 *
61
	 * @since  1.5
62
	 *
63
	 * @var    int
64
	 */
65
	public $ID = 0;
66
67
	/**
68
	 * Protected non-read $_ID.
69
	 *
70
	 * @var int
71
	 */
72
	protected $_ID = 0;
73
74
	/**
75
	 * Identify if the payment is a new one or existing.
76
	 *
77
	 * @since  1.5
78
	 * @access protected
79
	 *
80
	 * @var    boolean
81
	 */
82
	protected $new = false;
83
84
	/**
85
	 * The Payment number (for use with sequential payments).
86
	 *
87
	 * @since  1.5
88
	 * @access protected
89
	 *
90
	 * @var    string
91
	 */
92
	protected $number = '';
93
94
	/**
95
	 * The Gateway mode the payment was made in.
96
	 *
97
	 * @since  1.5
98
	 * @access protected
99
	 *
100
	 * @var    string
101
	 */
102
	protected $mode = 'live';
103
104
	/**
105
	 * Is donations is Import or not.
106
	 *
107
	 * @since  1.8.13
108
	 * @access protected
109
	 *
110
	 * @var    bool
111
	 */
112
	protected $import = false;
113
114
	/**
115
	 * The unique donation payment key.
116
	 *
117
	 * @since  1.5
118
	 * @access protected
119
	 *
120
	 * @var    string
121
	 */
122
	protected $key = '';
123
124
	/**
125
	 * The Donation Form Title
126
	 *
127
	 * @since  1.5
128
	 * @access protected
129
	 *
130
	 * @var    string
131
	 */
132
	protected $form_title = 0;
133
134
	/**
135
	 * The Donation Form ID
136
	 *
137
	 * @since  1.5
138
	 * @access protected
139
	 *
140
	 * @var    string
141
	 */
142
	protected $form_id = 0;
143
144
	/**
145
	 * The Donation Form Price ID
146
	 *
147
	 * @since  1.5
148
	 * @access protected
149
	 *
150
	 * @var    string|int
151
	 */
152
	protected $price_id = 0;
153
154
	/**
155
	 * The total amount of the donation payment.
156
	 *
157
	 * @since  1.5
158
	 * @access protected
159
	 *
160
	 * @var    float
161
	 */
162
	protected $total = 0.00;
163
164
	/**
165
	 * The Subtotal fo the payment.
166
	 *
167
	 * @since  1.5
168
	 * @access protected
169
	 *
170
	 * @var    float
171
	 */
172
	protected $subtotal = 0;
173
174
	/**
175
	 * The date the payment was created
176
	 *
177
	 * @since  1.5
178
	 * @access protected
179
	 *
180
	 * @var    string
181
	 */
182
	protected $date = '';
183
184
	/**
185
	 * The date the payment post was created.
186
	 *
187
	 * @var string
188
	 */
189
	protected $post_date = '';
190
191
	/**
192
	 * The date the payment was marked as 'complete'.
193
	 *
194
	 * @since  1.5
195
	 * @access protected
196
	 *
197
	 * @var    string
198
	 */
199
	protected $completed_date = '';
200
201
	/**
202
	 * The status of the donation payment.
203
	 *
204
	 * @since  1.5
205
	 * @access protected
206
	 *
207
	 * @var    string
208
	 */
209
	protected $status = 'pending';
210
211
	/**
212
	 * @var string
213
	 */
214
	protected $post_status = 'pending'; // Same as $status but here for backwards compat
215
216
	/**
217
	 * When updating, the old status prior to the change
218
	 *
219
	 * @since  1.5
220
	 * @access protected
221
	 *
222
	 * @var    string
223
	 */
224
	protected $old_status = '';
225
226
	/**
227
	 * The display name of the current payment status.
228
	 *
229
	 * @since  1.5
230
	 * @access protected
231
	 *
232
	 * @var    string
233
	 */
234
	protected $status_nicename = '';
235
236
	/**
237
	 * The donor ID that made the payment.
238
	 *
239
	 * @since  1.5
240
	 * @access protected
241
	 *
242
	 * @var    integer
243
	 */
244
	protected $customer_id = null;
245
246
	/**
247
	 * The Donor ID (if logged in) that made the payment
248
	 *
249
	 * @since  1.8.13
250
	 * @access protected
251
	 *
252
	 * @var    integer
253
	 */
254
	protected $donor_id = 0;
255
256
	/**
257
	 * The User ID (if logged in) that made the payment
258
	 *
259
	 * @since  1.5
260
	 * @access protected
261
	 *
262
	 * @var    integer
263
	 */
264
	protected $user_id = 0;
265
266
	/**
267
	 * The first name of the payee
268
	 *
269
	 * @since  1.5
270
	 * @access protected
271
	 *
272
	 * @var    string
273
	 */
274
	protected $first_name = '';
275
276
	/**
277
	 * The last name of the payee
278
	 *
279
	 * @since  1.5
280
	 * @access protected
281
	 *
282
	 * @var    string
283
	 */
284
	protected $last_name = '';
285
286
	/**
287
	 * The email used for the payment
288
	 *
289
	 * @since  1.5
290
	 * @access protected
291
	 *
292
	 * @var    string
293
	 */
294
	protected $email = '';
295
296
	/**
297
	 * Legacy (not to be accessed) array of user information
298
	 *
299
	 * @since  1.5
300
	 * @access private
301
	 *
302
	 * @var    array
303
	 */
304
	private $user_info = array();
305
306
	/**
307
	 * Legacy (not to be accessed) payment meta array
308
	 *
309
	 * @since  1.5
310
	 * @access private
311
	 *
312
	 * @var    array
313
	 */
314
	private $payment_meta = array();
315
316
	/**
317
	 * The physical address used for the payment if provided
318
	 *
319
	 * @since  1.5
320
	 * @access protected
321
	 *
322
	 * @var    array
323
	 */
324
	protected $address = array();
325
326
	/**
327
	 * The transaction ID returned by the gateway
328
	 *
329
	 * @since  1.5
330
	 * @access protected
331
	 *
332
	 * @var    string
333
	 */
334
	protected $transaction_id = '';
335
336
	/**
337
	 * IP Address payment was made from
338
	 *
339
	 * @since  1.5
340
	 * @access protected
341
	 *
342
	 * @var    string
343
	 */
344
	protected $ip = '';
345
346
	/**
347
	 * The gateway used to process the payment
348
	 *
349
	 * @since  1.5
350
	 * @access protected
351
	 *
352
	 * @var    string
353
	 */
354
	protected $gateway = '';
355
356
	/**
357
	 * The the payment was made with
358
	 *
359
	 * @since  1.5
360
	 * @access protected
361
	 *
362
	 * @var    string
363
	 */
364
	protected $currency = '';
365
366
	/**
367
	 * Array of items that have changed since the last save() was run.
368
	 * This is for internal use, to allow fewer update_payment_meta calls to be run.
369
	 *
370
	 * @since  1.5
371
	 * @access private
372
	 *
373
	 * @var    array
374
	 */
375
	private $pending;
376
377
	/**
378
	 * The parent payment (if applicable)
379
	 *
380
	 * @since  1.5
381
	 * @access protected
382
	 *
383
	 * @var    integer
384
	 */
385
	protected $parent_payment = 0;
386
387
	/**
388
	 * Setup the Give Payments class
389
	 *
390
	 * @since  1.5
391
	 * @access public
392
	 *
393
	 * @param  int|bool $payment_id A given payment
394
	 *
395
	 * @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...
396
	 */
397
	public function __construct( $payment_id = false ) {
398
399
		if ( empty( $payment_id ) ) {
400
			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...
401
		}
402
403
		$this->setup_payment( $payment_id );
0 ignored issues
show
Bug introduced by
It seems like $payment_id defined by parameter $payment_id on line 397 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...
404
	}
405
406
	/**
407
	 * Magic GET function.
408
	 *
409
	 * @since  1.5
410
	 * @access public
411
	 *
412
	 * @param  string $key The property.
413
	 *
414
	 * @return mixed        The value.
415
	 */
416
	public function __get( $key ) {
417
418
		if ( method_exists( $this, 'get_' . $key ) ) {
419
420
			$value = call_user_func( array( $this, 'get_' . $key ) );
421
422
		} else {
423
424
			$value = $this->$key;
425
426
		}
427
428
		return $value;
429
	}
430
431
	/**
432
	 * Magic SET function
433
	 *
434
	 * Sets up the pending array for the save method
435
	 *
436
	 * @since  1.5
437
	 * @access public
438
	 *
439
	 * @param  string $key   The property name
440
	 * @param  mixed  $value The value of the property
441
	 */
442
	public function __set( $key, $value ) {
443
		$ignore = array( '_ID' );
444
445
		if ( 'status' === $key ) {
446
			$this->old_status = $this->status;
447
		}
448
449
		if ( ! in_array( $key, $ignore ) ) {
450
			$this->pending[ $key ] = $value;
451
		}
452
453
		if ( '_ID' !== $key ) {
454
			$this->$key = $value;
455
		}
456
	}
457
458
	/**
459
	 * Magic ISSET function, which allows empty checks on protected elements
460
	 *
461
	 * @since  1.5
462
	 * @access public
463
	 *
464
	 * @param  string $name The attribute to get
465
	 *
466
	 * @return boolean|null       If the item is set or not
467
	 */
468
	public function __isset( $name ) {
469
		if ( property_exists( $this, $name ) ) {
470
			return false === empty( $this->$name );
471
		} else {
472
			return null;
473
		}
474
	}
475
476
	/**
477
	 * Setup payment properties
478
	 *
479
	 * @since  1.5
480
	 * @access private
481
	 *
482
	 * @param  int $payment_id The payment ID
483
	 *
484
	 * @return bool            If the setup was successful or not
485
	 */
486
	private function setup_payment( $payment_id ) {
487
		$this->pending = array();
488
489
		if ( empty( $payment_id ) ) {
490
			return false;
491
		}
492
493
		$payment = get_post( $payment_id );
494
495
		if ( ! $payment || is_wp_error( $payment ) ) {
496
			return false;
497
		}
498
499
		if ( 'give_payment' !== $payment->post_type ) {
500
			return false;
501
		}
502
503
		/**
504
		 * Fires before payment setup.
505
		 *
506
		 * Allow extensions to perform actions before the payment is loaded.
507
		 *
508
		 * @since 1.5
509
		 *
510
		 * @param Give_Payment $this       Payment object.
511
		 * @param int          $payment_id The ID of the payment.
512
		 */
513
		do_action( 'give_pre_setup_payment', $this, $payment_id );
514
515
		// Primary Identifier.
516
		$this->ID = absint( $payment_id );
517
518
		// Protected ID that can never be changed.
519
		$this->_ID = absint( $payment_id );
520
521
		// We have a payment, get the generic payment_meta item to reduce calls to it.
522
		$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...
523
524
		// Status and Dates.
525
		$this->date           = $payment->post_date;
526
		$this->post_date      = $payment->post_date;
527
		$this->completed_date = $this->setup_completed_date();
528
		$this->status         = $payment->post_status;
529
		$this->post_status    = $this->status;
530
		$this->mode           = $this->setup_mode();
531
		$this->import         = $this->setup_import();
532
		$this->parent_payment = $payment->post_parent;
533
534
		$all_payment_statuses  = give_get_payment_statuses();
535
		$this->status_nicename = array_key_exists( $this->status, $all_payment_statuses ) ? $all_payment_statuses[ $this->status ] : ucfirst( $this->status );
536
537
		// Currency Based.
538
		$this->total    = $this->setup_total();
539
		$this->subtotal = $this->setup_subtotal();
540
		$this->currency = $this->setup_currency();
541
542
		// Gateway based.
543
		$this->gateway        = $this->setup_gateway();
544
		$this->transaction_id = $this->setup_transaction_id();
545
546
		// User based.
547
		$this->ip          = $this->setup_ip();
548
		$this->customer_id = $this->setup_donor_id();
549
		$this->user_id     = $this->setup_user_id();
550
		$this->email       = $this->setup_email();
551
		$this->user_info   = $this->setup_user_info();
552
		$this->address     = $this->setup_address();
553
		$this->first_name  = $this->user_info['first_name'];
554
		$this->last_name   = $this->user_info['last_name'];
555
556
		// Other Identifiers.
557
		$this->form_title = $this->setup_form_title();
558
		$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...
559
		$this->price_id   = $this->setup_price_id();
560
		$this->key        = $this->setup_payment_key();
561
		$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...
562
563
		/**
564
		 * Fires after payment setup.
565
		 *
566
		 * Allow extensions to add items to this object via hook.
567
		 *
568
		 * @since 1.5
569
		 *
570
		 * @param Give_Payment $this       Payment object.
571
		 * @param int          $payment_id The ID of the payment.
572
		 */
573
		do_action( 'give_setup_payment', $this, $payment_id );
574
575
		return true;
576
	}
577
578
	/**
579
	 * Payment class object is storing various meta value in object parameter.
580
	 * So if user is updating payment meta but not updating payment object, then payment meta values will not reflect/changes on payment meta automatically
581
	 * 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.
582
	 * To prevent that user can use this function after updating any payment meta value ( in bulk or single update ).
583
	 *
584
	 * @since  1.6
585
	 * @access public
586
	 *
587
	 * @param  int $payment_id Payment ID.
588
	 *
589
	 * @return void
590
	 */
591
	public function update_payment_setup( $payment_id ) {
592
		$this->setup_payment( $payment_id );
593
	}
594
595
	/**
596
	 * Create the base of a payment.
597
	 *
598
	 * @since  1.5
599
	 * @access private
600
	 *
601
	 * @return int|bool False on failure, the payment ID on success.
602
	 */
603
	private function insert_payment() {
604
605
		// Construct the payment title.
606
		$payment_title = '';
607
		if ( ! empty( $this->first_name ) && ! empty( $this->last_name ) ) {
608
			$payment_title = $this->first_name . ' ' . $this->last_name;
609
		} elseif ( ! empty( $this->first_name ) && empty( $this->last_name ) ) {
610
			$payment_title = $this->first_name;
611
		} elseif ( ! empty( $this->email ) && is_email( $this->email ) ) {
612
			$payment_title = $this->email;
613
		}
614
615
		// Set Key.
616
		if ( empty( $this->key ) ) {
617
618
			$auth_key             = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
619
			$this->key            = strtolower( md5( $this->email . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'give', true ) ) );  // Unique key
620
			$this->pending['key'] = $this->key;
621
		}
622
623
		// Set IP.
624
		if ( empty( $this->ip ) ) {
625
626
			$this->ip            = give_get_ip();
627
			$this->pending['ip'] = $this->ip;
628
629
		}
630
631
		// @todo: payment data exist here only for backward compatibility
632
		// issue: https://github.com/WordImpress/Give/issues/1132
633
		$payment_data = array(
634
			'price'        => $this->total,
635
			'date'         => $this->date,
636
			'user_email'   => $this->email,
637
			'purchase_key' => $this->key,
638
			'form_title'   => $this->form_title,
639
			'form_id'      => $this->form_id,
640
			'donor_id'     => $this->donor_id,
641
			'price_id'     => $this->price_id,
642
			'currency'     => $this->currency,
643
			'user_info'    => array(
644
				'id'         => $this->user_id,
645
				'email'      => $this->email,
646
				'first_name' => $this->first_name,
647
				'last_name'  => $this->last_name,
648
				'address'    => $this->address,
649
			),
650
			'status'       => $this->status,
651
		);
652
653
		$args = apply_filters( 'give_insert_payment_args', array(
654
			'post_title'    => $payment_title,
655
			'post_status'   => $this->status,
656
			'post_type'     => 'give_payment',
657
			'post_date'     => ! empty( $this->date ) ? $this->date : null,
658
			'post_date_gmt' => ! empty( $this->date ) ? get_gmt_from_date( $this->date ) : null,
659
			'post_parent'   => $this->parent_payment,
660
		), $payment_data );
661
662
		// Create a blank payment
663
		$payment_id = wp_insert_post( $args );
664
665
		if ( ! empty( $payment_id ) ) {
666
667
			$this->ID  = $payment_id;
668
			$this->_ID = $payment_id;
669
670
			$donor = new stdClass;
671
672
			/**
673
			 * Filter donor class after the donation is completed and before customer table is updated.
674
			 *
675
			 * @since 1.8.13
676
			 */
677
			$donor = apply_filters( 'give_update_donor_information', $donor, $payment_id, $payment_data, $args );
678
679
			if ( did_action( 'give_pre_process_donation' ) && is_user_logged_in() ) {
680
				$donor = new Give_Donor( get_current_user_id(), true );
681
682
				// Donor is logged in but used a different email to purchase with so assign to their donor record.
683
				if ( ! empty( $donor->id ) && $this->email !== $donor->email ) {
684
					$donor->add_email( $this->email );
685
				}
686
			}
687
688
			if ( empty( $donor->id ) ) {
689
				$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...
690
			}
691
692
			if ( empty( $donor->id ) ) {
693
694
				$donor_data = array(
695
					'name'    => ! is_email( $payment_title ) ? $this->first_name . ' ' . $this->last_name : '',
696
					'email'   => $this->email,
697
					'user_id' => $this->user_id,
698
				);
699
700
				$donor->create( $donor_data );
701
702
			}
703
704
			// Update Donor Meta once donor is created.
705
			$donor->update_meta( '_give_donor_first_name', $this->first_name );
706
			$donor->update_meta( '_give_donor_last_name', $this->last_name );
707
708
			$this->customer_id            = $donor->id;
709
			$this->pending['customer_id'] = $this->customer_id;
710
			$donor->attach_payment( $this->ID, false );
711
712
			$this->payment_meta = apply_filters( 'give_payment_meta', $this->payment_meta, $payment_data );
713
714
			$this->new = true;
715
		}// End if().
716
717
		return $this->ID;
718
719
	}
720
721
	/**
722
	 * Save
723
	 *
724
	 * Once items have been set, an update is needed to save them to the database.
725
	 *
726
	 * @access public
727
	 *
728
	 * @return bool  True of the save occurred, false if it failed or wasn't needed
729
	 */
730
	public function save() {
731
		$saved = false;
732
733
		// Must have an ID.
734
		if ( empty( $this->ID ) ) {
735
736
			$payment_id = $this->insert_payment();
737
738
			if ( false === $payment_id ) {
739
				$saved = false;
740
			} else {
741
				$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...
742
			}
743
		}
744
745
		// Set ID if not matching.
746
		if ( $this->ID !== $this->_ID ) {
747
			$this->ID = $this->_ID;
748
		}
749
750
		// If we have something pending, let's save it.
751
		if ( ! empty( $this->pending ) ) {
752
753
			$total_increase = 0;
754
			$total_decrease = 0;
755
756
			foreach ( $this->pending as $key => $value ) {
757
758
				switch ( $key ) {
759
760
					case 'donations':
761
						// Update totals for pending donations.
762
						foreach ( $this->pending[ $key ] as $item ) {
763
764
							$quantity = isset( $item['quantity'] ) ? $item['quantity'] : 1;
765
							$price_id = isset( $item['price_id'] ) ? $item['price_id'] : 0;
766
767
							switch ( $item['action'] ) {
768
769
								case 'add':
770
771
									$price = $item['price'];
772
773
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
774
775
										// Add donation to logs.
776
										$log_date = date_i18n( 'Y-m-d G:i:s', current_time( 'timestamp' ) );
777
										give_record_donation_in_log( $item['id'], $this->ID, $price_id, $log_date );
778
779
										$form = new Give_Donate_Form( $item['id'] );
780
										$form->increase_sales( $quantity );
781
										$form->increase_earnings( $price );
782
783
										$total_increase += $price;
784
									}
785
									break;
786
787
								case 'remove':
788
									$this->delete_sales_logs();
789
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
790
										$form = new Give_Donate_Form( $item['id'] );
791
										$form->decrease_sales( $quantity );
792
										$form->decrease_earnings( $item['amount'] );
793
794
										$total_decrease += $item['amount'];
795
									}
796
									break;
797
798
							}// End switch().
799
						}// End foreach().
800
						break;
801
802
					case 'status':
803
						$this->update_status( $this->status );
804
						break;
805
806
					case 'gateway':
807
						$this->update_meta( '_give_payment_gateway', $this->gateway );
808
						break;
809
810
					case 'mode':
811
						$this->update_meta( '_give_payment_mode', $this->mode );
812
						break;
813
814
					case 'transaction_id':
815
						$this->update_meta( '_give_payment_transaction_id', $this->transaction_id );
816
						break;
817
818
					case 'ip':
819
						$this->update_meta( '_give_payment_donor_ip', $this->ip );
820
						break;
821
822
					case 'customer_id':
823
						$this->update_meta( '_give_payment_donor_id', $this->customer_id );
824
						break;
825
826
					// case 'user_id':
827
					// 	$this->update_meta( '_give_payment_user_id', $this->user_id );
828
					// 	break;
829
830
					case 'form_title':
831
						$this->update_meta( '_give_payment_form_title', $this->form_title );
832
						break;
833
834
					case 'form_id':
835
						$this->update_meta( '_give_payment_form_id', $this->form_id );
836
						break;
837
838
					case 'price_id':
839
						$this->update_meta( '_give_payment_price_id', $this->price_id );
840
						break;
841
842
					case 'first_name':
843
						$this->update_meta( '_give_donor_billing_first_name', $this->first_name );
844
						break;
845
846
					case 'last_name':
847
						$this->update_meta( '_give_donor_billing_last_name', $this->last_name );
848
						break;
849
850
					case 'currency':
851
						$this->update_meta( '_give_payment_currency', $this->currency );
852
						break;
853
854
					case 'address':
855
						if ( ! empty( $this->address ) ) {
856
							foreach ( $this->address as $address_name => $address ) {
857
								switch ( $address_name ) {
858
									case 'line1':
859
										$this->update_meta( '_give_donor_billing_address1', $address );
860
										break;
861
862
									case 'line2':
863
										$this->update_meta( '_give_donor_billing_address2', $address );
864
										break;
865
866
									default:
867
										$this->update_meta( "_give_donor_billing_{$address_name}", $address );
868
								}
869
							}
870
						}
871
						break;
872
873
					case 'email':
874
						$this->update_meta( '_give_payment_donor_email', $this->email );
875
						break;
876
877
					case 'key':
878
						$this->update_meta( '_give_payment_purchase_key', $this->key );
879
						break;
880
881
					case 'number':
882
						$this->update_meta( '_give_payment_number', $this->number );
883
						break;
884
885
					case 'date':
886
						$args = array(
887
							'ID'        => $this->ID,
888
							'post_date' => $this->date,
889
							'edit_date' => true,
890
						);
891
892
						wp_update_post( $args );
893
						break;
894
895
					case 'completed_date':
896
						$this->update_meta( '_give_completed_date', $this->completed_date );
897
						break;
898
899
					case 'parent_payment':
900
						$args = array(
901
							'ID'          => $this->ID,
902
							'post_parent' => $this->parent_payment,
903
						);
904
905
						wp_update_post( $args );
906
						break;
907
908
					default:
909
						/**
910
						 * Fires while saving payment.
911
						 *
912
						 * @since 1.7
913
						 *
914
						 * @param Give_Payment $this Payment object.
915
						 */
916
						do_action( 'give_payment_save', $this, $key );
917
						break;
918
				}// End switch().
919
			}// End foreach().
920
921
			if ( 'pending' !== $this->status ) {
922
923
				$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...
924
925
				$total_change = $total_increase - $total_decrease;
926
				if ( $total_change < 0 ) {
927
928
					$total_change = - ( $total_change );
929
					// Decrease the donor's donation stats.
930
					$donor->decrease_value( $total_change );
931
					give_decrease_total_earnings( $total_change );
932
933
				} elseif ( $total_change > 0 ) {
934
935
					// Increase the donor's donation stats.
936
					$donor->increase_value( $total_change );
937
					give_increase_total_earnings( $total_change );
938
939
				}
940
			}
941
942
			$this->update_meta( '_give_payment_total', give_sanitize_amount_for_db( $this->total ) );
943
944
			$this->pending = array();
945
			$saved         = true;
946
		}// End if().
947
948
		if ( true === $saved ) {
949
			$this->setup_payment( $this->ID );
950
		}
951
952
		return $saved;
953
	}
954
955
	/**
956
	 * Add a donation to a given payment
957
	 *
958
	 * @since  1.5
959
	 * @access public
960
	 *
961
	 * @param  int   $form_id The donation form to add
962
	 * @param  array $args    Other arguments to pass to the function
963
	 * @param  array $options List of donation options
964
	 *
965
	 * @return bool           True when successful, false otherwise
966
	 */
967
	public function add_donation( $form_id = 0, $args = array(), $options = array() ) {
968
969
		$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...
970
971
		// Bail if this post isn't a give donation form.
972
		if ( ! $donation || $donation->post_type !== 'give_forms' ) {
0 ignored issues
show
introduced by
Found "!== '". Use Yoda Condition checks, you must
Loading history...
973
			return false;
974
		}
975
976
		// Set some defaults.
977
		$defaults = array(
978
			'price'    => false,
979
			'price_id' => false,
980
		);
981
982
		$args = wp_parse_args( apply_filters( 'give_payment_add_donation_args', $args, $donation->ID ), $defaults );
983
984
		// Allow overriding the price.
985
		if ( false !== $args['price'] ) {
986
			$donation_amount = $args['price'];
987
		} else {
988
989
			// Deal with variable pricing.
990
			if ( give_has_variable_prices( $donation->ID ) ) {
991
				$prices          = give_get_meta( $form_id, '_give_donation_levels', true );
992
				$donation_amount = '';
993
				// Loop through prices.
994 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...
995
					// Find a match between price_id and level_id.
996
					// First verify array keys exists THEN make the match.
997
					if ( ( isset( $args['price_id'] ) && isset( $price['_give_id']['level_id'] ) )
998
					     && $args['price_id'] == $price['_give_id']['level_id']
999
					) {
1000
						$donation_amount = $price['_give_amount'];
1001
					}
1002
				}
1003
				// Fallback to the lowest price point.
1004
				if ( $donation_amount == '' ) {
1005
					$donation_amount  = give_get_lowest_price_option( $donation->ID );
1006
					$args['price_id'] = give_get_lowest_price_id( $donation->ID );
1007
				}
1008
			} else {
1009
				// Simple form price.
1010
				$donation_amount = give_get_form_price( $donation->ID );
1011
			}
1012
		}
1013
1014
		// Sanitizing the price here so we don't have a dozen calls later.
1015
		$donation_amount = give_maybe_sanitize_amount( $donation_amount );
1016
		$total           = round( $donation_amount, give_currency_decimal_filter() );
1017
1018
		// Add Options.
1019
		$default_options = array();
1020
		if ( false !== $args['price_id'] ) {
1021
			$default_options['price_id'] = (int) $args['price_id'];
1022
		}
1023
		$options = wp_parse_args( $options, $default_options );
1024
1025
		// Do not allow totals to go negative.
1026
		if ( $total < 0 ) {
1027
			$total = 0;
1028
		}
1029
1030
		$donation = array(
1031
			'name'     => $donation->post_title,
1032
			'id'       => $donation->ID,
1033
			'price'    => round( $total, give_currency_decimal_filter() ),
1034
			'subtotal' => round( $total, give_currency_decimal_filter() ),
1035
			'price_id' => $args['price_id'],
1036
			'action'   => 'add',
1037
			'options'  => $options,
1038
		);
1039
1040
		$this->pending['donations'][] = $donation;
1041
1042
		$this->increase_subtotal( $total );
1043
1044
		return true;
1045
1046
	}
1047
1048
	/**
1049
	 * Remove a donation from the payment
1050
	 *
1051
	 * @since  1.5
1052
	 * @access public
1053
	 *
1054
	 * @param  int   $form_id The form ID to remove
1055
	 * @param  array $args    Arguments to pass to identify (quantity, amount, price_id)
1056
	 *
1057
	 * @return bool           If the item was removed or not
1058
	 */
1059
	public function remove_donation( $form_id, $args = array() ) {
1060
1061
		// Set some defaults.
1062
		$defaults = array(
1063
			'quantity' => 1,
1064
			'price'    => false,
1065
			'price_id' => false,
1066
		);
1067
		$args     = wp_parse_args( $args, $defaults );
1068
1069
		$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...
1070
1071
		// Bail if this post isn't a valid give donation form.
1072
		if ( ! $form || $form->post_type !== 'give_forms' ) {
0 ignored issues
show
introduced by
Found "!== '". Use Yoda Condition checks, you must
Loading history...
1073
			return false;
1074
		}
1075
1076
		$pending_args             = $args;
1077
		$pending_args['id']       = $form_id;
1078
		$pending_args['amount']   = $this->total;
1079
		$pending_args['price_id'] = false !== $args['price_id'] ? (int) $args['price_id'] : false;
1080
		$pending_args['quantity'] = $args['quantity'];
1081
		$pending_args['action']   = 'remove';
1082
1083
		$this->pending['donations'][] = $pending_args;
1084
1085
		$this->decrease_subtotal( $this->total );
1086
1087
		return true;
1088
	}
1089
1090
1091
	/**
1092
	 * Add a note to a payment
1093
	 *
1094
	 * @since  1.5
1095
	 * @access public
1096
	 *
1097
	 * @param  string $note The note to add
1098
	 *
1099
	 * @return bool           If the note was specified or not
1100
	 */
1101
	public function add_note( $note = false ) {
1102
		// Bail if no note specified.
1103
		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...
1104
			return false;
1105
		}
1106
1107
		give_insert_payment_note( $this->ID, $note );
1108
	}
1109
1110
	/**
1111
	 * Increase the payment's subtotal
1112
	 *
1113
	 * @since  1.5
1114
	 * @access private
1115
	 *
1116
	 * @param  float $amount The amount to increase the payment subtotal by.
1117
	 *
1118
	 * @return void
1119
	 */
1120
	private function increase_subtotal( $amount = 0.00 ) {
1121
		$amount         = (float) $amount;
1122
		$this->subtotal += $amount;
1123
1124
		$this->recalculate_total();
1125
	}
1126
1127
	/**
1128
	 * Decrease the payment's subtotal.
1129
	 *
1130
	 * @since  1.5
1131
	 * @access private
1132
	 *
1133
	 * @param  float $amount The amount to decrease the payment subtotal by.
1134
	 *
1135
	 * @return void
1136
	 */
1137
	private function decrease_subtotal( $amount = 0.00 ) {
1138
		$amount         = (float) $amount;
1139
		$this->subtotal -= $amount;
1140
1141
		if ( $this->subtotal < 0 ) {
1142
			$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...
1143
		}
1144
1145
		$this->recalculate_total();
1146
	}
1147
1148
	/**
1149
	 * Set or update the total for a payment.
1150
	 *
1151
	 * @since  1.5
1152
	 * @access private
1153
	 *
1154
	 * @return void
1155
	 */
1156
	private function recalculate_total() {
1157
		$this->total = $this->subtotal;
1158
	}
1159
1160
	/**
1161
	 * Set the payment status and run any status specific changes necessary.
1162
	 *
1163
	 * @since  1.5
1164
	 * @access public
1165
	 *
1166
	 * @param  string|bool $status The status to set the payment to.
1167
	 *
1168
	 * @return bool   $updated Returns if the status was successfully updated.
1169
	 */
1170
	public function update_status( $status = false ) {
1171
1172
		// standardize the 'complete(d)' status.
1173
		if ( $status == 'completed' || $status == 'complete' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
1174
			$status = 'publish';
1175
		}
1176
1177
		$old_status = ! empty( $this->old_status ) ? $this->old_status : false;
1178
1179
		if ( $old_status === $status ) {
1180
			return false; // Don't permit status changes that aren't changes.
1181
		}
1182
1183
		$do_change = apply_filters( 'give_should_update_payment_status', true, $this->ID, $status, $old_status );
1184
1185
		$updated = false;
1186
1187
		if ( $do_change ) {
1188
1189
			/**
1190
			 * Fires before changing payment status.
1191
			 *
1192
			 * @since 1.5
1193
			 *
1194
			 * @param int    $payment_id Payments ID.
1195
			 * @param string $status     The new status.
1196
			 * @param string $old_status The old status.
1197
			 */
1198
			do_action( 'give_before_payment_status_change', $this->ID, $status, $old_status );
1199
1200
			$update_fields = array(
1201
				'ID'          => $this->ID,
1202
				'post_status' => $status,
1203
				'edit_date'   => current_time( 'mysql' ),
1204
			);
1205
1206
			$updated = wp_update_post( apply_filters( 'give_update_payment_status_fields', $update_fields ) );
1207
1208
			$all_payment_statuses  = give_get_payment_statuses();
1209
			$this->status_nicename = array_key_exists( $status, $all_payment_statuses ) ? $all_payment_statuses[ $status ] : ucfirst( $status );
1210
1211
			// Process any specific status functions.
1212
			switch ( $status ) {
1213
				case 'refunded':
1214
					$this->process_refund();
1215
					break;
1216
				case 'failed':
1217
					$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...
1218
					break;
1219
				case 'pending':
1220
					$this->process_pending();
1221
					break;
1222
				case 'cancelled':
1223
					$this->process_cancelled();
1224
					break;
1225
				case 'revoked':
1226
					$this->process_revoked();
1227
					break;
1228
			}
1229
1230
			/**
1231
			 * Fires after changing payment status.
1232
			 *
1233
			 * @since 1.5
1234
			 *
1235
			 * @param int    $payment_id Payment ID.
1236
			 * @param string $status     The new status.
1237
			 * @param string $old_status The old status.
1238
			 */
1239
			do_action( 'give_update_payment_status', $this->ID, $status, $old_status );
1240
1241
		}// End if().
1242
1243
		return $updated;
1244
1245
	}
1246
1247
	/**
1248
	 * Change the status of the payment to refunded, and run the necessary changes
1249
	 *
1250
	 * @since  1.5
1251
	 * @access public
1252
	 *
1253
	 * @return void
1254
	 */
1255
	public function refund() {
1256
		$this->old_status        = $this->status;
1257
		$this->status            = 'refunded';
1258
		$this->pending['status'] = $this->status;
1259
1260
		$this->save();
1261
	}
1262
1263
	/**
1264
	 * Get a post meta item for the payment
1265
	 *
1266
	 * @since  1.5
1267
	 * @access public
1268
	 *
1269
	 * @param  string  $meta_key The Meta Key
1270
	 * @param  boolean $single   Return single item or array
1271
	 *
1272
	 * @return mixed             The value from the post meta
1273
	 */
1274
	public function get_meta( $meta_key = '_give_payment_meta', $single = true ) {
1275
1276
		$meta = give_get_meta( $this->ID, $meta_key, $single );
1277
1278
		/**
1279
		 * Filter the specific meta key value.
1280
		 *
1281
		 * @since 1.5
1282
		 */
1283
		$meta = apply_filters( "give_get_payment_meta_{$meta_key}", $meta, $this->ID );
1284
1285
		// Security check.
1286 View Code Duplication
		if ( is_serialized( $meta ) ) {
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...
1287
			preg_match( '/[oO]\s*:\s*\d+\s*:\s*"\s*(?!(?i)(stdClass))/', $meta, $matches );
1288
			if ( ! empty( $matches ) ) {
1289
				$meta = array();
1290
			}
1291
		}
1292
1293
		/**
1294
		 * Filter the all meta keys.
1295
		 *
1296
		 * @since 1.5
1297
		 */
1298
		return apply_filters( 'give_get_payment_meta', $meta, $this->ID, $meta_key );
1299
	}
1300
1301
	/**
1302
	 * Update the post meta
1303
	 *
1304
	 * @since  1.5
1305
	 * @access public
1306
	 *
1307
	 * @param  string $meta_key   The meta key to update
1308
	 * @param  string $meta_value The meta value
1309
	 * @param  string $prev_value Previous meta value
1310
	 *
1311
	 * @return int|bool           Meta ID if the key didn't exist, true on successful update, false on failure
1312
	 */
1313
	public function update_meta( $meta_key = '', $meta_value = '', $prev_value = '' ) {
1314
		if ( empty( $meta_key ) ) {
1315
			return false;
1316
		}
1317
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1318
1319
		/**
1320
		 * Filter the single meta key while updating
1321
		 *
1322
		 * @since 1.5
1323
		 */
1324
		$meta_value = apply_filters( "give_update_payment_meta_{$meta_key}", $meta_value, $this->ID );
1325
1326
		return give_update_meta( $this->ID, $meta_key, $meta_value, $prev_value );
1327
	}
1328
1329
	/**
1330
	 * When a payment is set to a status of 'refunded' process the necessary actions to reduce stats
1331
	 *
1332
	 * @since  1.5
1333
	 * @access private
1334
	 *
1335
	 * @return void
1336
	 */
1337 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...
1338
		$process_refund = true;
1339
1340
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1341
		if ( 'publish' != $this->old_status || 'refunded' != $this->status ) {
1342
			$process_refund = false;
1343
		}
1344
1345
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1346
		$process_refund = apply_filters( 'give_should_process_refund', $process_refund, $this );
1347
1348
		if ( false === $process_refund ) {
1349
			return;
1350
		}
1351
1352
		/**
1353
		 * Fires before refunding payment.
1354
		 *
1355
		 * @since 1.5
1356
		 *
1357
		 * @param Give_Payment $this Payment object.
1358
		 */
1359
		do_action( 'give_pre_refund_payment', $this );
1360
1361
		$decrease_earnings       = apply_filters( 'give_decrease_store_earnings_on_refund', true, $this );
1362
		$decrease_customer_value = apply_filters( 'give_decrease_customer_value_on_refund', true, $this );
1363
		$decrease_purchase_count = apply_filters( 'give_decrease_customer_purchase_count_on_refund', true, $this );
1364
1365
		$this->maybe_alter_stats( $decrease_earnings, $decrease_customer_value, $decrease_purchase_count );
1366
		$this->delete_sales_logs();
1367
1368
		// @todo: Refresh only range related stat cache
1369
		give_delete_donation_stats();
1370
1371
		/**
1372
		 * Fires after refunding payment.
1373
		 *
1374
		 * @since 1.5
1375
		 *
1376
		 * @param Give_Payment $this Payment object.
1377
		 */
1378
		do_action( 'give_post_refund_payment', $this );
1379
	}
1380
1381
	/**
1382
	 * Process when a payment is set to failed
1383
	 *
1384
	 * @since  1.5
1385
	 * @access private
1386
	 *
1387
	 * @return void
1388
	 */
1389
	private function process_failure() {
1390
1391
	}
1392
1393
	/**
1394
	 * Process when a payment moves to pending
1395
	 *
1396
	 * @since  1.5
1397
	 * @access private
1398
	 *
1399
	 * @return void
1400
	 */
1401 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...
1402
		$process_pending = true;
1403
1404
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1405
		if ( 'publish' != $this->old_status || 'pending' != $this->status ) {
1406
			$process_pending = false;
1407
		}
1408
1409
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1410
		$process_pending = apply_filters( 'give_should_process_pending', $process_pending, $this );
1411
1412
		if ( false === $process_pending ) {
1413
			return;
1414
		}
1415
1416
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_pending', true, $this );
1417
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_pending', true, $this );
1418
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_pending', true, $this );
1419
1420
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1421
		$this->delete_sales_logs();
1422
1423
		$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...
1424
		$this->update_meta( '_give_completed_date', '' );
1425
1426
		// @todo: Refresh only range related stat cache
1427
		give_delete_donation_stats();
1428
	}
1429
1430
	/**
1431
	 * Process when a payment moves to cancelled.
1432
	 *
1433
	 * @since  1.5
1434
	 * @access private
1435
	 *
1436
	 * @return void
1437
	 */
1438 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...
1439
		$process_cancelled = true;
1440
1441
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1442
		if ( 'publish' != $this->old_status || 'cancelled' != $this->status ) {
1443
			$process_cancelled = false;
1444
		}
1445
1446
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1447
		$process_cancelled = apply_filters( 'give_should_process_cancelled', $process_cancelled, $this );
1448
1449
		if ( false === $process_cancelled ) {
1450
			return;
1451
		}
1452
1453
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_cancelled', true, $this );
1454
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_cancelled', true, $this );
1455
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_cancelled', 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
	 * Process when a payment moves to revoked.
1469
	 *
1470
	 * @since  1.5
1471
	 * @return void
1472
	 */
1473 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...
1474
		$process_revoked = true;
1475
1476
		// If the payment was not in publish, don't decrement stats as they were never incremented.
1477
		if ( 'publish' != $this->old_status || 'revoked' != $this->status ) {
1478
			$process_revoked = false;
1479
		}
1480
1481
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1482
		$process_revoked = apply_filters( 'give_should_process_revoked', $process_revoked, $this );
1483
1484
		if ( false === $process_revoked ) {
1485
			return;
1486
		}
1487
1488
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_revoked', true, $this );
1489
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_revoked', true, $this );
1490
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_revoked', true, $this );
1491
1492
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1493
		$this->delete_sales_logs();
1494
1495
		$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...
1496
		$this->update_meta( '_give_completed_date', '' );
1497
1498
		// @todo: Refresh only range related stat cache
1499
		give_delete_donation_stats();
1500
	}
1501
1502
	/**
1503
	 * Used during the process of moving to refunded or pending, to decrement stats
1504
	 *
1505
	 * @since  1.5
1506
	 * @access private
1507
	 *
1508
	 * @param  bool $alter_store_earnings          If the method should alter the store earnings
1509
	 * @param  bool $alter_customer_value          If the method should reduce the donor value
1510
	 * @param  bool $alter_customer_purchase_count If the method should reduce the donor's purchase count
1511
	 *
1512
	 * @return void
1513
	 */
1514
	private function maybe_alter_stats( $alter_store_earnings, $alter_customer_value, $alter_customer_purchase_count ) {
1515
1516
		give_undo_donation( $this->ID );
1517
1518
		// Decrease store earnings.
1519
		if ( true === $alter_store_earnings ) {
1520
			give_decrease_total_earnings( $this->total );
1521
		}
1522
1523
		// Decrement the stats for the donor.
1524
		if ( ! empty( $this->customer_id ) ) {
1525
1526
			$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...
1527
1528
			if ( true === $alter_customer_value ) {
1529
				$donor->decrease_value( $this->total );
1530
			}
1531
1532
			if ( true === $alter_customer_purchase_count ) {
1533
				$donor->decrease_donation_count();
1534
			}
1535
		}
1536
1537
	}
1538
1539
	/**
1540
	 * Delete sales logs for this donation
1541
	 *
1542
	 * @since  1.5
1543
	 * @access private
1544
	 *
1545
	 * @return void
1546
	 */
1547
	private function delete_sales_logs() {
1548
		// Remove related sale log entries.
1549
		Give()->logs->delete_logs( $this->ID );
1550
	}
1551
1552
	/**
1553
	 * Setup functions only, these are not to be used by developers.
1554
	 * These functions exist only to allow the setup routine to be backwards compatible with our old
1555
	 * helper functions.
1556
	 *
1557
	 * These will run whenever setup_payment is called, which should only be called once.
1558
	 * To update an attribute, update it directly instead of re-running the setup routine
1559
	 */
1560
1561
	/**
1562
	 * Setup the payment completed date
1563
	 *
1564
	 * @since  1.5
1565
	 * @access private
1566
	 *
1567
	 * @return string The date the payment was completed
1568
	 */
1569
	private function setup_completed_date() {
1570
		$payment = get_post( $this->ID );
1571
1572
		if ( 'pending' == $payment->post_status || 'preapproved' == $payment->post_status ) {
1573
			return false; // This payment was never completed.
1574
		}
1575
1576
		$date = ( $date = $this->get_meta( '_give_completed_date', true ) ) ? $date : $payment->modified_date;
1577
1578
		return $date;
1579
	}
1580
1581
	/**
1582
	 * Setup the payment mode
1583
	 *
1584
	 * @since  1.5
1585
	 * @access private
1586
	 *
1587
	 * @return string The payment mode
1588
	 */
1589
	private function setup_mode() {
1590
		return $this->get_meta( '_give_payment_mode' );
1591
	}
1592
1593
	/**
1594
	 * Setup the payment import data
1595
	 *
1596
	 * @since  1.8.13
1597
	 * @access private
1598
	 *
1599
	 * @return bool The payment import
1600
	 */
1601
	private function setup_import() {
1602
		return (bool) $this->get_meta( '_give_payment_import' );
1603
	}
1604
1605
	/**
1606
	 * Setup the payment total
1607
	 *
1608
	 * @since  1.5
1609
	 * @access private
1610
	 *
1611
	 * @return float The payment total
1612
	 */
1613
	private function setup_total() {
1614
		$amount = $this->get_meta( '_give_payment_total', true );
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
1726
		$donor   = Give()->customers->get_customer_by( 'id', $this->customer_id );
1727
		$user_id = $donor ? absint( $donor->user_id ) : 0;
1728
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1729
1730
		return $user_id;
1731
	}
1732
1733
	/**
1734
	 * Setup the email address for the donation.
1735
	 *
1736
	 * @since  1.5
1737
	 * @since  2.0 Set email from _give_payment_donor_email meta key
1738
	 *
1739
	 * @access private
1740
	 *
1741
	 * @return string The email address for the payment.
1742
	 */
1743
	private function setup_email() {
1744
		$email = $this->get_meta( '_give_payment_donor_email', true );
1745
1746
		if ( empty( $email ) && $this->customer_id ) {
1747
			$email = Give()->donors->get_column( 'email', $this->customer_id );
1748
		}
1749
1750
		return $email;
1751
	}
1752
1753
	/**
1754
	 * Setup the user info.
1755
	 *
1756
	 * @since  1.5
1757
	 * @access private
1758
	 *
1759
	 * @return array The user info associated with the payment.
1760
	 */
1761
	private function setup_user_info() {
1762
		$defaults = array(
1763
			'first_name' => $this->first_name,
1764
			'last_name'  => $this->last_name,
1765
		);
1766
1767
		$user_info = isset( $this->payment_meta['user_info'] ) ? $this->payment_meta['user_info'] : array();
1768
1769 View Code Duplication
		if ( is_serialized( $user_info ) ) {
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...
1770
			preg_match( '/[oO]\s*:\s*\d+\s*:\s*"\s*(?!(?i)(stdClass))/', $user_info, $matches );
1771
			if ( ! empty( $matches ) ) {
1772
				$user_info = array();
1773
			}
1774
		}
1775
1776
		$user_info = wp_parse_args( $user_info, $defaults );
1777
1778
		if ( empty( $user_info ) ) {
1779
			// Get the donor, but only if it's been created.
1780
			$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...
1781
1782
			if ( $donor->id > 0 ) {
1783
				$user_info = array(
1784
					'first_name' => $donor->get_first_name(),
1785
					'last_name'  => $donor->get_last_name(),
1786
					'email'      => $donor->email,
1787
					'discount'   => 'none',
1788
				);
1789
			}
1790
		} else {
1791
			// Get the donor, but only if it's been created.
1792
			$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...
1793
1794
			if ( $donor->id > 0 ) {
1795
				foreach ( $user_info as $key => $value ) {
1796
					if ( ! empty( $value ) ) {
1797
						continue;
1798
					}
1799
1800
					switch ( $key ) {
1801
						case 'first_name':
1802
							$user_info[ $key ] = $donor->get_first_name();
1803
							break;
1804
1805
						case 'last_name':
1806
							$user_info[ $key ] = $donor->get_last_name();
1807
							break;
1808
1809
						case 'email':
1810
							$user_info[ $key ] = $donor->email;
1811
							break;
1812
					}
1813
				}
1814
			}
1815
		}// End if().
1816
1817
		return $user_info;
1818
1819
	}
1820
1821
	/**
1822
	 * Setup the Address for the payment.
1823
	 *
1824
	 * @since  1.5
1825
	 * @access private
1826
	 *
1827
	 * @return array The Address information for the payment.
1828
	 */
1829
	private function setup_address() {
1830
		$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...
1831
		$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...
1832
		$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...
1833
		$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...
1834
		$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...
1835
		$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...
1836
1837
		return $address;
1838
	}
1839
1840
	/**
1841
	 * Setup the form title.
1842
	 *
1843
	 * @since  1.5
1844
	 * @access private
1845
	 *
1846
	 * @return string The Form Title.
1847
	 */
1848
	private function setup_form_title() {
1849
1850
		$form_id = $this->get_meta( '_give_payment_form_title', true );
1851
1852
		return $form_id;
1853
	}
1854
1855
	/**
1856
	 * Setup the form ID.
1857
	 *
1858
	 * @since  1.5
1859
	 * @access private
1860
	 *
1861
	 * @return int The Form ID
1862
	 */
1863
	private function setup_form_id() {
1864
1865
		$form_id = $this->get_meta( '_give_payment_form_id', true );
1866
1867
		return $form_id;
1868
	}
1869
1870
	/**
1871
	 * Setup the price ID.
1872
	 *
1873
	 * @since  1.5
1874
	 * @access private
1875
	 *
1876
	 * @return int The Form Price ID.
1877
	 */
1878
	private function setup_price_id() {
1879
		$price_id = $this->get_meta( '_give_payment_price_id', true );
1880
1881
		return $price_id;
1882
	}
1883
1884
	/**
1885
	 * Setup the payment key.
1886
	 *
1887
	 * @since  1.5
1888
	 * @access private
1889
	 *
1890
	 * @return string The Payment Key.
1891
	 */
1892
	private function setup_payment_key() {
1893
		$key = $this->get_meta( '_give_payment_purchase_key', true );
1894
1895
		return $key;
1896
	}
1897
1898
	/**
1899
	 * Setup the payment number.
1900
	 *
1901
	 * @since  1.5
1902
	 * @access private
1903
	 *
1904
	 * @return int|string Integer by default, or string if sequential order numbers is enabled.
1905
	 */
1906
	private function setup_payment_number() {
1907
		$number = $this->ID;
1908
1909
		if ( give_get_option( 'enable_sequential' ) ) {
1910
1911
			$number = $this->get_meta( '_give_payment_number', true );
1912
1913
			if ( ! $number ) {
1914
1915
				$number = $this->ID;
1916
1917
			}
1918
		}
1919
1920
		return $number;
1921
	}
1922
1923
	/**
1924
	 * Converts this object into an array for special cases.
1925
	 *
1926
	 * @access public
1927
	 *
1928
	 * @return array The payment object as an array.
1929
	 */
1930
	public function array_convert() {
1931
		return get_object_vars( $this );
1932
	}
1933
1934
1935
	/**
1936
	 * Flag to check if donation is completed or not.
1937
	 *
1938
	 * @since  1.8
1939
	 * @access public
1940
	 *
1941
	 * @return bool
1942
	 */
1943
	public function is_completed() {
1944
		return ( 'publish' === $this->status && $this->completed_date );
1945
	}
1946
1947
	/**
1948
	 * Retrieve payment completion date.
1949
	 *
1950
	 * @since  1.5
1951
	 * @access private
1952
	 *
1953
	 * @return string Date payment was completed.
1954
	 */
1955
	private function get_completed_date() {
1956
		return apply_filters( 'give_payment_completed_date', $this->completed_date, $this->ID, $this );
1957
	}
1958
1959
	/**
1960
	 * Retrieve payment subtotal.
1961
	 *
1962
	 * @since  1.5
1963
	 * @access private
1964
	 *
1965
	 * @return float Payment subtotal.
1966
	 */
1967
	private function get_subtotal() {
1968
		return apply_filters( 'give_get_payment_subtotal', $this->subtotal, $this->ID, $this );
1969
	}
1970
1971
	/**
1972
	 * Retrieve payment currency.
1973
	 *
1974
	 * @since  1.5
1975
	 * @access private
1976
	 *
1977
	 * @return string Payment currency code.
1978
	 */
1979
	private function get_currency() {
1980
		return apply_filters( 'give_payment_currency_code', $this->currency, $this->ID, $this );
1981
	}
1982
1983
	/**
1984
	 * Retrieve payment gateway.
1985
	 *
1986
	 * @since  1.5
1987
	 * @access private
1988
	 *
1989
	 * @return string Gateway used.
1990
	 */
1991
	private function get_gateway() {
1992
		return apply_filters( 'give_payment_gateway', $this->gateway, $this->ID, $this );
1993
	}
1994
1995
	/**
1996
	 * Retrieve donation ID.
1997
	 *
1998
	 * @since  1.5
1999
	 * @access private
2000
	 *
2001
	 * @return string Donation ID from merchant processor.
2002
	 */
2003
	private function get_transaction_id() {
2004
		return apply_filters( 'give_get_payment_transaction_id', $this->transaction_id, $this->ID, $this );
2005
	}
2006
2007
	/**
2008
	 * Retrieve payment IP
2009
	 *
2010
	 * @since  1.5
2011
	 * @access private
2012
	 *
2013
	 * @return string Payment IP address
2014
	 */
2015
	private function get_ip() {
2016
		return apply_filters( 'give_payment_user_ip', $this->ip, $this->ID, $this );
2017
	}
2018
2019
	/**
2020
	 * Retrieve payment donor ID.
2021
	 *
2022
	 * @since  1.5
2023
	 * @access private
2024
	 *
2025
	 * @return int Payment donor ID.
2026
	 */
2027
	private function get_donor_id() {
2028
		return apply_filters( 'give_payment_customer_id', $this->customer_id, $this->ID, $this );
2029
	}
2030
2031
	/**
2032
	 * Retrieve payment user ID.
2033
	 *
2034
	 * @since  1.5
2035
	 * @access private
2036
	 *
2037
	 * @return int Payment user ID.
2038
	 */
2039
	private function get_user_id() {
2040
		return apply_filters( 'give_payment_user_id', $this->user_id, $this->ID, $this );
2041
	}
2042
2043
	/**
2044
	 * Retrieve payment email.
2045
	 *
2046
	 * @since  1.5
2047
	 * @access private
2048
	 *
2049
	 * @return string Payment donor email.
2050
	 */
2051
	private function get_email() {
2052
		return apply_filters( 'give_payment_user_email', $this->email, $this->ID, $this );
2053
	}
2054
2055
	/**
2056
	 * Retrieve payment user info.
2057
	 *
2058
	 * @since  1.5
2059
	 * @access private
2060
	 *
2061
	 * @return array Payment user info.
2062
	 */
2063
	private function get_user_info() {
2064
		return apply_filters( 'give_payment_meta_user_info', $this->user_info, $this->ID, $this );
2065
	}
2066
2067
	/**
2068
	 * Retrieve payment billing address.
2069
	 *
2070
	 * @since  1.5
2071
	 * @access private
2072
	 *
2073
	 * @return array Payment billing address.
2074
	 */
2075
	private function get_address() {
2076
		return apply_filters( 'give_payment_address', $this->address, $this->ID, $this );
2077
	}
2078
2079
	/**
2080
	 * Retrieve payment key.
2081
	 *
2082
	 * @since  1.5
2083
	 * @access private
2084
	 *
2085
	 * @return string Payment key.
2086
	 */
2087
	private function get_key() {
2088
		return apply_filters( 'give_payment_key', $this->key, $this->ID, $this );
2089
	}
2090
2091
	/**
2092
	 * Retrieve payment form id
2093
	 *
2094
	 * @since  1.5
2095
	 * @access private
2096
	 *
2097
	 * @return string Payment form id
2098
	 */
2099
	private function get_form_id() {
2100
		return apply_filters( 'give_payment_form_id', $this->form_id, $this->ID, $this );
2101
	}
2102
2103
	/**
2104
	 * Retrieve payment number
2105
	 *
2106
	 * @since  1.5
2107
	 * @access private
2108
	 *
2109
	 * @return int|string Payment number
2110
	 */
2111
	private function get_number() {
2112
		return apply_filters( 'give_payment_number', $this->number, $this->ID, $this );
2113
	}
2114
}
2115