Completed
Push — issues/1429 ( 3d8b34 )
by Ravinder
37:26 queued 17:25
created

Give_Payment::get_form_id()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
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 string     $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
	 * Includes donation amount and fees.
146
	 *
147
	 * @since  1.5
148
	 * @access protected
149
	 *
150
	 * @var    float
151
	 */
152
	protected $total = 0.00;
153
154
	/**
155
	 * The Subtotal fo the payment before fees
156
	 *
157
	 * @since  1.5
158
	 * @access protected
159
	 *
160
	 * @var    float
161
	 */
162
	protected $subtotal = 0;
163
164
	/**
165
	 * Array of global fees for this payment
166
	 *
167
	 * @since  1.5
168
	 * @access protected
169
	 *
170
	 * @var    array
171
	 */
172
	protected $fees = array();
173
174
	/**
175
	 * The sum of the fee amounts
176
	 *
177
	 * @since  1.5
178
	 * @access protected
179
	 *
180
	 * @var    float
181
	 */
182
	protected $fees_total = 0;
183
184
	/**
185
	 * The date the payment was created
186
	 *
187
	 * @since  1.5
188
	 * @access protected
189
	 *
190
	 * @var    string
191
	 */
192
	protected $date = '';
193
194
	/**
195
	 * The date the payment post was created.
196
	 *
197
	 * @var string
198
	 */
199
	protected $post_date = '';
200
201
	/**
202
	 * The date the payment was marked as 'complete'.
203
	 *
204
	 * @since  1.5
205
	 * @access protected
206
	 *
207
	 * @var    string
208
	 */
209
	protected $completed_date = '';
210
211
	/**
212
	 * The status of the donation payment.
213
	 *
214
	 * @since  1.5
215
	 * @access protected
216
	 *
217
	 * @var    string
218
	 */
219
	protected $status = 'pending';
220
221
	/**
222
	 * @var string
223
	 */
224
	protected $post_status = 'pending'; // Same as $status but here for backwards compat
225
226
	/**
227
	 * When updating, the old status prior to the change
228
	 *
229
	 * @since  1.5
230
	 * @access protected
231
	 *
232
	 * @var    string
233
	 */
234
	protected $old_status = '';
235
236
	/**
237
	 * The display name of the current payment status.
238
	 *
239
	 * @since  1.5
240
	 * @access protected
241
	 *
242
	 * @var    string
243
	 */
244
	protected $status_nicename = '';
245
246
	/**
247
	 * The customer ID that made the payment
248
	 *
249
	 * @since  1.5
250
	 * @access protected
251
	 *
252
	 * @var    integer
253
	 */
254
	protected $customer_id = null;
255
256
	/**
257
	 * The User ID (if logged in) that made the payment
258
	 *
259
	 * @since  1.5
260
	 * @access protected
261
	 *
262
	 * @var    integer
263
	 */
264
	protected $user_id = 0;
265
266
	/**
267
	 * The first name of the payee
268
	 *
269
	 * @since  1.5
270
	 * @access protected
271
	 *
272
	 * @var    string
273
	 */
274
	protected $first_name = '';
275
276
	/**
277
	 * The last name of the payee
278
	 *
279
	 * @since  1.5
280
	 * @access protected
281
	 *
282
	 * @var    string
283
	 */
284
	protected $last_name = '';
285
286
	/**
287
	 * The email used for the payment
288
	 *
289
	 * @since  1.5
290
	 * @access protected
291
	 *
292
	 * @var    string
293
	 */
294
	protected $email = '';
295
296
	/**
297
	 * Legacy (not to be accessed) array of user information
298
	 *
299
	 * @since  1.5
300
	 * @access private
301
	 *
302
	 * @var    array
303
	 */
304
	private $user_info = array();
305
306
	/**
307
	 * Legacy (not to be accessed) payment meta array
308
	 *
309
	 * @since  1.5
310
	 * @access private
311
	 *
312
	 * @var    array
313
	 */
314
	private $payment_meta = array();
315
316
	/**
317
	 * The physical address used for the payment if provided
318
	 *
319
	 * @since  1.5
320
	 * @access protected
321
	 *
322
	 * @var    array
323
	 */
324
	protected $address = array();
325
326
	/**
327
	 * The transaction ID returned by the gateway
328
	 *
329
	 * @since  1.5
330
	 * @access protected
331
	 *
332
	 * @var    string
333
	 */
334
	protected $transaction_id = '';
335
336
	/**
337
	 * IP Address payment was made from
338
	 *
339
	 * @since  1.5
340
	 * @access protected
341
	 *
342
	 * @var    string
343
	 */
344
	protected $ip = '';
345
346
	/**
347
	 * The gateway used to process the payment
348
	 *
349
	 * @since  1.5
350
	 * @access protected
351
	 *
352
	 * @var    string
353
	 */
354
	protected $gateway = '';
355
356
	/**
357
	 * The the payment was made with
358
	 *
359
	 * @since  1.5
360
	 * @access protected
361
	 *
362
	 * @var    string
363
	 */
364
	protected $currency = '';
365
366
	/**
367
	 * Array of items that have changed since the last save() was run.
368
	 * This is for internal use, to allow fewer update_payment_meta calls to be run.
369
	 *
370
	 * @since  1.5
371
	 * @access private
372
	 *
373
	 * @var    array
374
	 */
375
	private $pending;
376
377
	/**
378
	 * The parent payment (if applicable)
379
	 *
380
	 * @since  1.5
381
	 * @access protected
382
	 *
383
	 * @var    integer
384
	 */
385
	protected $parent_payment = 0;
386
387
	/**
388
	 * Setup the Give Payments class
389
	 *
390
	 * @since  1.5
391
	 * @access public
392
	 *
393
	 * @param  int|bool $payment_id A given payment
394
	 *
395
	 * @return mixed void|false
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

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

Please refer to the PHP core documentation on constructors.

Loading history...
396
	 */
397
	public function __construct( $payment_id = false ) {
398
399
		if ( empty( $payment_id ) ) {
400
			return false;
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
401
		}
402
403
		$this->setup_payment( $payment_id );
404
	}
405
406
	/**
407
	 * Magic GET function.
408
	 *
409
	 * @since  1.5
410
	 * @access public
411
	 *
412
	 * @param  string $key The property.
413
	 *
414
	 * @return mixed        The value.
415
	 */
416
	public function __get( $key ) {
417
418
		if ( method_exists( $this, 'get_' . $key ) ) {
419
420
			$value = call_user_func( array( $this, 'get_' . $key ) );
421
422
		} else {
423
424
			$value = $this->$key;
425
426
		}
427
428
		return $value;
429
	}
430
431
	/**
432
	 * Magic SET function
433
	 *
434
	 * Sets up the pending array for the save method
435
	 *
436
	 * @since  1.5
437
	 * @access public
438
	 *
439
	 * @param  string $key   The property name
440
	 * @param  mixed  $value The value of the property
441
	 */
442
	public function __set( $key, $value ) {
443
		$ignore = array( '_ID' );
444
445
		if ( $key === 'status' ) {
446
			$this->old_status = $this->status;
447
		}
448
449
		if ( ! in_array( $key, $ignore ) ) {
450
			$this->pending[ $key ] = $value;
451
		}
452
453
		if ( '_ID' !== $key ) {
454
			$this->$key = $value;
455
		}
456
	}
457
458
	/**
459
	 * Magic ISSET function, which allows empty checks on protected elements
460
	 *
461
	 * @since  1.5
462
	 * @access public
463
	 *
464
	 * @param  string $name The attribute to get
465
	 *
466
	 * @return boolean       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...
467
	 */
468
	public function __isset( $name ) {
469
		if ( property_exists( $this, $name ) ) {
470
			return false === empty( $this->$name );
471
		} else {
472
			return null;
473
		}
474
	}
475
476
	/**
477
	 * Setup payment properties
478
	 *
479
	 * @since  1.5
480
	 * @access private
481
	 *
482
	 * @param  int $payment_id The payment ID
483
	 *
484
	 * @return bool            If the setup was successful or not
485
	 */
