Test Failed
Push — master ( cd44a0...d8bbfb )
by Devin
01:14
created

Give_Payment::update_payment_setup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 2
cts 2
cp 1
crap 1
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     $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     $post_date
38
 * @property string     $status
39
 * @property string     $email
40
 * @property array      $payment_meta
41
 * @property string     $customer_id
42
 * @property string     $donor_id
43
 * @property string     $completed_date
44
 * @property string     $currency
45
 * @property string     $ip
46
 * @property array      $user_info
47
 * @property string     $gateway
48
 * @property string     $user_id
49
 * @property string     $first_name
50
 * @property string     $last_name
51
 * @property string     $parent_payment
52
 * @property string     $transaction_id
53
 * @property string     $old_status
54
 *
55
 * @since 1.5
56
 */
57
final class Give_Payment {
58
59
	/**
60
	 * The Payment ID.
61
	 *
62
	 * @since  1.5
63
	 *
64
	 * @var    int
65
	 */
66
	public $ID = 0;
67
68
	/**
69
	 * Protected non-read $_ID.
70
	 *
71
	 * @var int
72
	 */
73
	protected $_ID = 0;
74
75
	/**
76
	 * Identify if the payment is a new one or existing.
77
	 *
78
	 * @since  1.5
79
	 * @access protected
80
	 *
81
	 * @var    boolean
82
	 */
83
	protected $new = false;
84
85
	/**
86
	 * The Payment number (for use with sequential payments).
87
	 *
88
	 * @since  1.5
89
	 * @access protected
90
	 *
91
	 * @var    string
92
	 */
93
	protected $number = '';
94
95
	/**
96
	 * The Gateway mode the payment was made in.
97
	 *
98
	 * @since  1.5
99
	 * @access protected
100
	 *
101
	 * @var    string
102
	 */
103
	protected $mode = 'live';
104
105
	/**
106
	 * Is donations is Import or not.
107
	 *
108
	 * @since  1.8.13
109
	 * @access protected
110
	 *
111
	 * @var    bool
112
	 */
113
	protected $import = false;
114
115
	/**
116
	 * The unique donation payment key.
117
	 *
118
	 * @since  1.5
119
	 * @access protected
120
	 *
121
	 * @var    string
122
	 */
123
	protected $key = '';
124
125
	/**
126
	 * The Donation Form Title
127
	 *
128
	 * @since  1.5
129
	 * @access protected
130
	 *
131
	 * @var    string
132
	 */
133
	protected $form_title = 0;
134
135
	/**
136
	 * The Donation Form ID
137
	 *
138
	 * @since  1.5
139
	 * @access protected
140
	 *
141
	 * @var    string
142
	 */
143
	protected $form_id = 0;
144
145
	/**
146
	 * The Donation Form Price ID
147
	 *
148
	 * @since  1.5
149
	 * @access protected
150
	 *
151
	 * @var    string|int
152
	 */
153
	protected $price_id = 0;
154
155
	/**
156
	 * The total amount of the donation payment.
157
	 *
158
	 * @since  1.5
159
	 * @access protected
160
	 *
161
	 * @var    float
162
	 */
163
	protected $total = 0.00;
164
165
	/**
166
	 * The Subtotal fo the payment.
167
	 *
168
	 * @since  1.5
169
	 * @access protected
170
	 *
171
	 * @var    float
172
	 */
173
	protected $subtotal = 0;
174
175
	/**
176
	 * The date the payment was created
177
	 *
178
	 * @since  1.5
179
	 * @access protected
180
	 *
181
	 * @var    string
182
	 */
183
	protected $date = '';
184
185
	/**
186
	 * The date the payment post was created.
187
	 *
188
	 * @var string
189
	 */
190
	protected $post_date = '';
191
192
	/**
193
	 * The date the payment was marked as 'complete'.
194
	 *
195
	 * @since  1.5
196
	 * @access protected
197
	 *
198
	 * @var    string
199
	 */
200
	protected $completed_date = '';
201
202
	/**
203
	 * The status of the donation payment.
204
	 *
205
	 * @since  1.5
206
	 * @access protected
207
	 *
208
	 * @var    string
209
	 */
210
	protected $status = 'pending';
211
212
	/**
213
	 * @var string
214
	 */
215
	protected $post_status = 'pending'; // Same as $status but here for backwards compat
216
217
	/**
218
	 * When updating, the old status prior to the change
219
	 *
220
	 * @since  1.5
221
	 * @access protected
222
	 *
223
	 * @var    string
224
	 */
225
	protected $old_status = '';
226
227
	/**
228
	 * The display name of the current payment status.
229
	 *
230
	 * @since  1.5
231
	 * @access protected
232
	 *
233
	 * @var    string
234
	 */
235
	protected $status_nicename = '';
236
237
	/**
238
	 * The donor ID that made the payment.
239
	 *
240
	 * @since  1.5
241
	 * @access protected
242
	 *
243
	 * @var    integer
244
	 */
245
	protected $customer_id = null;
246
247
	/**
248
	 * The Donor ID (if logged in) that made the payment
249
	 *
250
	 * @since  1.8.13
251
	 * @access protected
252
	 *
253
	 * @var    integer
254
	 */
255
	protected $donor_id = 0;
256
257
	/**
258
	 * The User ID (if logged in) that made the payment
259
	 *
260
	 * @since  1.5
261
	 * @access protected
262
	 *
263
	 * @var    integer
264
	 */
265
	protected $user_id = 0;
266
267
	/**
268
	 * The first name of the payee
269
	 *
270
	 * @since  1.5
271
	 * @access protected
272
	 *
273
	 * @var    string
274
	 */
275
	protected $first_name = '';
276
277
	/**
278
	 * The last name of the payee
279
	 *
280
	 * @since  1.5
281
	 * @access protected
282
	 *
283
	 * @var    string
284
	 */
285
	protected $last_name = '';
286
287
	/**
288
	 * The email used for the payment
289
	 *
290
	 * @since  1.5
291
	 * @access protected
292
	 *
293
	 * @var    string
294
	 */
295
	protected $email = '';
296
297
	/**
298 52
	 * Legacy (not to be accessed) array of user information
299
	 *
300 52
	 * @since  1.5
301 52
	 * @access private
302
	 *
303
	 * @var    array
304 52
	 */
305 52
	private $user_info = array();
306
307
	/**
308
	 * Legacy (not to be accessed) payment meta array
309
	 *
310
	 * @since  1.5
311
	 * @access private
312
	 *
313
	 * @var    array
314
	 */
315
	private $payment_meta = array();
316 52
317
	/**
318 52
	 * The physical address used for the payment if provided
319
	 *
320 52
	 * @since  1.5
321
	 * @access protected
322 52
	 *
323
	 * @var    array
324 52
	 */
325
	protected $address = array();
326
327
	/**
328 52
	 * The transaction ID returned by the gateway
329
	 *
330
	 * @since  1.5
331
	 * @access protected
332
	 *
333
	 * @var    string
334
	 */
335
	protected $transaction_id = '';
336
337
	/**
338
	 * IP Address payment was made from
339
	 *
340
	 * @since  1.5
341 52
	 * @access protected
342 52
	 *
343
	 * @var    string
344 52
	 */
345 52
	protected $ip = '';
346 52
347
	/**
348 52
	 * The gateway used to process the payment
349 52
	 *
350 52
	 * @since  1.5
351
	 * @access protected
352 52
	 *
353 52
	 * @var    string
354 52
	 */
355 52
	protected $gateway = '';
356
357
	/**
358
	 * The the payment was made with
359
	 *
360
	 * @since  1.5
361
	 * @access protected
362
	 *
363
	 * @var    string
364
	 */
365
	protected $currency = '';
366 42
367 42
	/**
368 42
	 * Array of items that have changed since the last save() was run.
369
	 * This is for internal use, to allow fewer update_payment_meta calls to be run.
370
	 *
371
	 * @since  1.5
372
	 * @access private
373
	 *
374
	 * @var    array
375
	 */
376
	private $pending;
377
378
	/**
379
	 * The parent payment (if applicable)
380
	 *
381
	 * @since  1.5
382
	 * @access protected
383 52
	 *
384 52
	 * @var    integer
385
	 */
386 52
	protected $parent_payment = 0;
387
388
	/**
389
	 * Setup the Give Payments class
390 52
	 *
391
	 * @since  1.5
392 52
	 * @access public
393 7
	 *
394
	 * @param  int|bool $payment_id A given payment
395
	 *
396 52
	 * @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...
397
	 */
398
	public function __construct( $payment_id = false ) {
399
400
		if ( empty( $payment_id ) ) {
401 52
			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...
402
		}
403
404 52
		$this->setup_payment( $payment_id );
0 ignored issues
show
Bug introduced by
It seems like $payment_id defined by parameter $payment_id on line 398 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...
405
	}
406
407 52
	/**
408
	 * Magic GET function.
409
	 *
410 52
	 * @since  1.5
411
	 * @access public
412
	 *
413 52
	 * @param  string $key The property.
414 52
	 *
415 52
	 * @return mixed        The value.
416 52
	 */
417 52
	public function __get( $key ) {
418 52
419 52
		if ( method_exists( $this, 'get_' . $key ) ) {
420
421 52
			$value = call_user_func( array( $this, 'get_' . $key ) );
422 52
423
		} else {
424
425 52
			$value = $this->$key;
426
427
		}
428 52
429 52
		return $value;
430 52
	}
431 52
432
	/**
433
	 * Magic SET function
434 52
	 *
435 52
	 * Sets up the pending array for the save method
436
	 *
437
	 * @since  1.5
438 52
	 * @access public
439 52
	 *
440 52
	 * @param  string $key   The property name
441 52
	 * @param  mixed  $value The value of the property
442 52
	 */
443 52
	public function __set( $key, $value ) {
444 52
		$ignore = array( '_ID' );
445 52
446
		if ( 'status' === $key ) {
447
			$this->old_status = $this->status;
448 52
		}
449 52
450 52
		if ( ! in_array( $key, $ignore ) ) {
451 52
			$this->pending[ $key ] = $value;
452 52
		}
453
454
		if ( '_ID' !== $key ) {
455 52
			$this->$key = $value;
456
		}
457 52
	}
458
459
	/**
460
	 * Magic ISSET function, which allows empty checks on protected elements
461
	 *
462
	 * @since  1.5
463
	 * @access public
464
	 *
465
	 * @param  string $name The attribute to get
466 52
	 *
467
	 * @return boolean|null       If the item is set or not
468
	 */
469 52
	public function __isset( $name ) {
470 52
		if ( property_exists( $this, $name ) ) {
471 31
			return false === empty( $this->$name );
472 52
		} else {
473
			return null;
474 22
		}
475 21
	}
476 21
477
	/**
478
	 * Setup payment properties
479 52
	 *
480
	 * @since  1.5
481 1
	 * @access private
482 1
	 *
483 1
	 * @param  int $payment_id The payment ID
484 1
	 *
485
	 * @return bool            If the setup was successful or not
486
	 */
487 52
	private function setup_payment( $payment_id ) {
488
		$this->pending = array();
489 1
490 1
		if ( empty( $payment_id ) ) {
491
			return false;
492 1
		}
493
494
		$payment = get_post( absint( $payment_id ) );
495 52
496 52
		if ( ! $payment || is_wp_error( $payment ) ) {
497 52
			return false;
498 52
		}
499 52
500 52
		if ( 'give_payment' !== $payment->post_type ) {
501 52
			return false;
502 52
		}
503
504 52
		/**
505 52
		 * Fires before payment setup.
506 52
		 *
507 52
		 * Allow extensions to perform actions before the payment is loaded.
508 52
		 *
509 52
		 * @since 1.5
510 52
		 *
511 52
		 * @param Give_Payment $this       Payment object.
512 52
		 * @param int          $payment_id The ID of the payment.
513
		 */
514 52
		do_action( 'give_pre_setup_payment', $this, $payment_id );
515 52
516 52
		// Get payment from cache.
517 52
		$donation_vars = Give_Cache::get_group( $payment_id, 'give-donations' );
518 52
519 52
		if ( is_null( $donation_vars ) ) {
520 52
			// Primary Identifier.
521 52
			$this->ID = absint( $payment_id );
522
523
			// Protected ID that can never be changed.
524 52
			$this->_ID = absint( $payment_id );
525
526 52
			// We have a payment, get the generic payment_meta item to reduce calls to it.
527
			$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...
528 52
529 52
			// Status and Dates.
530
			$this->date           = $payment->post_date;
531 52
			$this->post_date      = $payment->post_date;
532
			$this->completed_date = $this->setup_completed_date();
533 52
			$this->status         = $payment->post_status;
534
			$this->post_status    = $this->status;
535
			$this->mode           = $this->setup_mode();
536
			$this->import         = $this->setup_import();
537 52
			$this->parent_payment = $payment->post_parent;
538 52
539 52
			$all_payment_statuses  = give_get_payment_statuses();
540
			$this->status_nicename = array_key_exists( $this->status, $all_payment_statuses ) ? $all_payment_statuses[ $this->status ] : ucfirst( $this->status );
541 52
542
			// Currency Based.
543
			$this->total    = $this->setup_total();
544 52
			$this->subtotal = $this->setup_subtotal();
545 52
			$this->currency = $this->setup_currency();
546 52
547 52
			// Gateway based.
548
			$this->gateway        = $this->setup_gateway();
549 52
			$this->transaction_id = $this->setup_transaction_id();
550
551 52
			// User based.
552
			$this->ip          = $this->setup_ip();
553 52
			$this->customer_id = $this->setup_donor_id(); // Backward compatibility
554 52
			$this->donor_id    = $this->setup_donor_id();
555 52
			$this->user_id     = $this->setup_user_id();
556
			$this->email       = $this->setup_email();
557 52
			$this->user_info   = $this->setup_user_info();
558 52
			$this->address     = $this->setup_address();
559
			$this->first_name  = $this->user_info['first_name'];
560
			$this->last_name   = $this->user_info['last_name'];
561
562
			// Other Identifiers.
563
			$this->form_title = $this->setup_form_title();
564
			$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...
565 52
			$this->price_id   = $this->setup_price_id();
566 52
			$this->key        = $this->setup_payment_key();
567 52
			$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...
568
569 52
			Give_Cache::set_group( $this->ID, get_object_vars( $this ), 'give-donations' );
570
		} else {
571
572
			foreach ( $donation_vars as $donation_var => $value ) {
0 ignored issues
show
Bug introduced by
The expression $donation_vars of type object|integer|double|string|array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
573
				$this->$donation_var = $value;
574
			}
575
		}
576
577
		/**
578
		 * Fires after payment setup.
579
		 *
580 52
		 * Allow extensions to add items to this object via hook.
581
		 *
582 52
		 * @since 1.5
583
		 *
584
		 * @param Give_Payment $this       Payment object.
585 52
		 * @param int          $payment_id The ID of the payment.
586
		 */
587 52
		do_action( 'give_setup_payment', $this, $payment_id );
588
589 52
		return true;
590
	}
591
592 52
593
	/**
594
	 * Payment class object is storing various meta value in object parameter.
595 52
	 * So if user is updating payment meta but not updating payment object, then payment meta values will not reflect/changes on payment meta automatically
596
	 * 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.
597
	 * To prevent that user can use this function after updating any payment meta value ( in bulk or single update ).
598 52
	 *
599 1
	 * @since  1.6
600 1
	 * @access public
601
	 *
602
	 * @param  int $payment_id Payment ID.
603 52
	 *
604
	 * @return void
605 52
	 */
606 52
	public function update_payment_setup( $payment_id ) {
607
		// Delete cache.
608 52
		Give_Cache::delete_group( $this->ID,'give-donations' );
609
610
		$this->setup_payment( $payment_id );
611
	}
612 52
613
	/**
614 52
	 * Create the base of a payment.
615
	 *
616 52
	 * @since  1.5
617 52
	 * @access private
618
	 *
619 52
	 * @return int|bool False on failure, the payment ID on success.
620
	 */
621 52
	private function insert_payment() {
622
623 52
		// Construct the payment title.
624
		$payment_title = '';
625 52
		if ( ! empty( $this->first_name ) && ! empty( $this->last_name ) ) {
626
			$payment_title = $this->first_name . ' ' . $this->last_name;
627
		} elseif ( ! empty( $this->first_name ) && empty( $this->last_name ) ) {
628 1
			$payment_title = $this->first_name;
629
		} elseif ( ! empty( $this->email ) && is_email( $this->email ) ) {
630 1
			$payment_title = $this->email;
631 1
		}
632
633 1
		// Set Key.
634 1
		if ( empty( $this->key ) ) {
635 1
636
			$auth_key             = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
637 1
			$this->key            = strtolower( md5( $this->email . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'give', true ) ) );  // Unique key
638 1
			$this->pending['key'] = $this->key;
639 1
		}
640
641 1
		// Set IP.
642 1
		if ( empty( $this->ip ) ) {
643 52
644
			$this->ip            = give_get_ip();
0 ignored issues
show
Documentation Bug introduced by
It seems like give_get_ip() can also be of type array. However, the property $ip 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...
645 2
			$this->pending['ip'] = $this->ip;
646
647 2
		}
648 2
649 2
		// @todo: payment data exist here only for backward compatibility
650
		// issue: https://github.com/WordImpress/Give/issues/1132
651
		$payment_data = array(
652 2
			'price'        => $this->total,
653 2
			'date'         => $this->date,
654 2
			'user_email'   => $this->email,
655 2
			'purchase_key' => $this->key,
656
			'form_title'   => $this->form_title,
657 2
			'form_id'      => $this->form_id,
658 2
			'donor_id'     => $this->donor_id,
659
			'price_id'     => $this->price_id,
660 2
			'currency'     => $this->currency,
661 2
			'user_info'    => array(
662 2
				'id'         => $this->user_id,
663
				'email'      => $this->email,
664 2
				'first_name' => $this->first_name,
665 2
				'last_name'  => $this->last_name,
666 1
				'address'    => $this->address,
667 2
			),
668
			'status'       => $this->status,
669 2
		);
670 1
671 1
		$args = apply_filters( 'give_insert_payment_args', array(
672 1
			'post_title'    => $payment_title,
673
			'post_status'   => $this->status,
674 1
			'post_type'     => 'give_payment',
675 1
			'post_date'     => ! empty( $this->date ) ? $this->date : null,
676 2
			'post_date_gmt' => ! empty( $this->date ) ? get_gmt_from_date( $this->date ) : null,
677
			'post_parent'   => $this->parent_payment,
678 52
		), $payment_data );
679
680 52
		// Create a blank payment
681 52
		$payment_id = wp_insert_post( $args );
682
683 52
		if ( ! empty( $payment_id ) ) {
684
685
			$this->ID  = $payment_id;
686
			$this->_ID = $payment_id;
687
688
			$donor = new stdClass;
689
690
			/**
691
			 * Filter donor class after the donation is completed and before customer table is updated.
692
			 *
693
			 * @since 1.8.13
694
			 */
695
			$donor = apply_filters( 'give_update_donor_information', $donor, $payment_id, $payment_data, $args );
696
697
			if ( did_action( 'give_pre_process_donation' ) && is_user_logged_in() ) {
698
				$donor = new Give_Donor( get_current_user_id(), true );
699
700
				// Donor is logged in but used a different email to purchase with so assign to their donor record.
701
				if ( ! empty( $donor->id ) && $this->email !== $donor->email ) {
702
					$donor->add_email( $this->email );
703
				}
704
			}
705
706
			if ( empty( $donor->id ) ) {
707
				$donor = new Give_Donor( $this->email );
708
			}
709
710
			if ( empty( $donor->id ) ) {
711 52
712 52
				$donor_data = array(
713 52
					'name'    => ! is_email( $payment_title ) ? $this->first_name . ' ' . $this->last_name : '',
714
					'email'   => $this->email,
715 52
					'user_id' => $this->user_id,
716 52
				);
717 52
718
				$donor->create( $donor_data );
719 52
720 52
			}
721 52
722
			// Update Donor Meta once donor is created.
723 52
			$donor->update_meta( '_give_donor_first_name', $this->first_name );
724 20
			$donor->update_meta( '_give_donor_last_name', $this->last_name );
725 20
726
			$this->customer_id            = $donor->id;
727 52
			$this->pending['customer_id'] = $this->customer_id;
728 52
			$donor->attach_payment( $this->ID, false );
729 52
730
			$this->payment_meta = apply_filters( 'give_payment_meta', $this->payment_meta, $payment_data );
731 52
732 52
			/*
733 52
			 * _give_payment_meta backward compatibility.
734
			 *
735 52
			 * @since 2.0.1
736 52
			 */
737 52
			$custom_payment_meta = array_diff(
738
				array_map( 'maybe_serialize', $this->payment_meta ),
739 52
				array_map( 'maybe_serialize', $payment_data )
740 52
			);
741 52
742
			if( ! empty( $custom_payment_meta ) ) {
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...
743 52
				give_doing_it_wrong( '_give_payment_meta', __( 'This custom meta key deprecated. We are not using this meta key for storing payment meta but your custom meta data will be store because we added backward compatibility. Please change your logic because in future we can remove it.', 'give' ), '2.0.0' );
744 52
745 52
				$this->update_meta( '_give_payment_meta', array_map( 'maybe_unserialize', $custom_payment_meta ) );
0 ignored issues
show
Documentation introduced by
array_map('maybe_unseria..., $custom_payment_meta) is of type array, but the function expects a string.

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...
746
			}
747 52
748 52
			$this->new = true;
749 52
		}// End if().
750
751 52
		return $this->ID;
752 52
753 52
	}
754
755 52
	/**
756 52
	 * Save
757 52
	 *
758
	 * Once items have been set, an update is needed to save them to the database.
759 52
	 *
760
	 * @access public
761
	 *
762
	 * @return bool  True of the save occurred, false if it failed or wasn't needed
763 52
	 */
764 52
	public function save() {
765 52
		$saved = false;
766
767 52
		// Must have an ID.
768 52
		if ( empty( $this->ID ) ) {
769 52
770
			$payment_id = $this->insert_payment();
771 52
772 20
			if ( false === $payment_id ) {
773 20
				$saved = false;
774
			} else {
775 52
				$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...
776
			}
777 2
		}
778 2
779 2
		// Set ID if not matching.
780 2
		if ( $this->ID !== $this->_ID ) {
781
			$this->ID = $this->_ID;
782 2
		}
783 2
784
		// If we have something pending, let's save it.
785 52
		if ( ! empty( $this->pending ) ) {
786 42
787 42
			$total_increase = 0;
788
			$total_decrease = 0;
789 52
790
			foreach ( $this->pending as $key => $value ) {
791 52
792 52
				switch ( $key ) {
793 52
794
					case 'donations':
795 52
						// Update totals for pending donations.
796 52
						foreach ( $this->pending[ $key ] as $item ) {
797
798 52
							$quantity = isset( $item['quantity'] ) ? $item['quantity'] : 1;
799 52
							$price_id = isset( $item['price_id'] ) ? $item['price_id'] : 0;
800 52
801 52
							switch ( $item['action'] ) {
802 52
803
								case 'add':
804 52
805
									$price = $item['price'];
806 42
807
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
808 42
809 42
										// Add donation to logs.
810
										$log_date = date_i18n( 'Y-m-d G:i:s', current_time( 'timestamp' ) );
811 1
										give_record_donation_in_log( $item['id'], $this->ID, $price_id, $log_date );
812
813 1
										$form = new Give_Donate_Form( $item['id'] );
814 1
										$form->increase_sales( $quantity );
815
										$form->increase_earnings( $price );
816 42
817
										$total_increase += $price;
818
									}
819 1
									break;
820 1
821
								case 'remove':
822 1
									$this->delete_sales_logs();
823
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
824 42
										$form = new Give_Donate_Form( $item['id'] );
825
										$form->decrease_sales( $quantity );
826 52
										$form->decrease_earnings( $item['amount'] );
827
828
										$total_decrease += $item['amount'];
829 52
									}
830 52
									break;
831 52
832 52
							}// End switch().
833 52
						}// End foreach().
834 52
						break;
835 52
836
					case 'status':
837 52
						$this->update_status( $this->status );
838 52
						break;
839
840
					case 'gateway':
841 52
						$this->update_meta( '_give_payment_gateway', $this->gateway );
842 52
						break;
843 52
844 52
					case 'mode':
845 52
						$this->update_meta( '_give_payment_mode', $this->mode );
846 52
						break;
847
848 52
					case 'transaction_id':
849 52
						$this->update_meta( '_give_payment_transaction_id', $this->transaction_id );
850 52
						break;
851
852 52
					case 'ip':
853 52
						$this->update_meta( '_give_payment_donor_ip', $this->ip );
854 52
						break;
855
856 52
					case 'customer_id':
857
						$this->update_meta( '_give_payment_donor_id', $this->customer_id );
858
						break;
859
860
					// case 'user_id':
861
					// 	$this->update_meta( '_give_payment_user_id', $this->user_id );
862
					// 	break;
863
864
					case 'form_title':
865
						$this->update_meta( '_give_payment_form_title', $this->form_title );
866
						break;
867
868
					case 'form_id':
869
						$this->update_meta( '_give_payment_form_id', $this->form_id );
870 52
						break;
871
872 52
					case 'price_id':
873
						$this->update_meta( '_give_payment_price_id', $this->price_id );
874
						break;
875 52
876
					case 'first_name':
877
						$this->update_meta( '_give_donor_billing_first_name', $this->first_name );
878
						break;
879
880
					case 'last_name':
881 52
						$this->update_meta( '_give_donor_billing_last_name', $this->last_name );
882 52
						break;
883 52
884 52
					case 'currency':
885
						$this->update_meta( '_give_payment_currency', $this->currency );
886 52
						break;
887
888
					case 'address':
889 52
						if ( ! empty( $this->address ) ) {
890 52
							foreach ( $this->address as $address_name => $address ) {
891 52
								switch ( $address_name ) {
892
									case 'line1':
893
										$this->update_meta( '_give_donor_billing_address1', $address );
894 2
										break;
895 1
896 1
									case 'line2':
897
										$this->update_meta( '_give_donor_billing_address2', $address );
898 1
										break;
899
900
									default:
901 1
										$this->update_meta( "_give_donor_billing_{$address_name}", $address );
902 1
								}
903 1
							}
904 1
						}
905 1
						break;
906 1
907
					case 'email':
908 1
						$this->update_meta( '_give_payment_donor_email', $this->email );
909
						break;
910
911
					case 'key':
912 1
						$this->update_meta( '_give_payment_purchase_key', $this->key );
913
						break;
914 1
915
					case 'number':
916
						$this->update_meta( '_give_payment_number', $this->number );
917
						break;
918
919
					case 'date':
920 52
						$args = array(
921 52
							'ID'        => $this->ID,
922
							'post_date' => $this->date,
923
							'edit_date' => true,
924 52
						);
925 52
926 52
						wp_update_post( $args );
927 52
						break;
928 52
929
					case 'completed_date':
930
						$this->update_meta( '_give_completed_date', $this->completed_date );
931 52
						break;
932
933
					case 'parent_payment':
934
						$args = array(
935
							'ID'          => $this->ID,
936 52
							'post_parent' => $this->parent_payment,
937 52
						);
938 52
939 52
						wp_update_post( $args );
940 52
						break;
941 52
942 52
					default:
943
						/**
944 52
						 * Fires while saving payment.
945
						 *
946 52
						 * @since 1.7
947
						 *
948 52
						 * @param Give_Payment $this Payment object.
949
						 */
950 52
						do_action( 'give_payment_save', $this, $key );
951
						break;
952
				}// End switch().
953
			}// End foreach().
954
955
			if ( 'pending' !== $this->status ) {
956
957
				$donor = new Give_Donor( $this->customer_id );
958
959
				$total_change = $total_increase - $total_decrease;
960
				if ( $total_change < 0 ) {
961
962
					$total_change = - ( $total_change );
963
					// Decrease the donor's donation stats.
964 2
					$donor->decrease_value( $total_change );
965
					give_decrease_total_earnings( $total_change );
966
967
				} elseif ( $total_change > 0 ) {
968 2
969 2
					// Increase the donor's donation stats.
970 2
					$donor->increase_value( $total_change );
971 2
					give_increase_total_earnings( $total_change );
972 2
973
				}
974 2
			}
975
976
			$this->update_meta( '_give_payment_total', give_sanitize_amount_for_db( $this->total ) );
977 2
978
			$this->pending = array();
979
			$saved         = true;
980
		}// End if().
