Completed
Push — issues/1132 ( baf91f...f70d74 )
by Ravinder
18:30
created

Give_Payment::setup_address()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

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

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

Please refer to the PHP core documentation on constructors.

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

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

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

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

Let’s take a look at an example:

class A
{
    public function foo() { }
}

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

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

Available Fixes

  1. Add an additional type-check:

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

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

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

Let’s take a look at an example:

class A
{
    public function foo() { }
}

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

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

Available Fixes

  1. Add an additional type-check:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Loading history...
910
911
			if ( 'pending' !== $this->status ) {
912
913
				$donor = new Give_Donor( $this->customer_id );
914
915
				$total_change = $total_increase - $total_decrease;
916
				if ( $total_change < 0 ) {
917
918
					$total_change = - ( $total_change );
919
					// Decrease the donor's donation stats.
920
					$donor->decrease_value( $total_change );
921
					give_decrease_total_earnings( $total_change );
922
923
				} elseif ( $total_change > 0 ) {
924
925
					// Increase the donor's donation stats.
926
					$donor->increase_value( $total_change );
927
					give_increase_total_earnings( $total_change );
928
929
				}
930
			}
931
932
			$this->update_meta( '_give_payment_total', $this->total );
933
934
			$this->pending = array();
935
			$saved         = true;
936
		}// End if().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

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

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

<?php

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

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

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

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

}

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

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

See also the PhpDoc documentation for @property.

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

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

<?php

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

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

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

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

}

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

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

See also the PhpDoc documentation for @property.

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

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

Loading history...
1090
	 */
1091
	public function add_note( $note = false ) {
1092
		// Bail if no note specified.
1093
		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...
1094
			return false;
1095
		}
1096
1097
		give_insert_payment_note( $this->ID, $note );
1098
	}
1099
1100
	/**
1101
	 * Increase the payment's subtotal
1102
	 *
1103
	 * @since  1.5
1104
	 * @access private
1105
	 *
1106
	 * @param  float $amount The amount to increase the payment subtotal by.
1107
	 *
1108
	 * @return void
1109
	 */
1110
	private function increase_subtotal( $amount = 0.00 ) {
1111
		$amount         = (float) $amount;
1112
		$this->subtotal += $amount;
1113
1114
		$this->recalculate_total();
1115
	}
1116
1117
	/**
1118
	 * Decrease the payment's subtotal.
1119
	 *
1120
	 * @since  1.5
1121
	 * @access private
1122
	 *
1123
	 * @param  float $amount The amount to decrease the payment subtotal by.
1124
	 *
1125
	 * @return void
1126
	 */
1127
	private function decrease_subtotal( $amount = 0.00 ) {
1128
		$amount         = (float) $amount;
1129
		$this->subtotal -= $amount;
1130
1131
		if ( $this->subtotal < 0 ) {
1132
			$this->subtotal = 0;
1133
		}
1134
1135
		$this->recalculate_total();
1136
	}
1137
1138
	/**
1139
	 * Set or update the total for a payment.
1140
	 *
1141
	 * @since  1.5
1142
	 * @access private
1143
	 *
1144
	 * @return void
1145
	 */
1146
	private function recalculate_total() {
1147
		$this->total = $this->subtotal;
1148
	}
1149
1150
	/**
1151
	 * Set the payment status and run any status specific changes necessary.
1152
	 *
1153
	 * @since  1.5
1154
	 * @access public
1155
	 *
1156
	 * @param  string|bool $status The status to set the payment to.
1157
	 *
1158
	 * @return bool   $updated Returns if the status was successfully updated.
1159
	 */
1160
	public function update_status( $status = false ) {
1161
1162
		// standardize the 'complete(d)' status.
1163
		if ( $status == 'completed' || $status == 'complete' ) {
1164
			$status = 'publish';
1165
		}
1166
1167
		$old_status = ! empty( $this->old_status ) ? $this->old_status : false;
1168
1169
		if ( $old_status === $status ) {
1170
			return false; // Don't permit status changes that aren't changes.
1171
		}
1172
1173
		$do_change = apply_filters( 'give_should_update_payment_status', true, $this->ID, $status, $old_status );
1174
1175
		$updated = false;
1176
1177
		if ( $do_change ) {
1178
1179
			/**
1180
			 * Fires before changing payment status.
1181
			 *
1182
			 * @since 1.5
1183
			 *
1184
			 * @param int $payment_id Payments ID.
1185
			 * @param string $status The new status.
1186
			 * @param string $old_status The old status.
1187
			 */
1188
			do_action( 'give_before_payment_status_change', $this->ID, $status, $old_status );
1189
1190
			$update_fields = array(
1191
				'ID'          => $this->ID,
1192
				'post_status' => $status,
1193
				'edit_date'   => current_time( 'mysql' ),
1194
			);
1195
1196
			$updated = wp_update_post( apply_filters( 'give_update_payment_status_fields', $update_fields ) );
1197
1198
			$all_payment_statuses  = give_get_payment_statuses();
1199
			$this->status_nicename = array_key_exists( $status, $all_payment_statuses ) ? $all_payment_statuses[ $status ] : ucfirst( $status );
1200
1201
			// Process any specific status functions.
1202
			switch ( $status ) {
1203
				case 'refunded':
1204
					$this->process_refund();
1205
					break;
1206
				case 'failed':
1207
					$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...
1208
					break;
1209
				case 'pending':
1210
					$this->process_pending();
1211
					break;
1212
				case 'cancelled':
1213
					$this->process_cancelled();
1214
					break;
1215
				case 'revoked':
1216
					$this->process_revoked();
1217
					break;
1218
			}
1219
1220
			/**
1221
			 * Fires after changing payment status.
1222
			 *
1223
			 * @since 1.5
1224
			 *
1225
			 * @param int $payment_id Payment ID.
1226
			 * @param string $status The new status.
1227
			 * @param string $old_status The old status.
1228
			 */
1229
			do_action( 'give_update_payment_status', $this->ID, $status, $old_status );
1230
1231
		}// End if().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

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

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

1. Pass all data via parameters

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

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

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

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

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

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

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

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

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

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

Loading history...
1804
1805
		return $user_info;
1806
1807
	}
1808
1809
	/**
1810
	 * Setup the Address for the payment.
1811
	 *
1812
	 * @since  1.5
1813
	 * @access private
1814
	 *
1815
	 * @return array The Address information for the payment.
1816
	 */
1817
	private function setup_address() {
1818
		$address['line1']   = give_get_meta( $this->ID, '_give_donor_billing_address1', true, '' );
0 ignored issues
show
Coding Style Comprehensibility introduced by
$address was never initialized. Although not strictly required by PHP, it is generally a good practice to add $address = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

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