486
	private function setup_payment( $payment_id ) {
487
		$this->pending = array();
488
489
		if ( empty( $payment_id ) ) {
490
			return false;
491
		}
492
493
		$payment = get_post( $payment_id );
494
495
		if ( ! $payment || is_wp_error( $payment ) ) {
496
			return false;
497
		}
498
499
		if ( 'give_payment' !== $payment->post_type ) {
500
			return false;
501
		}
502
503
		/**
504
		 * Fires before payment setup.
505
		 *
506
		 * Allow extensions to perform actions before the payment is loaded.
507
		 *
508
		 * @since 1.5
509
		 *
510
		 * @param Give_Payment $this       Payment object.
511
		 * @param int          $payment_id The ID of the payment.
512
		 */
513
		do_action( 'give_pre_setup_payment', $this, $payment_id );
514
515
		// Primary Identifier.
516
		$this->ID = absint( $payment_id );
517
518
		// Protected ID that can never be changed.
519
		$this->_ID = absint( $payment_id );
520
521
		// We have a payment, get the generic payment_meta item to reduce calls to it.
522
		$this->payment_meta = $this->get_meta();
523
524
		// Status and Dates.
525
		$this->date           = $payment->post_date;
526
		$this->post_date      = $payment->post_date;
527
		$this->completed_date = $this->setup_completed_date();
528
		$this->status         = $payment->post_status;
529
		$this->post_status    = $this->status;
530
		$this->mode           = $this->setup_mode();
531
		$this->parent_payment = $payment->post_parent;
532
533
		$all_payment_statuses  = give_get_payment_statuses();
534
		$this->status_nicename = array_key_exists( $this->status, $all_payment_statuses ) ? $all_payment_statuses[ $this->status ] : ucfirst( $this->status );
535
536
		// Items.
537
		$this->fees = $this->setup_fees();
538
539
		// Currency Based.
540
		$this->total      = $this->setup_total();
541
		$this->fees_total = $this->setup_fees_total();
542
		$this->subtotal   = $this->setup_subtotal();
543
		$this->currency   = $this->setup_currency();
544
545
		// Gateway based.
546
		$this->gateway        = $this->setup_gateway();
547
		$this->transaction_id = $this->setup_transaction_id();
548
549
		// User based.
550
		$this->ip          = $this->setup_ip();
551
		$this->customer_id = $this->setup_customer_id();
552
		$this->user_id     = $this->setup_user_id();
553
		$this->email       = $this->setup_email();
554
		$this->user_info   = $this->setup_user_info();
555
		$this->address     = $this->setup_address();
556
		$this->first_name  = $this->user_info['first_name'];
557
		$this->last_name   = $this->user_info['last_name'];
558
559
		// Other Identifiers.
560
		$this->form_title = $this->setup_form_title();
561
		$this->form_id    = $this->setup_form_id();
562
		$this->price_id   = $this->setup_price_id();
563
		$this->key        = $this->setup_payment_key();
564
		$this->number     = $this->setup_payment_number();
565
566
		/**
567
		 * Fires after payment setup.
568
		 *
569
		 * Allow extensions to add items to this object via hook.
570
		 *
571
		 * @since 1.5
572
		 *
573
		 * @param Give_Payment $this       Payment object.
574
		 * @param int          $payment_id The ID of the payment.
575
		 */
576
		do_action( 'give_setup_payment', $this, $payment_id );
577
578
		return true;
579
	}
580
581
	/**
582
	 * Payment class object is storing various meta value in object parameter.
583
	 * So if user is updating payment meta but not updating payment object, then payment meta values will not reflect/changes on payment meta automatically
584
	 * 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.
585
	 * To prevent that user can use this function after updating any payment meta value ( in bulk or single update ).
586
	 *
587
	 * @since  1.6
588
	 * @access public
589
	 *
590
	 * @param  int $payment_id Payment ID.
591
	 *
592
	 * @return void
593
	 */
594
	public function update_payment_setup( $payment_id ) {
595
		$this->setup_payment( $payment_id );
596
	}
597
598
	/**
599
	 * Create the base of a payment.
600
	 *
601
	 * @since  1.5
602
	 * @access private
603
	 *
604
	 * @return int|bool False on failure, the payment ID on success.
605
	 */
606
	private function insert_payment() {
607
608
		// Construct the payment title.
609
		$payment_title = '';
610
		if ( ! empty( $this->first_name ) && ! empty( $this->last_name ) ) {
611
			$payment_title = $this->first_name . ' ' . $this->last_name;
612
		} elseif ( ! empty( $this->first_name ) && empty( $this->last_name ) ) {
613
			$payment_title = $this->first_name;
614
		} elseif ( ! empty( $this->email ) && is_email( $this->email ) ) {
615
			$payment_title = $this->email;
616
		}
617
618
		// Set Key.
619
		if ( empty( $this->key ) ) {
620
621
			$auth_key             = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
622
			$this->key            = strtolower( md5( $this->email . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'give', true ) ) );  // Unique key
623
			$this->pending['key'] = $this->key;
624
		}
625
626
		// Set IP.
627
		if ( empty( $this->ip ) ) {
628
629
			$this->ip            = give_get_ip();
630
			$this->pending['ip'] = $this->ip;
631
632
		}
633
634
		$payment_data = array(
635
			'price'        => $this->total,
636
			'date'         => $this->date,
637
			'user_email'   => $this->email,
638
			'purchase_key' => $this->key,
639
			'form_title'   => $this->form_title,
640
			'form_id'      => $this->form_id,
641
			'price_id'     => $this->price_id,
642
			'currency'     => $this->currency,
643
			'user_info'    => array(
644
				'id'         => $this->user_id,
645
				'email'      => $this->email,
646
				'first_name' => $this->first_name,
647
				'last_name'  => $this->last_name,
648
				'address'    => $this->address,
649
			),
650
			'status'       => $this->status,
651
			'fees'         => $this->fees,
652
		);
653
654
		$args = apply_filters( 'give_insert_payment_args', array(
655
			'post_title'    => $payment_title,
656
			'post_status'   => $this->status,
657
			'post_type'     => 'give_payment',
658
			'post_date'     => ! empty( $this->date ) ? $this->date : null,
659
			'post_date_gmt' => ! empty( $this->date ) ? get_gmt_from_date( $this->date ) : null,
660
			'post_parent'   => $this->parent_payment,
661
		), $payment_data );
662
663
		// Create a blank payment
664
		$payment_id = wp_insert_post( $args );
665
666
		if ( ! empty( $payment_id ) ) {
667
668
			$this->ID  = $payment_id;
669
			$this->_ID = $payment_id;
670
671
			$customer = new stdClass;
672
673
			if ( did_action( 'give_pre_process_donation' ) && is_user_logged_in() ) {
674
				$customer = new Give_Customer( get_current_user_id(), true );
675
676
				// Customer is logged in but used a different email to purchase with so assign to their customer record
677
				if ( ! empty( $customer->id ) && $this->email != $customer->email ) {
678
					$customer->add_email( $this->email );
679
				}
680
			}
681
682
			if ( empty( $customer->id ) ) {
683
				$customer = new Give_Customer( $this->email );
684
			}
685
686
			if ( empty( $customer->id ) ) {
687
688
				$customer_data = array(
689
					'name'    => ! is_email( $payment_title ) ? $this->first_name . ' ' . $this->last_name : '',
690
					'email'   => $this->email,
691
					'user_id' => $this->user_id,
692
				);
693
694
				$customer->create( $customer_data );
0 ignored issues
show
Bug introduced by
The method create does only exist in Give_Customer, 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...
695
696
			}
697
698
			$this->customer_id            = $customer->id;
699
			$this->pending['customer_id'] = $this->customer_id;
700
			$customer->attach_payment( $this->ID, false );
0 ignored issues
show
Bug introduced by
The method attach_payment does only exist in Give_Customer, 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...
701
702
			$this->payment_meta = apply_filters( 'give_payment_meta', $this->payment_meta, $payment_data );
703
			if ( ! empty( $this->payment_meta['fees'] ) ) {
704
				$this->fees = array_merge( $this->fees, $this->payment_meta['fees'] );
705
				foreach ( $this->fees as $fee ) {
706
					$this->increase_fees( $fee['amount'] );
707
				}
708
			}
709
710
			$this->update_meta( '_give_payment_meta', $this->payment_meta );
711
			$this->new = true;
712
		}
713
714
		return $this->ID;
715
716
	}
717
718
	/**
719
	 * Save
720
	 *
721
	 * Once items have been set, an update is needed to save them to the database.
722
	 *
723
	 * @access public
724
	 *
725
	 * @return bool  True of the save occurred, false if it failed or wasn't needed
726
	 */