981 2
982 2
		if ( true === $saved ) {
983 2
			$this->setup_payment( $this->ID );
984 2
		}
985 2
986 2
		return $saved;
987
	}
988 2
989
	/**
990 2
	 * Add a donation to a given payment
991
	 *
992 2
	 * @since  1.5
993
	 * @access public
994
	 *
995
	 * @param  int   $form_id The donation form to add
996
	 * @param  array $args    Other arguments to pass to the function
997
	 * @param  array $options List of donation options
998
	 *
999
	 * @return bool           True when successful, false otherwise
1000
	 */
1001
	public function add_donation( $form_id = 0, $args = array(), $options = array() ) {
1002
1003
		$donation = new Give_Donate_Form( $form_id );
1004
1005
		// Bail if this post isn't a give donation form.
1006
		if ( ! $donation || $donation->post_type !== 'give_forms' ) {
0 ignored issues
show
introduced by
Found "!== '". Use Yoda Condition checks, you must
Loading history...
1007
			return false;
1008
		}
1009
1010
		// Set some defaults.
1011
		$defaults = array(
1012
			'price'    => false,
1013
			'price_id' => false,
1014
		);
1015
1016
		$args = wp_parse_args( apply_filters( 'give_payment_add_donation_args', $args, $donation->ID ), $defaults );
1017
1018
		// Allow overriding the price.
1019
		if ( false !== $args['price'] ) {
1020
			$donation_amount = $args['price'];
1021
		} else {
1022
1023
			// Deal with variable pricing.
1024
			if ( give_has_variable_prices( $donation->ID ) ) {
1025
				$prices          = give_get_meta( $form_id, '_give_donation_levels', true );
1026
				$donation_amount = '';
1027
				// Loop through prices.
1028 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...
1029
					// Find a match between price_id and level_id.
1030
					// First verify array keys exists THEN make the match.
1031
					if ( ( isset( $args['price_id'] ) && isset( $price['_give_id']['level_id'] ) )
1032
					     && $args['price_id'] == $price['_give_id']['level_id']
1033
					) {
1034
						$donation_amount = $price['_give_amount'];
1035
					}
1036
				}
1037
				// Fallback to the lowest price point.
1038
				if ( $donation_amount == '' ) {
1039
					$donation_amount  = give_get_lowest_price_option( $donation->ID );
1040
					$args['price_id'] = give_get_lowest_price_id( $donation->ID );
1041
				}
1042
			} else {
1043
				// Simple form price.
1044
				$donation_amount = give_get_form_price( $donation->ID );
1045
			}
1046
		}