727
	public function save() {
728
729
		$saved = false;
730
731
		// Must have an ID.
732
		if ( empty( $this->ID ) ) {
733
734
			$payment_id = $this->insert_payment();
735
736
			if ( false === $payment_id ) {
737
				$saved = false;
738
			} else {
739
				$this->ID = $payment_id;
740
			}
741
		}
742
743
		// Set ID if not matching.
744
		if ( $this->ID !== $this->_ID ) {
745
			$this->ID = $this->_ID;
746
		}
747
748
		// If we have something pending, let's save it.
749
		if ( ! empty( $this->pending ) ) {
750
751
			$total_increase = 0;
752
			$total_decrease = 0;
753
754
			foreach ( $this->pending as $key => $value ) {
755
756
				switch ( $key ) {
757
758
					case 'donations':
759
						// Update totals for pending donations.
760
						foreach ( $this->pending[ $key ] as $item ) {
761
762
							$quantity = isset( $item['quantity'] ) ? $item['quantity'] : 1;
763
							$price_id = isset( $item['price_id'] ) ? $item['price_id'] : 0;
764
765
							switch ( $item['action'] ) {
766
767
								case 'add':
768
769
									$price = $item['price'];
770
771
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
772
773
										// Add sales logs.
774
										$log_date = date_i18n( 'Y-m-d G:i:s', current_time( 'timestamp' ) );
775
776
										$y = 0;
777
										while ( $y < $quantity ) {
778
779
											give_record_sale_in_log( $item['id'], $this->ID, $price_id, $log_date );
780
											$y ++;
781
										}
782
783
										$form = new Give_Donate_Form( $item['id'] );
784
										$form->increase_sales( $quantity );
785
										$form->increase_earnings( $price );
786
787
										$total_increase += $price;
788
									}
789
									break;
790
791
								case 'remove':
792
									$log_args = array(
793
										'post_type'   => 'give_log',
794
										'post_parent' => $item['id'],
795
										'numberposts' => $quantity,
796
										'meta_query'  => array(
797
											array(
798
												'key'     => '_give_log_payment_id',
799
												'value'   => $this->ID,
800
												'compare' => '=',
801
											),
802
											array(
803
												'key'     => '_give_log_price_id',
804
												'value'   => $price_id,
805
												'compare' => '=',
806
											),
807
										),
808
									);
809
810
									$found_logs = get_posts( $log_args );
811
									foreach ( $found_logs as $log ) {
812
										wp_delete_post( $log->ID, true );
813
									}
814
815
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
816
										$form = new Give_Donate_Form( $item['id'] );
817
										$form->decrease_sales( $quantity );
818
										$form->decrease_earnings( $item['amount'] );
819
820
										$total_decrease += $item['amount'];
821
									}
822
									break;
823
824
							}
825
						}
826
						break;
827
828
					case 'fees':
829
830
						if ( 'publish' !== $this->status && 'complete' !== $this->status ) {
831
							break;
832
						}
833
834
						if ( empty( $this->pending[ $key ] ) ) {
835
							break;
836
						}
837
838
						foreach ( $this->pending[ $key ] as $fee ) {
839
840
							switch ( $fee['action'] ) {
841
842
								case 'add':
843
									$total_increase += $fee['amount'];
844
									break;
845
846
								case 'remove':
847
									$total_decrease += $fee['amount'];
848
									break;
849
850
							}
851
						}
852
853
						break;
854
855
					case 'status':
856
						$this->update_status( $this->status );
857
						break;
858
859
					case 'gateway':
860
						$this->update_meta( '_give_payment_gateway', $this->gateway );
861
						break;
862
863
					case 'mode':
864
						$this->update_meta( '_give_payment_mode', $this->mode );
865
						break;
866
867
					case 'transaction_id':
868
						$this->update_meta( '_give_payment_transaction_id', $this->transaction_id );
869
						break;
870
871
					case 'ip':
872
						$this->update_meta( '_give_payment_user_ip', $this->ip );
873
						break;
874
875
					case 'customer_id':
876
						$this->update_meta( '_give_payment_customer_id', $this->customer_id );
877
						break;
878
879
					case 'user_id':
880
						$this->update_meta( '_give_payment_user_id', $this->user_id );
881
						break;
882
883
					case 'form_title':
884
						$this->update_meta( '_give_payment_form_title', $this->form_title );
885
						break;
886
887
					case 'form_id':
888
						$this->update_meta( '_give_payment_form_id', $this->form_id );
889
						break;
890
891
					case 'price_id':
892
						$this->update_meta( '_give_payment_price_id', $this->price_id );
893
						break;
894
895
					case 'first_name':
896
						$this->user_info['first_name'] = $this->first_name;
897
						break;
898
899
					case 'last_name':
900
						$this->user_info['last_name'] = $this->last_name;
901
						break;
902
903
					case 'address':
904
						$this->user_info['address'] = $this->address;
905
						break;
906
907
					case 'email':
908
						$this->update_meta( '_give_payment_user_email', $this->email );
909
						break;
910
911
					case 'key':
912
						$this->update_meta( '_give_payment_purchase_key', $this->key );
913
						break;
914
915
					case 'number':
916
						$this->update_meta( '_give_payment_number', $this->number );
917
						break;
918
919
					case 'date':
920
						$args = array(
921
							'ID'        => $this->ID,
922
							'post_date' => $this->date,
923
							'edit_date' => true,
924
						);
925
926
						wp_update_post( $args );
927
						break;
928
929
					case 'completed_date':
930
						$this->update_meta( '_give_completed_date', $this->completed_date );
931
						break;
932
933
					case 'parent_payment':
934
						$args = array(
935
							'ID'          => $this->ID,
936
							'post_parent' => $this->parent_payment,
937
						);
938
939
						wp_update_post( $args );
940
						break;
941
942
					default:
943
						/**
944
						 * Fires while saving payment.
945
						 *
946
						 * @since 1.7
947
						 *
948
						 * @param Give_Payment $this Payment object.
949
						 */
950
						do_action( 'give_payment_save', $this, $key );
951
						break;
952
				}
953
			}
954
955
			if ( 'pending' !== $this->status ) {
956
957
				$customer = new Give_Customer( $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 customer's donation stats.
964
					$customer->decrease_value( $total_change );
965
					give_decrease_total_earnings( $total_change );
966
967
				} elseif ( $total_change > 0 ) {
968
969
					// Increase the customer's donation stats.
970
					$customer->increase_value( $total_change );
971
					give_increase_total_earnings( $total_change );
972
973
				}
974
			}
975
976
			$this->update_meta( '_give_payment_total', $this->total );
977
978
			$new_meta = array(
979
				'form_title' => $this->form_title,
980
				'form_id'    => $this->form_id,
981
				'price_id'   => $this->price_id,
982
				'fees'       => $this->fees,
983
				'currency'   => $this->currency,
984
				'user_info'  => $this->user_info,
985
			);
986
987
			$meta        = $this->get_meta();
988
			$merged_meta = array_merge( $meta, $new_meta );
989
990
			// Only save the payment meta if it's changed.
991
			if ( md5( serialize( $meta ) ) !== md5( serialize( $merged_meta ) ) ) {
992
				$updated = $this->update_meta( '_give_payment_meta', $merged_meta );
993
				if ( false !== $updated ) {
994
					$saved = true;
995
				}
996
			}
997
998
			$this->pending = array();
999
			$saved         = true;
1000
		}
1001
1002
		if ( true === $saved ) {
1003
			$this->setup_payment( $this->ID );
1004
		}
1005
1006
		return $saved;
1007
	}
1008
1009
	/**
1010
	 * Add a donation to a given payment
1011
	 *
1012
	 * @since  1.5
1013
	 * @access public
1014
	 *
1015
	 * @param  int   $form_id The donation form to add
1016
	 * @param  array $args    Other arguments to pass to the function
1017
	 * @param  array $options List of donation options
1018
	 *
1019
	 * @return bool           True when successful, false otherwise
1020
	 */
1021
	public function add_donation( $form_id = 0, $args = array(), $options = array() ) {
1022
1023
		$donation = new Give_Donate_Form( $form_id );
1024
1025
		// Bail if this post isn't a give donation form.
1026
		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...
1027
			return false;
1028
		}
1029
1030
		// Set some defaults.
1031
		$defaults = array(
1032
			'price'    => false,
1033
			'price_id' => false,
1034
			'fees'     => array(),
1035
		);
1036
1037
		$args = wp_parse_args( apply_filters( 'give_payment_add_donation_args', $args, $donation->ID ), $defaults );
1038
1039
		// Allow overriding the price.
1040
		if ( false !== $args['price'] ) {
1041
			$item_price = $args['price'];
1042
		} else {
1043
1044
			// Deal with variable pricing.
1045
			if ( give_has_variable_prices( $donation->ID ) ) {
1046
				$prices     = maybe_unserialize( get_post_meta( $form_id, '_give_donation_levels', true ) );
1047
				$item_price = '';
1048
				// Loop through prices.
1049
				foreach ( $prices as $price ) {
1050
					// Find a match between price_id and level_id.
1051
					// First verify array keys exists THEN make the match.
1052
					if ( ( isset( $args['price_id'] ) && isset( $price['_give_id']['level_id'] ) )
1053
					     && $args['price_id'] == $price['_give_id']['level_id']
1054
					) {
1055
						$item_price = $price['_give_amount'];
1056
					}
1057
				}
1058
				// Fallback to the lowest price point.
1059
				if ( $item_price == '' ) {
1060
					$item_price       = give_get_lowest_price_option( $donation->ID );
1061
					$args['price_id'] = give_get_lowest_price_id( $donation->ID );
1062
				}
1063
			} else {
1064
				// Simple form price.
1065
				$item_price = give_get_form_price( $donation->ID );
1066
			}
1067
		}
1068
1069
		// Sanitizing the price here so we don't have a dozen calls later.
1070
		$item_price = give_sanitize_amount( $item_price );
1071
		$total      = round( $item_price, give_currency_decimal_filter() );
1072
1073
		// Add Options.
1074
		$default_options = array();
1075
		if ( false !== $args['price_id'] ) {
1076
			$default_options['price_id'] = (int) $args['price_id'];
1077
		}
1078
		$options = wp_parse_args( $options, $default_options );
1079
1080
		// Do not allow totals to go negative.
1081
		if ( $total < 0 ) {
1082
			$total = 0;
1083
		}
1084
1085
		$donation = array(
1086
			'name'     => $donation->post_title,
1087
			'id'       => $donation->ID,
1088
			'price'    => round( $total, give_currency_decimal_filter() ),
1089
			'subtotal' => round( $total, give_currency_decimal_filter() ),
1090
			'fees'     => $args['fees'],
1091
			'price_id' => $args['price_id'],
1092
			'action'   => 'add',
1093
			'options'  => $options,
1094
		);
1095
1096
		$this->pending['donations'][] = $donation;
1097
1098
		$this->increase_subtotal( $total );
1099
1100
		return true;
1101
1102
	}
1103
1104
	/**
1105
	 * Remove a donation from the payment
1106
	 *
1107
	 * @since  1.5
1108
	 * @access public
1109
	 *
1110
	 * @param  int   $form_id The form ID to remove
1111
	 * @param  array $args    Arguments to pass to identify (quantity, amount, price_id)
1112
	 *
1113
	 * @return bool           If the item was removed or not
1114
	 */
1115
	public function remove_donation( $form_id, $args = array() ) {
1116
1117
		// Set some defaults.
1118
		$defaults = array(
1119
			'quantity' => 1,
1120
			'price'    => false,
1121
			'price_id' => false,
1122
		);
1123
		$args     = wp_parse_args( $args, $defaults );
1124
1125
		$form = new Give_Donate_Form( $form_id );
1126
1127
		// Bail if this post isn't a valid give donation form.
1128
		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...
1129
			return false;
1130
		}
1131
1132
		$pending_args             = $args;
1133
		$pending_args['id']       = $form_id;
1134
		$pending_args['amount']   = $this->total;
1135
		$pending_args['price_id'] = false !== $args['price_id'] ? (int) $args['price_id'] : false;
1136
		$pending_args['quantity'] = $args['quantity'];
1137
		$pending_args['action']   = 'remove';
1138
1139
		$this->pending['donations'][] = $pending_args;
1140
1141
		$this->decrease_subtotal( $this->total );
1142
1143
		return true;
1144
	}
1145
1146
	/**
1147
	 * Add a fee to a given payment
1148
	 *
1149
	 * @since  1.5
1150
	 * @access public
1151
	 *
1152
	 * @param  array $args Array of arguments for the fee to add
1153
	 * @param  bool  $global
1154
	 *
1155
	 * @return bool          If the fee was added
1156
	 */
1157
	public function add_fee( $args, $global = true ) {
0 ignored issues
show
Unused Code introduced by
The parameter $global is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1158
1159
		$default_args = array(
1160
			'label'    => '',
1161
			'amount'   => 0,
1162
			'type'     => 'fee',
1163
			'id'       => '',
1164
			'price_id' => 0,
1165
		);
1166
1167
		$fee          = wp_parse_args( $args, $default_args );
1168
		$this->fees[] = $fee;
1169
1170
		$added_fee               = $fee;
1171
		$added_fee['action']     = 'add';
1172
		$this->pending['fees'][] = $added_fee;
1173
		reset( $this->fees );
1174
1175
		$this->increase_fees( $fee['amount'] );
1176
1177
		return true;
1178
	}
1179
1180
	/**
1181
	 * Remove a fee from the payment
1182
	 *
1183
	 * @since  1.5
1184
	 * @access public
1185
	 *
1186
	 * @param  int $key The array key index to remove
1187
	 *
1188
	 * @return bool     If the fee was removed successfully
1189
	 */
1190
	public function remove_fee( $key ) {
1191
		$removed = false;
1192
1193
		if ( is_numeric( $key ) ) {
1194
			$removed = $this->remove_fee_by( 'index', $key );
1195
		}
1196
1197
		return $removed;
1198
	}
1199
1200
	/**
1201
	 * Remove a fee by the defined attributed
1202
	 *
1203
	 * @since  1.5
1204
	 * @access public
1205
	 *
1206
	 * @param  string     $key    The key to remove by
1207
	 * @param  int|string $value  The value to search for
1208
	 * @param  boolean    $global False - removes the first value it fines,
1209
	 *                            True - removes all matches.
1210
	 *
1211
	 * @return boolean            If the item is removed
1212
	 */
1213
	public function remove_fee_by( $key, $value, $global = false ) {
1214
1215
		$allowed_fee_keys = apply_filters( 'give_payment_fee_keys', array(
1216
			'index',
1217
			'label',
1218
			'amount',
1219
			'type',
1220
		) );
1221
1222
		if ( ! in_array( $key, $allowed_fee_keys ) ) {
1223
			return false;
1224
		}
1225
1226
		$removed = false;
1227
		if ( 'index' === $key && array_key_exists( $value, $this->fees ) ) {
1228
1229
			$removed_fee             = $this->fees[ $value ];
1230
			$removed_fee['action']   = 'remove';
1231
			$this->pending['fees'][] = $removed_fee;
1232
1233
			$this->decrease_fees( $removed_fee['amount'] );
1234
1235
			unset( $this->fees[ $value ] );
1236
			$removed = true;
1237
1238
		} elseif ( 'index' !== $key ) {
1239
1240
			foreach ( $this->fees as $index => $fee ) {
1241
1242
				if ( isset( $fee[ $key ] ) && $fee[ $key ] == $value ) {
1243
1244
					$removed_fee             = $fee;
1245
					$removed_fee['action']   = 'remove';
1246
					$this->pending['fees'][] = $removed_fee;
1247
1248
					$this->decrease_fees( $removed_fee['amount'] );
1249
1250
					unset( $this->fees[ $index ] );
1251
					$removed = true;
1252
1253
					if ( false === $global ) {
1254
						break;
1255
					}
1256
				}
1257
			}
1258
		}
1259
1260
		if ( true === $removed ) {
1261
			$this->fees = array_values( $this->fees );
1262
		}
1263
1264
		return $removed;
1265
	}
1266
1267
	/**
1268
	 * Get the fees, filterable by type
1269
	 *
1270
	 * @since  1.5
1271
	 * @access public
1272
	 *
1273
	 * @param  string $type All, item, fee
1274
	 *
1275
	 * @return array        The Fees for the type specified
1276
	 */
1277
	public function get_fees( $type = 'all' ) {
1278
		$fees = array();
1279
1280
		if ( ! empty( $this->fees ) && is_array( $this->fees ) ) {
1281
1282
			foreach ( $this->fees as $fee_id => $fee ) {
1283
1284
				if ( 'all' != $type && ! empty( $fee['type'] ) && $type != $fee['type'] ) {
1285
					continue;
1286
				}
1287
1288
				$fee['id'] = $fee_id;
1289
				$fees[]    = $fee;
1290
1291
			}
1292
		}
1293
1294
		return apply_filters( 'give_get_payment_fees', $fees, $this->ID, $this );
1295
	}
1296
1297
	/**
1298
	 * Add a note to a payment
1299
	 *
1300
	 * @since  1.5
1301
	 * @access public
1302
	 *
1303
	 * @param  string $note The note to add
1304
	 *
1305
	 * @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...
1306
	 */
1307
	public function add_note( $note = false ) {
1308
		// Bail if no note specified.
1309
		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...
1310
			return false;
1311
		}
1312
1313
		give_insert_payment_note( $this->ID, $note );
1314
	}
1315
1316
	/**
1317
	 * Increase the payment's subtotal
1318
	 *
1319
	 * @since  1.5
1320
	 * @access private
1321
	 *
1322
	 * @param  float $amount The amount to increase the payment subtotal by.
1323
	 *
1324
	 * @return void
1325
	 */