1047
1048
		// Sanitizing the price here so we don't have a dozen calls later.
1049
		$donation_amount = give_maybe_sanitize_amount( $donation_amount );
1050
		$total           = round( $donation_amount, give_get_price_decimals( $this->ID ) );
1051
1052
		// Add Options.
1053
		$default_options = array();
1054
		if ( false !== $args['price_id'] ) {
1055
			$default_options['price_id'] = (int) $args['price_id'];
1056
		}
1057
		$options = wp_parse_args( $options, $default_options );
1058
1059
		// Do not allow totals to go negative.
1060
		if ( $total < 0 ) {
1061
			$total = 0;
1062
		}
1063
1064
		$donation = array(
1065
			'name'     => $donation->post_title,
1066
			'id'       => $donation->ID,
1067
			'price'    => round( $total, give_get_price_decimals( $this->ID ) ),
1068
			'subtotal' => round( $total, give_get_price_decimals( $this->ID ) ),
1069
			'price_id' => $args['price_id'],
1070
			'action'   => 'add',
1071
			'options'  => $options,
1072
		);
1073
1074
		$this->pending['donations'][] = $donation;
1075
1076
		$this->increase_subtotal( $total );
1077
1078
		return true;
1079
1080
	}
1081
1082
	/**
1083
	 * Remove a donation from the payment
1084
	 *
1085
	 * @since  1.5
1086
	 * @access public
1087
	 *
1088
	 * @param  int   $form_id The form ID to remove
1089
	 * @param  array $args    Arguments to pass to identify (quantity, amount, price_id)
1090
	 *
1091
	 * @return bool           If the item was removed or not
1092
	 */