1326
	private function increase_subtotal( $amount = 0.00 ) {
1327
		$amount = (float) $amount;
1328
		$this->subtotal += $amount;
1329
1330
		$this->recalculate_total();
1331
	}
1332
1333
	/**
1334
	 * Decrease the payment's subtotal.
1335
	 *
1336
	 * @since  1.5
1337
	 * @access private
1338
	 *
1339
	 * @param  float $amount The amount to decrease the payment subtotal by.
1340
	 *
1341
	 * @return void
1342
	 */
1343
	private function decrease_subtotal( $amount = 0.00 ) {
1344
		$amount = (float) $amount;
1345
		$this->subtotal -= $amount;
1346
1347
		if ( $this->subtotal < 0 ) {
1348
			$this->subtotal = 0;
1349
		}
1350
1351
		$this->recalculate_total();
1352
	}
1353
1354
	/**
1355
	 * Increase the payment's subtotal.
1356
	 *
1357
	 * @since  1.5
1358
	 * @access private
1359
	 *
1360
	 * @param  float $amount The amount to increase the payment subtotal by.
1361
	 *
1362
	 * @return void
1363
	 */
1364
	private function increase_fees( $amount = 0.00 ) {
1365
		$amount = (float) $amount;
1366
		$this->fees_total += $amount;
1367
1368
		$this->recalculate_total();
1369
	}
1370
1371
	/**
1372
	 * Decrease the payment's subtotal.
1373
	 *
1374
	 * @since  1.5
1375
	 * @access private
1376
	 *
1377
	 * @param  float $amount The amount to decrease the payment subtotal by.
1378
	 *
1379
	 * @return void
1380
	 */
1381
	private function decrease_fees( $amount = 0.00 ) {
1382
		$amount = (float) $amount;
1383
		$this->fees_total -= $amount;
1384
1385
		if ( $this->fees_total < 0 ) {
1386
			$this->fees_total = 0;
1387
		}
1388
1389
		$this->recalculate_total();
1390
	}
1391
1392
	/**
1393
	 * Set or update the total for a payment.
1394
	 *
1395
	 * @since  1.5
1396
	 * @access private
1397
	 *
1398
	 * @return void
1399
	 */
1400
	private function recalculate_total() {
1401
		$this->total = $this->subtotal + $this->fees_total;
1402
	}
1403
1404
	/**
1405
	 * Set the payment status and run any status specific changes necessary.
1406
	 *
1407
	 * @since  1.5
1408
	 * @access public
1409
	 *
1410
	 * @param  string|bool $status The status to set the payment to.
1411
	 *
1412
	 * @return bool   $updated Returns if the status was successfully updated.
1413
	 */
1414
	public function update_status( $status = false ) {
1415
1416
		// standardize the 'complete(d)' status.
1417
		if ( $status == 'completed' || $status == 'complete' ) {
1418
			$status = 'publish';
1419
		}
1420
1421
		$old_status = ! empty( $this->old_status ) ? $this->old_status : false;
1422
1423
		if ( $old_status === $status ) {
1424
			return false; // Don't permit status changes that aren't changes.
1425
		}
1426
1427
		$do_change = apply_filters( 'give_should_update_payment_status', true, $this->ID, $status, $old_status );
1428
1429
		$updated = false;
1430
1431
		if ( $do_change ) {
1432
1433
			/**
1434
			 * Fires before changing payment status.
1435
			 *
1436
			 * @since 1.5
1437
			 *
1438
			 * @param int    $payment_id Payments ID.
1439
			 * @param string $status     The new status.
1440
			 * @param string $old_status The old status.
1441
			 */
1442
			do_action( 'give_before_payment_status_change', $this->ID, $status, $old_status );
1443
1444
			$update_fields = array(
1445
				'ID'          => $this->ID,
1446
				'post_status' => $status,
1447
				'edit_date'   => current_time( 'mysql' ),
1448
			);
1449
1450
			$updated = wp_update_post( apply_filters( 'give_update_payment_status_fields', $update_fields ) );
1451
1452
			$all_payment_statuses  = give_get_payment_statuses();
1453
			$this->status_nicename = array_key_exists( $status, $all_payment_statuses ) ? $all_payment_statuses[ $status ] : ucfirst( $status );
1454
1455
			// Process any specific status functions.
1456
			switch ( $status ) {
1457
				case 'refunded':
1458
					$this->process_refund();
1459
					break;
1460
				case 'failed':
1461
					$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...
1462
					break;
1463
				case 'pending':
1464
					$this->process_pending();
1465
					break;
1466
				case 'cancelled':
1467
					$this->process_cancelled();
1468
					break;
1469
				case 'revoked':
1470
					$this->process_revoked();
1471
					break;
1472
			}
1473
1474
			/**
1475
			 * Fires after changing payment status.
1476
			 *
1477
			 * @since 1.5
1478
			 *
1479
			 * @param int    $payment_id Payment ID.
1480
			 * @param string $status     The new status.
1481
			 * @param string $old_status The old status.
1482
			 */
1483
			do_action( 'give_update_payment_status', $this->ID, $status, $old_status );
1484
1485
		}
1486
1487
		return $updated;
1488
1489
	}
1490
1491
	/**
1492
	 * Change the status of the payment to refunded, and run the necessary changes
1493
	 *
1494
	 * @since  1.5
1495
	 * @access public
1496
	 *
1497
	 * @return void
1498
	 */
1499
	public function refund() {
1500
		$this->old_status        = $this->status;
1501
		$this->status            = 'refunded';
1502
		$this->pending['status'] = $this->status;
1503
1504
		$this->save();
1505
	}
1506
1507
	/**
1508
	 * Get a post meta item for the payment
1509
	 *
1510
	 * @since  1.5
1511
	 * @access public
1512
	 *
1513
	 * @param  string  $meta_key The Meta Key
1514
	 * @param  boolean $single   Return single item or array
1515
	 *
1516
	 * @return mixed             The value from the post meta
1517
	 */
1518
	public function get_meta( $meta_key = '_give_payment_meta', $single = true ) {
1519
1520
		$meta = get_post_meta( $this->ID, $meta_key, $single );
1521
1522
		if ( $meta_key === '_give_payment_meta' ) {
1523
1524
			if ( empty( $meta['key'] ) ) {
1525
				$meta['key'] = $this->setup_payment_key();
1526
			}
1527
1528
			if ( empty( $meta['form_title'] ) ) {
1529
				$meta['form_title'] = $this->setup_form_title();
1530
			}
1531
1532
			if ( empty( $meta['email'] ) ) {
1533
				$meta['email'] = $this->setup_email();
1534
			}
1535
1536
			if ( empty( $meta['date'] ) ) {
1537
				$meta['date'] = get_post_field( 'post_date', $this->ID );
1538
			}
1539
		}
1540
1541
		$meta = apply_filters( "give_get_payment_meta_{$meta_key}", $meta, $this->ID );
1542
1543
		return apply_filters( 'give_get_payment_meta', $meta, $this->ID, $meta_key );
1544
	}
1545
1546
	/**
1547
	 * Update the post meta
1548
	 *
1549
	 * @since  1.5
1550
	 * @access public
1551
	 *
1552
	 * @param  string $meta_key   The meta key to update
1553
	 * @param  string $meta_value The meta value
1554
	 * @param  string $prev_value Previous meta value
1555
	 *
1556
	 * @return int|bool           Meta ID if the key didn't exist, true on successful update, false on failure
1557
	 */
1558
	public function update_meta( $meta_key = '', $meta_value = '', $prev_value = '' ) {
1559
		if ( empty( $meta_key ) ) {
1560
			return false;
1561
		}
1562
1563
		if ( $meta_key == 'key' || $meta_key == 'date' ) {
1564
1565
			$current_meta              = $this->get_meta();
1566
			$current_meta[ $meta_key ] = $meta_value;
1567
1568
			$meta_key   = '_give_payment_meta';
1569
			$meta_value = $current_meta;
1570
1571
		} elseif ( $meta_key == 'email' || $meta_key == '_give_payment_user_email' ) {
1572
1573
			$meta_value = apply_filters( "give_give_update_payment_meta_{$meta_key}", $meta_value, $this->ID );
1574
			update_post_meta( $this->ID, '_give_payment_user_email', $meta_value );
1575
1576
			$current_meta                       = $this->get_meta();
1577
			$current_meta['user_info']['email'] = $meta_value;
1578
1579
			$meta_key   = '_give_payment_meta';
1580
			$meta_value = $current_meta;
1581
1582
		}
1583
1584
		$meta_value = apply_filters( "give_update_payment_meta_{$meta_key}", $meta_value, $this->ID );
1585
1586
		return update_post_meta( $this->ID, $meta_key, $meta_value, $prev_value );
1587
	}