1093
	public function remove_donation( $form_id, $args = array() ) {
1094
1095
		// Set some defaults.
1096
		$defaults = array(
1097
			'quantity' => 1,
1098
			'price'    => false,
1099
			'price_id' => false,
1100
		);
1101
		$args     = wp_parse_args( $args, $defaults );
1102
1103
		$form = new Give_Donate_Form( $form_id );
1104
1105
		// Bail if this post isn't a valid give donation form.
1106
		if ( ! $form || $form->post_type !== 'give_forms' ) {
0 ignored issues
show
introduced by
Found "!== '". Use Yoda Condition checks, you must
Loading history...
1107
			return false;
1108
		}
1109
1110
		$pending_args             = $args;
1111
		$pending_args['id']       = $form_id;
1112
		$pending_args['amount']   = $this->total;
1113
		$pending_args['price_id'] = false !== $args['price_id'] ? (int) $args['price_id'] : false;
1114
		$pending_args['quantity'] = $args['quantity'];
1115
		$pending_args['action']   = 'remove';
1116
1117
		$this->pending['donations'][] = $pending_args;
1118
1119
		$this->decrease_subtotal( $this->total );
1120
1121
		return true;
1122
	}
1123
1124
1125
	/**
1126
	 * Add a note to a payment
1127
	 *
1128
	 * @since  1.5
1129
	 * @access public
1130
	 *
1131
	 * @param  string|bool $note The note to add
1132
	 *
1133
	 * @return bool           If the note was specified or not
1134
	 */
1135
	public function add_note( $note = false ) {
1136
		// Bail if no note specified.
1137
		if ( ! $note ) {
1138
			return false;
1139
		}
1140
1141
		give_insert_payment_note( $this->ID, $note );
0 ignored issues
show
Bug introduced by
It seems like $note defined by parameter $note on line 1135 can also be of type boolean; however, give_insert_payment_note() does only seem to accept string, 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...
1142
	}
1143
1144
	/**
1145
	 * Increase the payment's subtotal
1146
	 *
1147
	 * @since  1.5
1148
	 * @access private
1149
	 *
1150
	 * @param  float $amount The amount to increase the payment subtotal by.
1151
	 *
1152
	 * @return void
1153
	 */
1154
	private function increase_subtotal( $amount = 0.00 ) {
1155
		$amount         = (float) $amount;
1156
		$this->subtotal += $amount;
1157
1158
		$this->recalculate_total();
1159
	}
1160
1161
	/**
1162
	 * Decrease the payment's subtotal.
1163
	 *
1164
	 * @since  1.5
1165
	 * @access private
1166
	 *
1167
	 * @param  float $amount The amount to decrease the payment subtotal by.
1168
	 *
1169
	 * @return void
1170
	 */
1171
	private function decrease_subtotal( $amount = 0.00 ) {
1172 52
		$amount         = (float) $amount;
1173 52
		$this->subtotal -= $amount;
1174 52
1175
		if ( $this->subtotal < 0 ) {
1176 52
			$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...
1177 52
		}
1178
1179
		$this->recalculate_total();
1180
	}
1181
1182
	/**
1183
	 * Set or update the total for a payment.
1184
	 *
1185
	 * @since  1.5
1186
	 * @access private
1187
	 *
1188 2
	 * @return void
1189 2
	 */
1190 2
	private function recalculate_total() {
1191
		$this->total = $this->subtotal;
1192 2
	}
1193
1194
	/**
1195
	 * Set the payment status and run any status specific changes necessary.
1196 2
	 *
1197 2
	 * @since  1.5
1198
	 * @access public
1199
	 *
1200
	 * @param  string|bool $status The status to set the payment to.
1201
	 *
1202
	 * @return bool   $updated Returns if the status was successfully updated.
1203
	 */
1204
	public function update_status( $status = false ) {
1205
1206
		// standardize the 'complete(d)' status.
1207
		if ( $status == 'completed' || $status == 'complete' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
1208
			$status = 'publish';
1209
		}
1210
1211
		$old_status = ! empty( $this->old_status ) ? $this->old_status : false;
1212
1213
		if ( $old_status === $status ) {
1214
			return false; // Don't permit status changes that aren't changes.
1215
		}
1216
1217
		$do_change = apply_filters( 'give_should_update_payment_status', true, $this->ID, $status, $old_status );
1218
1219
		$updated = false;
1220
1221
		if ( $do_change ) {
1222
1223
			/**
1224
			 * Fires before changing payment status.
1225
			 *
1226
			 * @since 1.5
1227
			 *
1228
			 * @param int    $payment_id Payments ID.
1229
			 * @param string $status     The new status.
1230
			 * @param string $old_status The old status.
1231
			 */
1232
			do_action( 'give_before_payment_status_change', $this->ID, $status, $old_status );
1233
1234
			$update_fields = array(
1235
				'ID'          => $this->ID,
1236
				'post_status' => $status,
1237
				'edit_date'   => current_time( 'mysql' ),
1238
			);
1239
1240
			$updated = wp_update_post( apply_filters( 'give_update_payment_status_fields', $update_fields ) );
1241 52
1242 52
			$all_payment_statuses  = give_get_payment_statuses();
1243 52
			$this->status_nicename = array_key_exists( $status, $all_payment_statuses ) ? $all_payment_statuses[ $status ] : ucfirst( $status );
1244
1245
			// Process any specific status functions.
1246
			$this->process_status( $status );
0 ignored issues
show
Bug introduced by
It seems like $status defined by parameter $status on line 1204 can also be of type boolean; however, Give_Payment::process_status() does only seem to accept string, 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...
1247
1248
			/**
1249
			 * Fires after changing payment status.
1250
			 *
1251
			 * @since 1.5
1252
			 *
1253
			 * @param int    $payment_id Payment ID.
1254 52
			 * @param string $status     The new status.
1255
			 * @param string $old_status The old status.
1256
			 */
1257 52
			do_action( 'give_update_payment_status', $this->ID, $status, $old_status );
1258 39
1259 39
		}// End if().
1260
1261 52
		return $updated;
1262
1263 52
	}
1264 52
1265
	/**
1266
	 * Change the status of the payment to refunded, and run the necessary changes
1267 42
	 *
1268
	 * @since  1.5
1269 42
	 * @access public
1270
	 *
1271
	 * @return void
1272 42
	 */
1273
	public function refund() {
1274 42
		$this->old_status        = $this->status;
1275
		$this->status            = 'refunded';
1276
		$this->pending['status'] = $this->status;
1277 42
1278 42
		$this->save();
1279 42
	}
1280 42
1281
	/**
1282 42
	 * Get a post meta item for the payment
1283
	 *
1284 42
	 * @since  1.5
1285 42
	 * @access public
1286
	 *
1287
	 * @param  string  $meta_key The Meta Key
1288
	 * @param  boolean $single   Return single item or array
1289 42
	 *
1290 4
	 * @return mixed             The value from the post meta
1291 4
	 */