1588
1589
	/**
1590
	 * When a payment is set to a status of 'refunded' process the necessary actions to reduce stats
1591
	 *
1592
	 * @since  1.5
1593
	 * @access private
1594
	 *
1595
	 * @return void
1596
	 */
1597
	private function process_refund() {
1598
		$process_refund = true;
1599
1600
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1601
		if ( 'publish' != $this->old_status || 'refunded' != $this->status ) {
1602
			$process_refund = false;
1603
		}
1604
1605
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1606
		$process_refund = apply_filters( 'give_should_process_refund', $process_refund, $this );
1607
1608
		if ( false === $process_refund ) {
1609
			return;
1610
		}
1611
1612
		/**
1613
		 * Fires before refunding payment.
1614
		 *
1615
		 * @since 1.5
1616
		 *
1617
		 * @param Give_Payment $this Payment object.
1618
		 */
1619
		do_action( 'give_pre_refund_payment', $this );
1620
1621
		$decrease_store_earnings = apply_filters( 'give_decrease_store_earnings_on_refund', true, $this );
1622
		$decrease_customer_value = apply_filters( 'give_decrease_customer_value_on_refund', true, $this );
1623
		$decrease_purchase_count = apply_filters( 'give_decrease_customer_purchase_count_on_refund', true, $this );
1624
1625
		$this->maybe_alter_stats( $decrease_store_earnings, $decrease_customer_value, $decrease_purchase_count );
1626
		$this->delete_sales_logs();
1627
1628
		// Clear the This Month earnings (this_monththis_month is NOT a typo).
1629
		delete_transient( md5( 'give_earnings_this_monththis_month' ) );
1630
1631
		/**
1632
		 * Fires after refunding payment.
1633
		 *
1634
		 * @since 1.5
1635
		 *
1636
		 * @param Give_Payment $this Payment object.
1637
		 */
1638
		do_action( 'give_post_refund_payment', $this );
1639
	}
1640
1641
	/**
1642
	 * Process when a payment is set to failed
1643
	 *
1644
	 * @since  1.5
1645
	 * @access private
1646
	 *
1647
	 * @return void
1648
	 */
1649
	private function process_failure() {
1650
1651
	}
1652
1653
	/**
1654
	 * Process when a payment moves to pending
1655
	 *
1656
	 * @since  1.5
1657
	 * @access private
1658
	 *
1659
	 * @return void
1660
	 */
1661
	private function process_pending() {
1662
		$process_pending = true;
1663
1664
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1665
		if ( 'publish' != $this->old_status || 'pending' != $this->status ) {
1666
			$process_pending = false;
1667
		}
1668
1669
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1670
		$process_pending = apply_filters( 'give_should_process_pending', $process_pending, $this );
1671
1672
		if ( false === $process_pending ) {
1673
			return;
1674
		}
1675
1676
		$decrease_store_earnings = apply_filters( 'give_decrease_store_earnings_on_pending', true, $this );
1677
		$decrease_customer_value = apply_filters( 'give_decrease_customer_value_on_pending', true, $this );
1678
		$decrease_purchase_count = apply_filters( 'give_decrease_customer_purchase_count_on_pending', true, $this );
1679
1680
		$this->maybe_alter_stats( $decrease_store_earnings, $decrease_customer_value, $decrease_purchase_count );
1681
		$this->delete_sales_logs();
1682
1683
		$this->completed_date = false;
1684
		$this->update_meta( '_give_completed_date', '' );
1685
1686
		// Clear the This Month earnings (this_monththis_month is NOT a typo).
1687
		delete_transient( md5( 'give_earnings_this_monththis_month' ) );
1688
	}
1689
1690
	/**
1691
	 * Process when a payment moves to cancelled
1692
	 *
1693
	 * @since  1.5
1694
	 * @access private
1695
	 *
1696
	 * @return void
1697
	 */
1698
	private function process_cancelled() {
1699
		$process_cancelled = true;
1700
1701
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1702
		if ( 'publish' != $this->old_status || 'cancelled' != $this->status ) {
1703
			$process_cancelled = false;
1704
		}
1705
1706
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1707
		$process_cancelled = apply_filters( 'give_should_process_cancelled', $process_cancelled, $this );
1708
1709
		if ( false === $process_cancelled ) {
1710
			return;
1711
		}
1712
1713
		$decrease_store_earnings = apply_filters( 'give_decrease_store_earnings_on_cancelled', true, $this );
1714
		$decrease_customer_value = apply_filters( 'give_decrease_customer_value_on_cancelled', true, $this );
1715
		$decrease_purchase_count = apply_filters( 'give_decrease_customer_purchase_count_on_cancelled', true, $this );
1716
1717
		$this->maybe_alter_stats( $decrease_store_earnings, $decrease_customer_value, $decrease_purchase_count );
1718
		$this->delete_sales_logs();
1719
1720
		$this->completed_date = false;
1721
		$this->update_meta( '_give_completed_date', '' );
1722
1723
		// Clear the This Month earnings (this_monththis_month is NOT a typo).
1724
		delete_transient( md5( 'give_earnings_this_monththis_month' ) );
1725
	}
1726
1727
	/**
1728
	 * Process when a payment moves to revoked
1729
	 *
1730
	 * @since  1.5
1731
	 * @return void
1732
	 */
1733
	private function process_revoked() {
1734
		$process_revoked = true;
1735
1736
		// If the payment was not in publish, don't decrement stats as they were never incremented.
1737
		if ( 'publish' != $this->old_status || 'revoked' != $this->status ) {
1738
			$process_revoked = false;
1739
		}
1740
1741
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1742
		$process_revoked = apply_filters( 'give_should_process_revoked', $process_revoked, $this );
1743
1744
		if ( false === $process_revoked ) {
1745
			return;
1746
		}
1747
1748
		$decrease_store_earnings = apply_filters( 'give_decrease_store_earnings_on_revoked', true, $this );
1749
		$decrease_customer_value = apply_filters( 'give_decrease_customer_value_on_revoked', true, $this );
1750
		$decrease_purchase_count = apply_filters( 'give_decrease_customer_purchase_count_on_revoked', true, $this );
1751
1752
		$this->maybe_alter_stats( $decrease_store_earnings, $decrease_customer_value, $decrease_purchase_count );
1753
		$this->delete_sales_logs();
1754
1755
		$this->completed_date = false;
1756
		$this->update_meta( '_give_completed_date', '' );
1757
1758
		// Clear the This Month earnings (this_monththis_month is NOT a typo).
1759
		delete_transient( md5( 'give_earnings_this_monththis_month' ) );
1760
	}
1761
1762
	/**
1763
	 * Used during the process of moving to refunded or pending, to decrement stats
1764
	 *
1765
	 * @since  1.5
1766
	 * @access private
1767
	 *
1768
	 * @param  bool $alter_store_earnings          If the method should alter the store earnings
1769
	 * @param  bool $alter_customer_value          If the method should reduce the customer value
1770
	 * @param  bool $alter_customer_purchase_count If the method should reduce the customer's purchase count
1771
	 *
1772
	 * @return void
1773
	 */
1774
	private function maybe_alter_stats( $alter_store_earnings, $alter_customer_value, $alter_customer_purchase_count ) {
1775
1776
		give_undo_purchase( false, $this->ID );
1777
1778
		// Decrease store earnings.
1779
		if ( true === $alter_store_earnings ) {
1780
			give_decrease_total_earnings( $this->total );
1781
		}
1782
1783
		// Decrement the stats for the customer.
1784
		if ( ! empty( $this->customer_id ) ) {
1785
1786
			$customer = new Give_Customer( $this->customer_id );
1787
1788
			if ( true === $alter_customer_value ) {
1789
				$customer->decrease_value( $this->total );
1790
			}
1791
1792
			if ( true === $alter_customer_purchase_count ) {
1793
				$customer->decrease_purchase_count();
1794
			}
1795
		}
1796
1797
	}
1798
1799
	/**
1800
	 * Delete sales logs for this donation
1801
	 *
1802
	 * @since  1.5
1803
	 * @access private
1804
	 *
1805
	 * @return void
1806
	 */
1807
	private function delete_sales_logs() {
1808
		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...
1809
1810
		// Remove related sale log entries.
1811
		$give_logs->delete_logs(
1812
			null,
1813
			'sale',
1814
			array(
1815
				array(
1816
					'key'   => '_give_log_payment_id',
1817
					'value' => $this->ID,
1818
				),
1819
			)
1820
		);
1821
	}