1292 42
	public function get_meta( $meta_key = '_give_payment_meta', $single = true ) {
1293
		if( ! has_filter( 'get_post_metadata', 'give_bc_v20_get_payment_meta' ) && ! doing_filter( 'get_post_metadata' ) ) {
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...
1294
			add_filter( 'get_post_metadata', 'give_bc_v20_get_payment_meta', 999, 4 );
1295 42
		}
1296 3
1297 3
		$meta = give_get_meta( $this->ID, $meta_key, $single );
1298
1299
		/**
1300 42
		 * Filter the specific meta key value.
1301
		 *
1302 42
		 * @since 1.5
1303
		 */
1304 42
		$meta = apply_filters( "give_get_payment_meta_{$meta_key}", $meta, $this->ID );
1305
1306
		// Security check.
1307 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...
1308
			preg_match( '/[oO]\s*:\s*\d+\s*:\s*"\s*(?!(?i)(stdClass))/', $meta, $matches );
1309
			if ( ! empty( $matches ) ) {
1310
				$meta = array();
1311
			}
1312
		}
1313
1314 4
		/**
1315 4
		 * Filter the all meta keys.
1316 4
		 *
1317 4
		 * @since 1.5
1318
		 */
1319 4
		return apply_filters( 'give_get_payment_meta', $meta, $this->ID, $meta_key );
1320 4
	}
1321
1322
	/**
1323
	 * Update the post meta
1324
	 *
1325
	 * @since  1.5
1326
	 * @access public
1327
	 *
1328
	 * @param  string $meta_key   The meta key to update
1329
	 * @param  string $meta_value The meta value
1330
	 * @param  string $prev_value Previous meta value
1331
	 *
1332 52
	 * @return int|bool           Meta ID if the key didn't exist, true on successful update, false on failure
1333
	 */
1334 52
	public function update_meta( $meta_key = '', $meta_value = '', $prev_value = '' ) {
1335
		if ( empty( $meta_key ) ) {
1336 52
			return false;
1337
		}
1338 52
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1339 52
1340 52
		/**
1341
		 * Filter the single meta key while updating
1342 52
		 *
1343 52
		 * @since 1.5
1344 52
		 */
1345
		$meta_value = apply_filters( "give_update_payment_meta_{$meta_key}", $meta_value, $this->ID );
1346 52
1347 52
		return give_update_meta( $this->ID, $meta_key, $meta_value, $prev_value );
1348 52
	}
1349
1350 52
	/**
1351 52
	 * Process Donation Status.
1352 52
	 *
1353 52
	 * @param string $status Donation Status.
1354
	 *
1355 52
	 * @since  2.0.2
1356
	 * @access private
1357 52
	 *
1358
	 * @return void
1359
	 */
1360
	private function process_status( $status ) {
1361
		$process = true;
1362
1363
		// Bailout, if changed from completed to preapproval/processing.
1364
		// Bailout, if current status = previous status or status is publish.
1365
		if (
1366
			'preapproval' === $status ||
1367
			'processing' === $status ||
1368
			'publish' !== $this->old_status ||
1369
			$status !== $this->status
1370
		) {
1371 52
			$process = false;
1372 52
		}
1373
1374
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1375
		$process = apply_filters( "give_should_process_{$status}", $process, $this );
1376 52
1377
		if ( false === $process ) {
1378
			return;
1379
		}
1380
1381
		/**
1382
		 * Fires before processing donation status.
1383
		 *
1384 52
		 * @param Give_Payment $this Payment object.
1385
		 *
1386 52
		 * @since 1.5
1387 52
		 */
1388
		do_action( "give_pre_{$status}_payment", $this );
1389 52
1390 52
		$decrease_earnings       = apply_filters( "give_decrease_earnings_on_{$status}", true, $this );
1391
		$decrease_donor_value    = apply_filters( "give_decrease_donor_value_on_{$status}", true, $this );
1392 52
		$decrease_donation_count = apply_filters( "give_decrease_donors_donation_count_on_{$status}", true, $this );
1393 52
1394
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1395 52
		$this->delete_sales_logs();
1396
1397 52
		// @todo: Refresh only range related stat cache
1398
		give_delete_donation_stats();
1399 52
1400
		/**
1401
		 * Fires after processing donation status.
1402
		 *
1403
		 * @param Give_Payment $this Payment object.
1404
		 *
1405
		 * @since 1.5
1406
		 */
1407
		do_action( "give_post_{$status}_payment", $this );
1408
	}
1409 4
1410 4
	/**
1411
	 * Used during the process of moving to refunded or pending, to decrement stats
1412
	 *
1413 4
	 * @since  1.5
1414
	 * @access private
1415
	 *
1416
	 * @param  bool $alter_store_earnings          If the method should alter the store earnings
1417
	 * @param  bool $alter_customer_value          If the method should reduce the donor value
1418 4
	 * @param  bool $alter_customer_purchase_count If the method should reduce the donor's purchase count
1419
	 *
1420 4
	 * @return void
1421
	 */
1422
	private function maybe_alter_stats( $alter_store_earnings, $alter_customer_value, $alter_customer_purchase_count ) {
1423
1424 4
		give_undo_donation( $this->ID );
1425
1426 4
		// Decrease store earnings.
1427 4
		if ( true === $alter_store_earnings ) {
1428 4
			give_decrease_total_earnings( $this->total );
1429
		}
1430 4
1431 4
		// Decrement the stats for the donor.
1432
		if ( ! empty( $this->customer_id ) ) {
1433
1434 4
			$donor = new Give_Donor( $this->customer_id );
1435
1436 4
			if ( true === $alter_customer_value ) {
1437 4
				$donor->decrease_value( $this->total );
1438
			}
1439
1440
			if ( true === $alter_customer_purchase_count ) {
1441
				$donor->decrease_donation_count();
1442
			}
1443
		}
1444
1445
	}
1446
1447
	/**
1448
	 * Delete sales logs for this donation
1449
	 *
1450
	 * @since  1.5
1451
	 * @access private
1452
	 *
1453
	 * @return void
1454
	 */
1455
	private function delete_sales_logs() {
1456 3
		// Remove related sale log entries.
1457 3
		Give()->logs->delete_logs( $this->ID );
1458
	}
1459
1460 3
	/**
1461 1
	 * Setup functions only, these are not to be used by developers.
1462 1
	 * These functions exist only to allow the setup routine to be backwards compatible with our old
1463
	 * helper functions.
1464
	 *
1465 3
	 * These will run whenever setup_payment is called, which should only be called once.
1466
	 * To update an attribute, update it directly instead of re-running the setup routine
1467 3
	 */
1468 1
1469
	/**
1470
	 * Setup the payment completed date
1471 2
	 *
1472 2
	 * @since  1.5
1473 2
	 * @access private
1474
	 *
1475 2
	 * @return string The date the payment was completed
1476 2
	 */
1477
	private function setup_completed_date() {
1478 2
		$payment = get_post( $this->ID );
1479 2
1480
		if ( 'pending' == $payment->post_status || 'preapproved' == $payment->post_status ) {
1481
			return false; // This payment was never completed.
1482 2
		}
1483 2
1484
		$date = ( $date = $this->get_meta( '_give_completed_date', true ) ) ? $date : $payment->modified_date;
1485
1486
		return $date;
1487
	}
1488
1489
	/**
1490
	 * Setup the payment mode
1491
	 *
1492
	 * @since  1.5
1493
	 * @access private
1494
	 *
1495
	 * @return string The payment mode
1496 6
	 */
1497
	private function setup_mode() {
1498 6
		return $this->get_meta( '_give_payment_mode' );
1499
	}
1500
1501 6
	/**
1502 4
	 * Setup the payment import data
1503 4
	 *
1504
	 * @since  1.8.13
1505
	 * @access private
1506 6
	 *
1507
	 * @return bool The payment import
1508 6
	 */
1509
	private function setup_import() {
1510 6
		return (bool) $this->get_meta( '_give_payment_import' );
1511 4
	}