1822
1823
	/**
1824
	 * Setup functions only, these are not to be used by developers.
1825
	 * These functions exist only to allow the setup routine to be backwards compatible with our old
1826
	 * helper functions.
1827
	 *
1828
	 * These will run whenever setup_payment is called, which should only be called once.
1829
	 * To update an attribute, update it directly instead of re-running the setup routine
1830
	 */
1831
1832
	/**
1833
	 * Setup the payment completed date
1834
	 *
1835
	 * @since  1.5
1836
	 * @access private
1837
	 *
1838
	 * @return string The date the payment was completed
1839
	 */
1840
	private function setup_completed_date() {
1841
		$payment = get_post( $this->ID );
1842
1843
		if ( 'pending' == $payment->post_status || 'preapproved' == $payment->post_status ) {
1844
			return false; // This payment was never completed.
1845
		}
1846
1847
		$date = ( $date = $this->get_meta( '_give_completed_date', true ) ) ? $date : $payment->modified_date;
1848
1849
		return $date;
1850
	}
1851
1852
	/**
1853
	 * Setup the payment mode
1854
	 *
1855
	 * @since  1.5
1856
	 * @access private
1857
	 *
1858
	 * @return string The payment mode
1859
	 */
1860
	private function setup_mode() {
1861
		return $this->get_meta( '_give_payment_mode' );
1862
	}
1863
1864
	/**
1865
	 * Setup the payment total
1866
	 *
1867
	 * @since  1.5
1868
	 * @access private
1869
	 *
1870
	 * @return float The payment total
1871
	 */
1872
	private function setup_total() {
1873
		$amount = $this->get_meta( '_give_payment_total', true );
1874
1875
		if ( empty( $amount ) && '0.00' != $amount ) {
1876
			$meta = $this->get_meta( '_give_payment_meta', true );
1877
			$meta = maybe_unserialize( $meta );
1878
1879
			if ( isset( $meta['amount'] ) ) {
1880
				$amount = $meta['amount'];
1881
			}
1882
		}
1883
1884
		return $amount;
1885
	}
1886
1887
	/**
1888
	 * Setup the payment subtotal
1889
	 *
1890
	 * @since  1.5
1891
	 * @access private
1892
	 *
1893
	 * @return float The subtotal of the payment
1894
	 */
1895
	private function setup_subtotal() {
1896
		$subtotal = $this->total;
1897
1898
		return $subtotal;
1899
	}
1900
1901
	/**
1902
	 * Setup the payment fees
1903
	 *
1904
	 * @since  1.5
1905
	 * @access private
1906
	 *
1907
	 * @return float The fees total for the payment
1908
	 */
1909
	private function setup_fees_total() {
1910
		$fees_total = (float) 0.00;
1911
1912
		$payment_fees = isset( $this->payment_meta['fees'] ) ? $this->payment_meta['fees'] : array();
1913
		if ( ! empty( $payment_fees ) ) {
1914
			foreach ( $payment_fees as $fee ) {
1915
				$fees_total += (float) $fee['amount'];
1916
			}
1917
		}
1918
1919
		return $fees_total;
1920
1921
	}
1922
1923
	/**
1924
	 * Setup the currency code
1925
	 *
1926
	 * @since  1.5
1927
	 * @access private
1928
	 *
1929
	 * @return string The currency for the payment
1930
	 */
1931
	private function setup_currency() {
1932
		$currency = isset( $this->payment_meta['currency'] ) ? $this->payment_meta['currency'] : apply_filters( 'give_payment_currency_default', give_get_currency(), $this );
1933
1934
		return $currency;
1935
	}
1936
1937
	/**
1938
	 * Setup any fees associated with the payment
1939
	 *
1940
	 * @since  1.5
1941
	 * @access private
1942
	 *
1943
	 * @return array The Fees
1944
	 */
1945
	private function setup_fees() {
1946
		$payment_fees = isset( $this->payment_meta['fees'] ) ? $this->payment_meta['fees'] : array();
1947
1948
		return $payment_fees;
1949
	}
1950
1951
	/**
1952
	 * Setup the gateway used for the payment
1953
	 *
1954
	 * @since  1.5
1955
	 * @access private
1956
	 *
1957
	 * @return string The gateway
1958
	 */
1959
	private function setup_gateway() {
1960
		$gateway = $this->get_meta( '_give_payment_gateway', true );
1961
1962
		return $gateway;
1963
	}
1964
1965
	/**
1966
	 * Setup the donation ID
1967
	 *
1968
	 * @since  1.5
1969
	 * @access private
1970
	 *
1971
	 * @return string The donation ID
1972
	 */
1973
	private function setup_transaction_id() {
1974
		$transaction_id = $this->get_meta( '_give_payment_transaction_id', true );
1975
1976
		if ( empty( $transaction_id ) || (int) $transaction_id === (int) $this->ID ) {
1977
1978
			$gateway        = $this->gateway;
1979
			$transaction_id = apply_filters( "give_get_payment_transaction_id-{$gateway}", $this->ID );
1980
1981
		}
1982
1983
		return $transaction_id;
1984
	}
1985
1986
	/**
1987
	 * Setup the IP Address for the payment
1988
	 *
1989
	 * @since  1.5
1990
	 * @access private
1991
	 *
1992
	 * @return string The IP address for the payment
1993
	 */
1994
	private function setup_ip() {
1995
		$ip = $this->get_meta( '_give_payment_user_ip', true );
1996
1997
		return $ip;
1998
	}
1999
2000
	/**
2001
	 * Setup the customer ID
2002
	 *
2003
	 * @since  1.5
2004
	 * @access private
2005
	 *
2006
	 * @return int The Customer ID
2007
	 */
2008
	private function setup_customer_id() {
2009
		$customer_id = $this->get_meta( '_give_payment_customer_id', true );
2010
2011
		return $customer_id;
2012
	}
2013
2014
	/**
2015
	 * Setup the User ID associated with the donation
2016
	 *
2017
	 * @since  1.5
2018
	 * @access private
2019
	 *
2020
	 * @return int The User ID
2021
	 */
2022
	private function setup_user_id() {
2023
		$user_id = $this->get_meta( '_give_payment_user_id', true );
2024
2025
		return $user_id;
2026
	}
2027
2028
	/**
2029
	 * Setup the email address for the donation
2030
	 *
2031
	 * @since  1.5
2032
	 * @access private
2033
	 *
2034
	 * @return string The email address for the payment
2035
	 */
2036
	private function setup_email() {
2037
		$email = $this->get_meta( '_give_payment_user_email', true );
2038
2039
		if ( empty( $email ) ) {
2040
			$email = Give()->customers->get_column( 'email', $this->customer_id );
2041
		}
2042
2043
		return $email;
2044
	}
2045
2046
	/**
2047
	 * Setup the user info
2048
	 *
2049
	 * @since  1.5
2050
	 * @access private
2051
	 *
2052
	 * @return array The user info associated with the payment
2053
	 */
2054
	private function setup_user_info() {
2055
		$defaults = array(
2056
			'first_name' => $this->first_name,
2057
			'last_name'  => $this->last_name,
2058
		);
2059
2060
		$user_info = isset( $this->payment_meta['user_info'] ) ? maybe_unserialize( $this->payment_meta['user_info'] ) : array();
2061
		$user_info = wp_parse_args( $user_info, $defaults );
2062
2063
		if ( empty( $user_info ) ) {
2064
			// Get the customer, but only if it's been created.
2065
			$customer = new Give_Customer( $this->customer_id );
2066
2067
			if ( $customer->id > 0 ) {
2068
				$name      = explode( ' ', $customer->name, 2 );
2069
				$user_info = array(
2070
					'first_name' => $name[0],
2071
					'last_name'  => $name[1],
2072
					'email'      => $customer->email,
2073
					'discount'   => 'none',
2074
				);
2075
			}
2076
		} else {
2077
			// Get the customer, but only if it's been created.
2078
			$customer = new Give_Customer( $this->customer_id );
2079
			if ( $customer->id > 0 ) {
2080
				foreach ( $user_info as $key => $value ) {
2081
					if ( ! empty( $value ) ) {
2082
						continue;
2083
					}
2084
2085
					switch ( $key ) {
2086
						case 'first_name':
2087
							$name = explode( ' ', $customer->name, 2 );
2088
2089
							$user_info[ $key ] = $name[0];
2090
							break;
2091
2092
						case 'last_name':
2093
							$name      = explode( ' ', $customer->name, 2 );
2094
							$last_name = ! empty( $name[1] ) ? $name[1] : '';
2095
2096
							$user_info[ $key ] = $last_name;
2097
							break;
2098
2099
						case 'email':
2100
							$user_info[ $key ] = $customer->email;
2101
							break;
2102
					}
2103
				}
2104
			}
2105
		}
2106
2107
		return $user_info;
2108
2109
	}