1512 4
1513
	/**
1514 6
	 * Setup the payment total
1515 4
	 *
1516 4
	 * @since  1.5
1517
	 * @access private
1518 6
	 *
1519
	 * @return float The payment total
1520 6
	 */
1521
	private function setup_total() {
1522
		$amount = $this->get_meta( '_give_payment_total', true );
1523
1524
		return round( floatval( $amount ), give_get_price_decimals( $this->ID ) );
1525
	}
1526
1527
	/**
1528 6
	 * Setup the payment subtotal
1529 6
	 *
1530
	 * @since  1.5
1531
	 * @access private
1532 6
	 *
1533 6
	 * @return float The subtotal of the payment
1534 6
	 */
1535
	private function setup_subtotal() {
1536
		$subtotal = $this->total;
1537 6
1538 6
		return $subtotal;
1539 6
	}
1540
1541 6
	/**
1542 6
	 * Setup the currency code
1543
	 *
1544
	 * @since  1.5
1545
	 * @since  2.0 Set currency from _give_payment_currency meta key
1546
	 * @access private
1547
	 *
1548
	 * @return string The currency for the payment
1549
	 */
1550 View Code Duplication
	private function setup_currency() {
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...
1551
		$currency = $this->get_meta( '_give_payment_currency', true );
1552
		$currency = ! empty( $currency ) ?
1553
			$currency :
1554
			/**
1555
			 * Filter the default donation currency
1556
			 *
1557
			 * @since 1.5
1558
			 */
1559 52
			apply_filters(
1560 52
				'give_payment_currency_default',
1561
				give_get_currency( $this->form_id, $this ),
1562 52
				$this
1563 52
			);
1564
1565
		return $currency;
1566 42
	}
1567
1568 42
	/**
1569
	 * Setup the gateway used for the payment
1570
	 *
1571
	 * @since  1.5
1572
	 * @access private
1573
	 *
1574
	 * @return string The gateway
1575
	 */
1576
	private function setup_gateway() {
1577 52
		$gateway = $this->get_meta( '_give_payment_gateway', true );
1578 52
1579
		return $gateway;
1580
	}
1581
1582
	/**
1583
	 * Setup the donation ID
1584
	 *
1585
	 * @since  1.5
1586
	 * @access private
1587 52
	 *
1588 52
	 * @return string The donation ID
1589
	 */
1590 52 View Code Duplication
	private function setup_transaction_id() {
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...
1591 2
		$transaction_id = $this->get_meta( '_give_payment_transaction_id', true );
1592 2
1593
		if ( empty( $transaction_id ) ) {
1594 2
			$gateway        = $this->gateway;
1595
			$transaction_id = apply_filters( "give_get_payment_transaction_id-{$gateway}", $this->ID );
1596
		}
1597 2
1598
		return $transaction_id;
1599 52
	}
1600
1601
	/**
1602
	 * Setup the IP Address for the payment
1603
	 *
1604
	 * @since  1.5
1605
	 * @since  2.0 Set ip address from _give_payment_donor_ip meta key
1606
	 * @access private
1607
	 *
1608 52
	 * @return string The IP address for the payment
1609 52
	 */
1610
	private function setup_ip() {
1611 52
		$ip = $this->get_meta( '_give_payment_donor_ip', true );
1612
1613
		return $ip;
1614
	}
1615
1616
	/**
1617
	 * Setup the donor ID.
1618
	 *
1619
	 * @since  1.5
1620 52
	 * @since  2.0 Set id from _give_payment_donor_id meta key
1621 52
	 * @access private
1622
	 *
1623 52
	 * @return int The Donor ID.
1624 52
	 */
1625
	private function setup_donor_id() {
1626
		$donor_id = $this->get_meta( '_give_payment_donor_id', true );
1627
1628
		return $donor_id;
1629
	}
1630 52
1631
	/**
1632
	 * Setup the User ID associated with the donation
1633
	 *
1634
	 * @since  1.5
1635
	 * @since  2.0 Get user id connect to donor from donor table instead of payment meta.
1636
	 *
1637
	 * @access private
1638
	 *
1639
	 * @return int The User ID
1640 52
	 */
1641 52
	private function setup_user_id() {
1642
1643 52
		$donor   = Give()->customers->get_customer_by( 'id', $this->customer_id );
1644
		$user_id = $donor ? absint( $donor->user_id ) : 0;
1645
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1646
1647
		return $user_id;
1648
	}
1649
1650
	/**
1651
	 * Setup the email address for the donation.
1652 52
	 *
1653 52
	 * @since  1.5
1654
	 * @since  2.0 Set email from _give_payment_donor_email meta key
1655 52
	 *
1656
	 * @access private
1657
	 *
1658
	 * @return string The email address for the payment.
1659
	 */
1660
	private function setup_email() {
1661
		$email = $this->get_meta( '_give_payment_donor_email', true );
1662
1663
		if ( empty( $email ) && $this->customer_id ) {
1664 52
			$email = Give()->donors->get_column( 'email', $this->customer_id );
1665 52
		}
1666
1667 52
		return $email;
1668
	}
1669
1670
	/**
1671
	 * Setup the user info.
1672
	 *
1673
	 * @since  1.5
1674
	 * @access private
1675
	 *
1676 52
	 * @return array The user info associated with the payment.
1677 52
	 */
1678
	private function setup_user_info() {
1679 52
		$defaults = array(
1680
			'first_name' => $this->first_name,
1681 52
			'last_name'  => $this->last_name,
1682 52
		);
1683
1684 52
		$user_info = isset( $this->payment_meta['user_info'] ) ? $this->payment_meta['user_info'] : array();
1685
1686 52 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...
1687
			preg_match( '/[oO]\s*:\s*\d+\s*:\s*"\s*(?!(?i)(stdClass))/', $user_info, $matches );
1688
			if ( ! empty( $matches ) ) {
1689
				$user_info = array();
1690
			}
1691
		}
1692
1693
		$user_info = wp_parse_args( $user_info, $defaults );
1694
1695 52
		if ( empty( $user_info ) ) {
1696 52
			// Get the donor, but only if it's been created.
1697
			$donor = new Give_Donor( $this->customer_id );
1698 52
1699
			if ( $donor->id > 0 ) {
1700
				$user_info = array(
1701
					'first_name' => $donor->get_first_name(),
1702
					'last_name'  => $donor->get_last_name(),
1703
					'email'      => $donor->email,
1704
					'discount'   => 'none',
1705
				);
1706
			}
1707 52
		} else {
1708 52
			// Get the donor, but only if it's been created.
1709
			$donor = new Give_Donor( $this->customer_id );
1710 52
1711
			if ( $donor->id > 0 ) {
1712
				foreach ( $user_info as $key => $value ) {
1713
					if ( ! empty( $value ) ) {
1714
						continue;
1715
					}
1716
1717
					switch ( $key ) {
1718
						case 'first_name':
1719 52
							$user_info[ $key ] = $donor->get_first_name();
1720 52
							break;
1721
1722 52
						case 'last_name':
1723
							$user_info[ $key ] = $donor->get_last_name();
1724
							break;
1725
1726
						case 'email':
1727
							$user_info[ $key ] = $donor->email;
1728
							break;
1729
					}
1730
				}
1731 52
			}
1732 52
		}// End if().
1733
1734 52
		return $user_info;
1735 2
1736 2
	}
1737
1738 52
	/**
1739
	 * Setup the Address for the payment.
1740
	 *
1741
	 * @since  1.5
1742
	 * @access private
1743
	 *
1744
	 * @return array The Address information for the payment.
1745
	 */
1746
	private function setup_address() {
1747 52
		$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...
1748
		$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...
1749 52
		$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...
1750 52
		$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...
1751 52
		$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...
1752
		$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...
1753 52
1754 52
		return $address;
1755
	}
1756 52
1757
	/**
1758
	 * Setup the form title.
1759
	 *
1760
	 * @since  1.5
1761
	 * @access private
1762
	 *
1763
	 * @return string The Form Title.
1764
	 */