2110
2111
	/**
2112
	 * Setup the Address for the payment
2113
	 *
2114
	 * @since  1.5
2115
	 * @access private
2116
	 *
2117
	 * @return array The Address information for the payment
2118
	 */
2119
	private function setup_address() {
2120
2121
		$address = ! empty( $this->payment_meta['user_info']['address'] ) ? $this->payment_meta['user_info']['address'] : array(
2122
			'line1'   => '',
2123
			'line2'   => '',
2124
			'city'    => '',
2125
			'country' => '',
2126
			'state'   => '',
2127
			'zip'     => '',
2128
		);
2129
2130
		return $address;
2131
	}
2132
2133
	/**
2134
	 * Setup the form title
2135
	 *
2136
	 * @since  1.5
2137
	 * @access private
2138
	 *
2139
	 * @return string The Form Title
2140
	 */
2141
	private function setup_form_title() {
2142
2143
		$form_id = $this->get_meta( '_give_payment_form_title', true );
2144
2145
		return $form_id;
2146
	}
2147
2148
	/**
2149
	 * Setup the form ID
2150
	 *
2151
	 * @since  1.5
2152
	 * @access private
2153
	 *
2154
	 * @return int The Form ID
2155
	 */
2156
	private function setup_form_id() {
2157
2158
		$form_id = $this->get_meta( '_give_payment_form_id', true );
2159
2160
		return $form_id;
2161
	}
2162
2163
	/**
2164
	 * Setup the price ID
2165
	 *
2166
	 * @since  1.5
2167
	 * @access private
2168
	 *
2169
	 * @return int The Form Price ID
2170
	 */
2171
	private function setup_price_id() {
2172
		$price_id = $this->get_meta( '_give_payment_price_id', true );
2173
2174
		return $price_id;
2175
	}
2176
2177
	/**
2178
	 * Setup the payment key
2179
	 *
2180
	 * @since  1.5
2181
	 * @access private
2182
	 *
2183
	 * @return string The Payment Key
2184
	 */
2185
	private function setup_payment_key() {
2186
		$key = $this->get_meta( '_give_payment_purchase_key', true );
2187
2188
		return $key;
2189
	}
2190
2191
	/**
2192
	 * Setup the payment number
2193
	 *
2194
	 * @since  1.5
2195
	 * @access private
2196
	 *
2197
	 * @return int|string Integer by default, or string if sequential order numbers is enabled
2198
	 */
2199
	private function setup_payment_number() {
2200
		$number = $this->ID;
2201
2202
		if ( give_get_option( 'enable_sequential' ) ) {
2203
2204
			$number = $this->get_meta( '_give_payment_number', true );
2205
2206
			if ( ! $number ) {
2207
2208
				$number = $this->ID;
2209
2210
			}
2211
		}
2212
2213
		return $number;
2214
	}
2215
2216
	/**
2217
	 * Converts this object into an array for special cases
2218
	 *
2219
	 * @access public
2220
	 *
2221
	 * @return array The payment object as an array
2222
	 */
2223
	public function array_convert() {
2224
		return get_object_vars( $this );
2225
	}
2226
2227
2228
	/**
2229
	 * Flag to check if donation is completed or not.
2230
	 *
2231
	 * @since  1.8
2232
	 * @access public
2233
	 *
2234
	 * @return bool
2235
	 */
2236
	public function is_completed() {
2237
		return ( 'complete' === $this->status && $this->completed_date );
2238
	}
2239
2240
	/**
2241
	 * Retrieve payment completion date
2242
	 *
2243
	 * @since  1.5
2244
	 * @access private
2245
	 *
2246
	 * @return string Date payment was completed
2247
	 */
2248
	private function get_completed_date() {
2249
		return apply_filters( 'give_payment_completed_date', $this->completed_date, $this->ID, $this );
2250
	}
2251
2252
	/**
2253
	 * Retrieve payment subtotal
2254
	 *
2255
	 * @since  1.5
2256
	 * @access private
2257
	 *
2258
	 * @return float Payment subtotal
2259
	 */
2260
	private function get_subtotal() {
2261
		return apply_filters( 'give_get_payment_subtotal', $this->subtotal, $this->ID, $this );
2262
	}
2263
2264
	/**
2265
	 * Retrieve payment currency
2266
	 *
2267
	 * @since  1.5
2268
	 * @access private
2269
	 *
2270
	 * @return string Payment currency code
2271
	 */
2272
	private function get_currency() {
2273
		return apply_filters( 'give_payment_currency_code', $this->currency, $this->ID, $this );
2274
	}
2275
2276
	/**
2277
	 * Retrieve payment gateway
2278
	 *
2279
	 * @since  1.5
2280
	 * @access private
2281
	 *
2282
	 * @return string Gateway used
2283
	 */
2284
	private function get_gateway() {
2285
		return apply_filters( 'give_payment_gateway', $this->gateway, $this->ID, $this );
2286
	}
2287
2288
	/**
2289
	 * Retrieve donation ID
2290
	 *
2291
	 * @since  1.5
2292
	 * @access private
2293
	 *
2294
	 * @return string Donation ID from merchant processor
2295
	 */
2296
	private function get_transaction_id() {
2297
		return apply_filters( 'give_get_payment_transaction_id', $this->transaction_id, $this->ID, $this );
2298
	}
2299
2300
	/**
2301
	 * Retrieve payment IP
2302
	 *
2303
	 * @since  1.5
2304
	 * @access private
2305
	 *
2306
	 * @return string Payment IP address
2307
	 */
2308
	private function get_ip() {
2309
		return apply_filters( 'give_payment_user_ip', $this->ip, $this->ID, $this );
2310
	}
2311
2312
	/**
2313
	 * Retrieve payment customer ID
2314
	 *
2315
	 * @since  1.5
2316
	 * @access private
2317
	 *
2318
	 * @return int Payment customer ID
2319
	 */
2320
	private function get_customer_id() {
2321
		return apply_filters( 'give_payment_customer_id', $this->customer_id, $this->ID, $this );
2322
	}
2323
2324
	/**
2325
	 * Retrieve payment user ID
2326
	 *
2327
	 * @since  1.5
2328
	 * @access private
2329
	 *
2330
	 * @return int Payment user ID
2331
	 */
2332
	private function get_user_id() {
2333
		return apply_filters( 'give_payment_user_id', $this->user_id, $this->ID, $this );
2334
	}
2335
2336
	/**
2337
	 * Retrieve payment email
2338
	 *
2339
	 * @since  1.5
2340
	 * @access private
2341
	 *
2342
	 * @return string Payment customer email
2343
	 */
2344
	private function get_email() {
2345
		return apply_filters( 'give_payment_user_email', $this->email, $this->ID, $this );
2346
	}
2347
2348
	/**
2349
	 * Retrieve payment user info
2350
	 *
2351
	 * @since  1.5
2352
	 * @access private
2353
	 *
2354
	 * @return array Payment user info
2355
	 */
2356
	private function get_user_info() {
2357
		return apply_filters( 'give_payment_meta_user_info', $this->user_info, $this->ID, $this );
2358
	}
2359
2360
	/**
2361
	 * Retrieve payment billing address
2362
	 *
2363
	 * @since  1.5
2364
	 * @access private
2365
	 *
2366
	 * @return array Payment billing address
2367
	 */
2368
	private function get_address() {
2369
		return apply_filters( 'give_payment_address', $this->address, $this->ID, $this );
2370
	}
2371
2372
	/**
2373
	 * Retrieve payment key
2374
	 *
2375
	 * @since  1.5
2376
	 * @access private
2377
	 *
2378
	 * @return string Payment key
2379
	 */
2380
	private function get_key() {
2381
		return apply_filters( 'give_payment_key', $this->key, $this->ID, $this );
2382
	}
2383
2384
	/**
2385
	 * Retrieve payment form id
2386
	 *
2387
	 * @since  1.5
2388
	 * @access private
2389
	 *
2390
	 * @return string Payment form id
2391
	 */
2392
	private function get_form_id() {
2393
		return apply_filters( 'give_payment_form_id', $this->form_id, $this->ID, $this );
2394
	}
2395
2396
	/**
2397
	 * Retrieve payment number
2398
	 *
2399
	 * @since  1.5
2400
	 * @access private
2401
	 *
2402
	 * @return int|string Payment number
2403
	 */
2404
	private function get_number() {
2405
		return apply_filters( 'give_payment_number', $this->number, $this->ID, $this );
2406
	}
2407
2408
}
2409