1765
	private function setup_form_title() {
1766
1767
		$form_id = $this->get_meta( '_give_payment_form_title', true );
1768
1769
		return $form_id;
1770
	}
1771 52
1772 52
	/**
1773 52
	 * Setup the form ID.
1774 52
	 *
1775 52
	 * @since  1.5
1776
	 * @access private
1777
	 *
1778
	 * @return int The Form ID
1779 21
	 */
1780 21
	private function setup_form_id() {
1781
1782 21
		$form_id = $this->get_meta( '_give_payment_form_id', true );
1783 21
1784
		return $form_id;
1785 21
	}
1786 21
1787 21
	/**
1788
	 * Setup the price ID.
1789 21
	 *
1790 21
	 * @since  1.5
1791
	 * @access private
1792
	 *
1793
	 * @return int The Form Price ID.
1794
	 */
1795
	private function setup_price_id() {
1796 52
		$price_id = $this->get_meta( '_give_payment_price_id', true );
1797
1798 52
		return $price_id;
1799
	}
1800
1801 52
	/**
1802
	 * Setup the payment key.
1803
	 *
1804
	 * @since  1.5
1805
	 * @access private
1806
	 *
1807
	 * @return string The Payment Key.
1808
	 */
1809
	private function setup_payment_key() {
1810
		$key = $this->get_meta( '_give_payment_purchase_key', true );
1811 52
1812
		return $key;
1813 52
	}
1814 52
1815 52
	/**
1816 52
	 * Setup the payment number.
1817 52
	 *
1818 52
	 * @since  1.5
1819
	 * @access private
1820 52
	 *
1821
	 * @return int|string Integer by default, or string if sequential order numbers is enabled.
1822 52
	 */
1823
	private function setup_payment_number() {
1824
		$number = $this->ID;
1825
1826
		if ( give_get_option( 'enable_sequential' ) ) {
1827
1828
			$number = $this->get_meta( '_give_payment_number', true );
1829
1830
			if ( ! $number ) {
1831 52
1832
				$number = $this->ID;
1833 52
1834
			}
1835 52
		}
1836
1837
		return $number;
1838
	}
1839
1840
	/**
1841
	 * Converts this object into an array for special cases.
1842
	 *
1843
	 * @access public
1844 52
	 *
1845
	 * @return array The payment object as an array.
1846 52
	 */
1847
	public function array_convert() {
1848 52
		return get_object_vars( $this );
1849
	}
1850
1851
1852
	/**
1853
	 * Flag to check if donation is completed or not.
1854
	 *
1855
	 * @since  1.8
1856
	 * @access public
1857 52
	 *
1858 52
	 * @return bool
1859
	 */
1860 52
	public function is_completed() {
1861
		return ( 'publish' === $this->status && $this->completed_date );
1862
	}
1863
1864
	/**
1865
	 * Retrieve payment completion date.
1866
	 *
1867
	 * @since  1.5
1868
	 * @access private
1869 52
	 *
1870 52
	 * @return string Date payment was completed.
1871
	 */
1872 52
	private function get_completed_date() {
1873
		return apply_filters( 'give_payment_completed_date', $this->completed_date, $this->ID, $this );
1874
	}
1875
1876
	/**
1877
	 * Retrieve payment subtotal.
1878
	 *
1879
	 * @since  1.5
1880
	 * @access private
1881 52
	 *
1882 52
	 * @return float Payment subtotal.
1883
	 */
1884 52
	private function get_subtotal() {
1885
		return apply_filters( 'give_get_payment_subtotal', $this->subtotal, $this->ID, $this );
1886 20
	}
1887
1888 20
	/**
1889
	 * Retrieve payment currency.
1890 2
	 *
1891
	 * @since  1.5
1892 2
	 * @access private
1893
	 *
1894 20
	 * @return string Payment currency code.
1895
	 */
1896 52
	private function get_currency() {
1897
		return apply_filters( 'give_payment_currency_code', $this->currency, $this->ID, $this );
1898
	}
1899
1900
	/**
1901
	 * Retrieve payment gateway.
1902
	 *
1903
	 * @since  1.5
1904
	 * @access private
1905
	 *
1906
	 * @return string Gateway used.
1907
	 */
1908
	private function get_gateway() {
1909
		return apply_filters( 'give_payment_gateway', $this->gateway, $this->ID, $this );
1910
	}
1911
1912
	/**
1913
	 * Retrieve donation ID.
1914 42
	 *
1915 42
	 * @since  1.5
1916
	 * @access private
1917
	 *
1918
	 * @return string Donation ID from merchant processor.
1919
	 */
1920
	private function get_transaction_id() {
1921
		return apply_filters( 'give_get_payment_transaction_id', $this->transaction_id, $this->ID, $this );
1922
	}
1923
1924
	/**
1925
	 * Retrieve payment IP
1926
	 *
1927
	 * @since  1.5
1928
	 * @access private
1929
	 *
1930
	 * @return string Payment IP address
1931
	 */
1932
	private function get_ip() {
1933
		return apply_filters( 'give_payment_user_ip', $this->ip, $this->ID, $this );
1934 42
	}
1935 42
1936
	/**
1937
	 * Retrieve payment donor ID.
1938
	 *
1939
	 * @since  1.5
1940
	 * @access private
1941
	 *
1942
	 * @return int Payment donor ID.
1943
	 */
1944 42
	private function get_donor_id() {
1945 42
		return apply_filters( 'give_payment_customer_id', $this->customer_id, $this->ID, $this );
1946
	}
1947
1948
	/**
1949
	 * Retrieve payment user ID.
1950
	 *
1951
	 * @since  1.5
1952
	 * @access private
1953
	 *
1954 11
	 * @return int Payment user ID.
1955 11
	 */
1956
	private function get_user_id() {
1957
		return apply_filters( 'give_payment_user_id', $this->user_id, $this->ID, $this );
1958
	}
1959
1960
	/**
1961
	 * Retrieve payment email.
1962
	 *
1963
	 * @since  1.5
1964
	 * @access private
1965
	 *
1966
	 * @return string Payment donor email.
1967
	 */
1968
	private function get_email() {
1969
		return apply_filters( 'give_payment_user_email', $this->email, $this->ID, $this );
1970
	}
1971
1972
	/**
1973
	 * Retrieve payment user info.
1974 52
	 *
1975 52
	 * @since  1.5
1976
	 * @access private
1977
	 *
1978
	 * @return array Payment user info.
1979
	 */
1980
	private function get_user_info() {
1981
		return apply_filters( 'give_payment_meta_user_info', $this->user_info, $this->ID, $this );
1982
	}
1983
1984 41
	/**
1985 41
	 * Retrieve payment billing address.
1986
	 *
1987
	 * @since  1.5
1988
	 * @access private
1989
	 *
1990
	 * @return array Payment billing address.
1991
	 */
1992
	private function get_address() {
1993
		return apply_filters( 'give_payment_address', $this->address, $this->ID, $this );
1994 42
	}
1995 42
1996
	/**
1997
	 * Retrieve payment key.
1998
	 *
1999
	 * @since  1.5
2000
	 * @access private
2001
	 *
2002
	 * @return string Payment key.
2003
	 */
2004 43
	private function get_key() {
2005 43
		return apply_filters( 'give_payment_key', $this->key, $this->ID, $this );
2006
	}
2007
2008
	/**
2009
	 * Retrieve payment form id
2010
	 *
2011
	 * @since  1.5
2012
	 * @access private
2013
	 *
2014
	 * @return string Payment form id
2015
	 */
2016
	private function get_form_id() {
2017
		return apply_filters( 'give_payment_form_id', $this->form_id, $this->ID, $this );
2018
	}
2019
2020
	/**
2021
	 * Retrieve payment number
2022
	 *
2023
	 * @since  1.5
2024 52
	 * @access private
2025 52
	 *
2026
	 * @return int|string Payment number
2027
	 */
2028
	private function get_number() {
2029
		return apply_filters( 'give_payment_number', $this->number, $this->ID, $this );
2030
	}
2031
}
2032