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

includes/payments/class-give-payment.php (11 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Payments
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Give_Payment
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.5
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Give_Payment Class
19
 *
20
 * This class is for working with payments in Give.
21
 *
22
 * @property int        $ID
23
 * @property bool       $new
24
 * @property string     $number
25
 * @property string     $mode
26
 * @property string     $key
27
 * @property string     $form_title
28
 * @property string|int $form_id
29
 * @property string|int $price_id
30
 * @property string|int $total
31
 * @property string|int $subtotal
32
 * @property string|int $fees
33
 * @property string|int $fees_total
34
 * @property string     $post_status
35
 * @property string     $date
36
 * @property string     $postdate
37
 * @property string     $status
38
 * @property string     $email
39
 * @property array      $payment_meta
40
 * @property string     $customer_id
41
 * @property string     $completed_date
42
 * @property string     $currency
43
 * @property string     $ip
44
 * @property array      $user_info
45
 * @property string     $gateway
46
 * @property string     $user_id
47
 * @property string     $first_name
48
 * @property string     $last_name
49
 * @property string     $parent_payment
50
 * @property string     $transaction_id
51
 * @property string     $old_status
52
 *
53
 * @since 1.5
54
 */
55
final class Give_Payment {
56
57
	/**
58
	 * The Payment ID.
59
	 *
60
	 * @since  1.5
61
	 *
62
	 * @var    int
63
	 */
64
	public $ID = 0;
65
66
	/**
67
	 * Protected non-read $_ID.
68
	 *
69
	 * @var int
70
	 */
71
	protected $_ID = 0;
72
73
	/**
74
	 * Identify if the payment is a new one or existing.
75
	 *
76
	 * @since  1.5
77
	 * @access protected
78
	 *
79
	 * @var    boolean
80
	 */
81
	protected $new = false;
82
83
	/**
84
	 * The Payment number (for use with sequential payments).
85
	 *
86
	 * @since  1.5
87
	 * @access protected
88
	 *
89
	 * @var    string
90
	 */
91
	protected $number = '';
92
93
	/**
94
	 * The Gateway mode the payment was made in.
95
	 *
96
	 * @since  1.5
97
	 * @access protected
98
	 *
99
	 * @var    string
100
	 */
101
	protected $mode = 'live';
102
103
	/**
104
	 * The unique donation payment key.
105
	 *
106
	 * @since  1.5
107
	 * @access protected
108
	 *
109
	 * @var    string
110
	 */
111
	protected $key = '';
112
113
	/**
114
	 * The Donation Form Title
115
	 *
116
	 * @since  1.5
117
	 * @access protected
118
	 *
119
	 * @var    string
120
	 */
121
	protected $form_title = 0;
122
123
	/**
124
	 * The Donation Form ID
125
	 *
126
	 * @since  1.5
127
	 * @access protected
128
	 *
129
	 * @var    string
130
	 */
131
	protected $form_id = 0;
132
133
	/**
134
	 * The Donation Form Price ID
135
	 *
136
	 * @since  1.5
137
	 * @access protected
138
	 *
139
	 * @var    string|int
140
	 */
141
	protected $price_id = 0;
142
143
	/**
144
	 * The total amount of the donation payment.
145
	 *
146
	 * @since  1.5
147
	 * @access protected
148
	 *
149
	 * @var    float
150
	 */
151
	protected $total = 0.00;
152
153
	/**
154
	 * The Subtotal fo the payment.
155
	 *
156
	 * @since  1.5
157
	 * @access protected
158
	 *
159
	 * @var    float
160
	 */
161
	protected $subtotal = 0;
162
163
	/**
164
	 * The date the payment was created
165
	 *
166
	 * @since  1.5
167
	 * @access protected
168
	 *
169
	 * @var    string
170
	 */
171
	protected $date = '';
172
173
	/**
174
	 * The date the payment post was created.
175
	 *
176
	 * @var string
177
	 */
178
	protected $post_date = '';
179
180
	/**
181
	 * The date the payment was marked as 'complete'.
182
	 *
183
	 * @since  1.5
184
	 * @access protected
185
	 *
186
	 * @var    string
187
	 */
188
	protected $completed_date = '';
189
190
	/**
191
	 * The status of the donation payment.
192
	 *
193
	 * @since  1.5
194
	 * @access protected
195
	 *
196
	 * @var    string
197
	 */
198
	protected $status = 'pending';
199
200
	/**
201
	 * @var string
202
	 */
203
	protected $post_status = 'pending'; // Same as $status but here for backwards compat
204
205
	/**
206
	 * When updating, the old status prior to the change
207
	 *
208
	 * @since  1.5
209
	 * @access protected
210
	 *
211
	 * @var    string
212
	 */
213
	protected $old_status = '';
214
215
	/**
216
	 * The display name of the current payment status.
217
	 *
218
	 * @since  1.5
219
	 * @access protected
220
	 *
221
	 * @var    string
222
	 */
223
	protected $status_nicename = '';
224
225
	/**
226
	 * The donor ID that made the payment.
227
	 *
228
	 * @since  1.5
229
	 * @access protected
230
	 *
231
	 * @var    integer
232
	 */
233
	protected $customer_id = null;
234
235
	/**
236
	 * The User ID (if logged in) that made the payment
237
	 *
238
	 * @since  1.5
239
	 * @access protected
240
	 *
241
	 * @var    integer
242
	 */
243
	protected $user_id = 0;
244
245
	/**
246
	 * The first name of the payee
247
	 *
248
	 * @since  1.5
249
	 * @access protected
250
	 *
251
	 * @var    string
252
	 */
253
	protected $first_name = '';
254
255
	/**
256
	 * The last name of the payee
257
	 *
258
	 * @since  1.5
259
	 * @access protected
260
	 *
261
	 * @var    string
262
	 */
263
	protected $last_name = '';
264
265
	/**
266
	 * The email used for the payment
267
	 *
268
	 * @since  1.5
269
	 * @access protected
270
	 *
271
	 * @var    string
272
	 */
273
	protected $email = '';
274
275
	/**
276
	 * Legacy (not to be accessed) array of user information
277
	 *
278
	 * @since  1.5
279
	 * @access private
280
	 *
281
	 * @var    array
282
	 */
283
	private $user_info = array();
284
285
	/**
286
	 * Legacy (not to be accessed) payment meta array
287
	 *
288
	 * @since  1.5
289
	 * @access private
290
	 *
291
	 * @var    array
292
	 */
293
	private $payment_meta = array();
294
295
	/**
296
	 * The physical address used for the payment if provided
297
	 *
298
	 * @since  1.5
299
	 * @access protected
300
	 *
301
	 * @var    array
302
	 */
303
	protected $address = array();
304
305
	/**
306
	 * The transaction ID returned by the gateway
307
	 *
308
	 * @since  1.5
309
	 * @access protected
310
	 *
311
	 * @var    string
312
	 */
313
	protected $transaction_id = '';
314
315
	/**
316
	 * IP Address payment was made from
317
	 *
318
	 * @since  1.5
319
	 * @access protected
320
	 *
321
	 * @var    string
322
	 */
323
	protected $ip = '';
324
325
	/**
326
	 * The gateway used to process the payment
327
	 *
328
	 * @since  1.5
329
	 * @access protected
330
	 *
331
	 * @var    string
332
	 */
333
	protected $gateway = '';
334
335
	/**
336
	 * The the payment was made with
337
	 *
338
	 * @since  1.5
339
	 * @access protected
340
	 *
341
	 * @var    string
342
	 */
343
	protected $currency = '';
344
345
	/**
346
	 * Array of items that have changed since the last save() was run.
347
	 * This is for internal use, to allow fewer update_payment_meta calls to be run.
348
	 *
349
	 * @since  1.5
350
	 * @access private
351
	 *
352
	 * @var    array
353
	 */
354
	private $pending;
355
356
	/**
357
	 * The parent payment (if applicable)
358
	 *
359
	 * @since  1.5
360
	 * @access protected
361
	 *
362
	 * @var    integer
363
	 */
364
	protected $parent_payment = 0;
365
366
	/**
367
	 * Setup the Give Payments class
368
	 *
369
	 * @since  1.5
370
	 * @access public
371
	 *
372
	 * @param  int|bool $payment_id A given payment
373
	 *
374
	 * @return mixed void|false
375
	 */
376
	public function __construct( $payment_id = false ) {
377
378
		if ( empty( $payment_id ) ) {
379
			return false;
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
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
		// @todo: payment data exist here only for backward compatibility
610
		// issue: https://github.com/WordImpress/Give/issues/1132
611
		$payment_data = array(
612
			'price'        => $this->total,
613
			'date'         => $this->date,
614
			'user_email'   => $this->email,
615
			'purchase_key' => $this->key,
616
			'form_title'   => $this->form_title,
617
			'form_id'      => $this->form_id,
618
			'price_id'     => $this->price_id,
619
			'currency'     => $this->currency,
620
			'user_info'    => array(
621
				'id'         => $this->user_id,
622
				'email'      => $this->email,
623
				'first_name' => $this->first_name,
624
				'last_name'  => $this->last_name,
625
				'address'    => $this->address,
626
			),
627
			'status'       => $this->status,
628
		);
629
630
		$args = apply_filters( 'give_insert_payment_args', array(
631
			'post_title'    => $payment_title,
632
			'post_status'   => $this->status,
633
			'post_type'     => 'give_payment',
634
			'post_date'     => ! empty( $this->date ) ? $this->date : null,
635
			'post_date_gmt' => ! empty( $this->date ) ? get_gmt_from_date( $this->date ) : null,
636
			'post_parent'   => $this->parent_payment,
637
		), $payment_data );
638
639
		// Create a blank payment
640
		$payment_id = wp_insert_post( $args );
641
642
		if ( ! empty( $payment_id ) ) {
643
644
			$this->ID  = $payment_id;
645
			$this->_ID = $payment_id;
646
647
			$donor = new stdClass;
648
649
			if ( did_action( 'give_pre_process_donation' ) && is_user_logged_in() ) {
650
				$donor = new Give_Donor( get_current_user_id(), true );
651
652
				// Donor is logged in but used a different email to purchase with so assign to their donor record.
653
				if ( ! empty( $donor->id ) && $this->email != $donor->email ) {
654
					$donor->add_email( $this->email );
655
				}
656
			}
657
658
			if ( empty( $donor->id ) ) {
659
				$donor = new Give_Donor( $this->email );
660
			}
661
662
			if ( empty( $donor->id ) ) {
663
664
				$donor_data = array(
665
					'name'    => ! is_email( $payment_title ) ? $this->first_name . ' ' . $this->last_name : '',
666
					'email'   => $this->email,
667
					'user_id' => $this->user_id,
668
				);
669
670
				$donor->create( $donor_data );
671
672
			}
673
674
			$this->customer_id            = $donor->id;
675
			$this->pending['customer_id'] = $this->customer_id;
676
			$donor->attach_payment( $this->ID, false );
677
678
			$this->payment_meta = apply_filters( 'give_payment_meta', $this->payment_meta, $payment_data );
679
680
			$this->new = true;
681
		}// End if().
682
683
		return $this->ID;
684
685
	}
686
687
	/**
688
	 * Save
689
	 *
690
	 * Once items have been set, an update is needed to save them to the database.
691
	 *
692
	 * @access public
693
	 *
694
	 * @return bool  True of the save occurred, false if it failed or wasn't needed
695
	 */
696
	public function save() {
697
		$saved = false;
698
699
		// Must have an ID.
700
		if ( empty( $this->ID ) ) {
701
702
			$payment_id = $this->insert_payment();
703
704
			if ( false === $payment_id ) {
705
				$saved = false;
706
			} else {
707
				$this->ID = $payment_id;
708
			}
709
		}
710
711
		// Set ID if not matching.
712
		if ( $this->ID !== $this->_ID ) {
713
			$this->ID = $this->_ID;
714
		}
715
716
		// If we have something pending, let's save it.
717
		if ( ! empty( $this->pending ) ) {
718
719
			$total_increase = 0;
720
			$total_decrease = 0;
721
722
			foreach ( $this->pending as $key => $value ) {
723
724
				switch ( $key ) {
725
726
					case 'donations':
727
						// Update totals for pending donations.
728
						foreach ( $this->pending[ $key ] as $item ) {
729
730
							$quantity = isset( $item['quantity'] ) ? $item['quantity'] : 1;
731
							$price_id = isset( $item['price_id'] ) ? $item['price_id'] : 0;
732
733
							switch ( $item['action'] ) {
734
735
								case 'add':
736
737
									$price = $item['price'];
738
739
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
740
741
										// Add sales logs.
742
										$log_date = date_i18n( 'Y-m-d G:i:s', current_time( 'timestamp' ) );
743
744
										$y = 0;
745
										while ( $y < $quantity ) {
746
747
											give_record_donation_in_log( $item['id'], $this->ID, $price_id, $log_date );
748
											$y ++;
749
										}
750
751
										$form = new Give_Donate_Form( $item['id'] );
752
										$form->increase_sales( $quantity );
753
										$form->increase_earnings( $price );
754
755
										$total_increase += $price;
756
									}
757
									break;
758
759
								case 'remove':
760
									$this->delete_sales_logs();
761
									if ( 'publish' === $this->status || 'complete' === $this->status ) {
762
										$form = new Give_Donate_Form( $item['id'] );
763
										$form->decrease_sales( $quantity );
764
										$form->decrease_earnings( $item['amount'] );
765
766
										$total_decrease += $item['amount'];
767
									}
768
									break;
769
770
							}// End switch().
771
						}// End foreach().
772
						break;
773
774
					case 'status':
775
						$this->update_status( $this->status );
776
						break;
777
778
					case 'gateway':
779
						$this->update_meta( '_give_payment_gateway', $this->gateway );
780
						break;
781
782
					case 'mode':
783
						$this->update_meta( '_give_payment_mode', $this->mode );
784
						break;
785
786
					case 'transaction_id':
787
						$this->update_meta( '_give_payment_transaction_id', $this->transaction_id );
788
						break;
789
790
					case 'ip':
791
						$this->update_meta( '_give_payment_donor_ip', $this->ip );
792
						break;
793
794
					case 'customer_id':
795
						$this->update_meta( '_give_payment_donor_id', $this->customer_id );
796
						break;
797
798
					// case 'user_id':
799
					// 	$this->update_meta( '_give_payment_user_id', $this->user_id );
800
					// 	break;
801
802
					case 'form_title':
803
						$this->update_meta( '_give_payment_form_title', $this->form_title );
804
						break;
805
806
					case 'form_id':
807
						$this->update_meta( '_give_payment_form_id', $this->form_id );
808
						break;
809
810
					case 'price_id':
811
						$this->update_meta( '_give_payment_price_id', $this->price_id );
812
						break;
813
814
					case 'first_name':
815
						$this->update_meta( '_give_donor_billing_first_name', $this->first_name );
816
						break;
817
818
					case 'last_name':
819
						$this->update_meta( '_give_donor_billing_last_name', $this->last_name );
820
						break;
821
822
					case 'currency':
823
						$this->update_meta( '_give_payment_currency', $this->currency );
824
						break;
825
826
					case 'address':
827
						if( ! empty( $this->address ) ) {
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
828
							foreach ( $this->address as $address_name => $address ) {
829
								switch ( $address_name ) {
830
									case 'line1':
831
										$this->update_meta( '_give_donor_billing_address1', $address );
832
										break;
833
834
									case 'line2':
835
										$this->update_meta( '_give_donor_billing_address2', $address );
836
										break;
837
838
									default:
839
										$this->update_meta( "_give_donor_billing_{$address_name}", $address );
840
								}
841
							}
842
						}
843
						break;
844
845
					case 'email':
846
						$this->update_meta( '_give_payment_donor_email', $this->email );
847
						break;
848
849
					case 'key':
850
						$this->update_meta( '_give_payment_purchase_key', $this->key );
851
						break;
852
853
					case 'number':
854
						$this->update_meta( '_give_payment_number', $this->number );
855
						break;
856
857
					case 'date':
858
						$args = array(
859
							'ID'        => $this->ID,
860
							'post_date' => $this->date,
861
							'edit_date' => true,
862
						);
863
864
						wp_update_post( $args );
865
						break;
866
867
					case 'completed_date':
868
						$this->update_meta( '_give_completed_date', $this->completed_date );
869
						break;
870
871
					case 'parent_payment':
872
						$args = array(
873
							'ID'          => $this->ID,
874
							'post_parent' => $this->parent_payment,
875
						);
876
877
						wp_update_post( $args );
878
						break;
879
880
					default:
881
						/**
882
						 * Fires while saving payment.
883
						 *
884
						 * @since 1.7
885
						 *
886
						 * @param Give_Payment $this Payment object.
887
						 */
888
						do_action( 'give_payment_save', $this, $key );
889
						break;
890
				}// End switch().
891
			}// End foreach().
892
893
			if ( 'pending' !== $this->status ) {
894
895
				$donor = new Give_Donor( $this->customer_id );
896
897
				$total_change = $total_increase - $total_decrease;
898
				if ( $total_change < 0 ) {
899
900
					$total_change = - ( $total_change );
901
					// Decrease the donor's donation stats.
902
					$donor->decrease_value( $total_change );
903
					give_decrease_total_earnings( $total_change );
904
905
				} elseif ( $total_change > 0 ) {
906
907
					// Increase the donor's donation stats.
908
					$donor->increase_value( $total_change );
909
					give_increase_total_earnings( $total_change );
910
911
				}
912
			}
913
914
			$this->update_meta( '_give_payment_total', give_sanitize_amount_for_db( $this->total ) );
915
916
			$this->pending = array();
917
			$saved         = true;
918
		}// End if().
919
920
		if ( true === $saved ) {
921
			$this->setup_payment( $this->ID );
922
		}
923
924
		return $saved;
925
	}
926
927
	/**
928
	 * Add a donation to a given payment
929
	 *
930
	 * @since  1.5
931
	 * @access public
932
	 *
933
	 * @param  int   $form_id The donation form to add
934
	 * @param  array $args Other arguments to pass to the function
935
	 * @param  array $options List of donation options
936
	 *
937
	 * @return bool           True when successful, false otherwise
938
	 */
939
	public function add_donation( $form_id = 0, $args = array(), $options = array() ) {
940
941
		$donation = new Give_Donate_Form( $form_id );
942
943
		// Bail if this post isn't a give donation form.
944
		if ( ! $donation || $donation->post_type !== 'give_forms' ) {
945
			return false;
946
		}
947
948
		// Set some defaults.
949
		$defaults = array(
950
			'price'    => false,
951
			'price_id' => false,
952
		);
953
954
		$args = wp_parse_args( apply_filters( 'give_payment_add_donation_args', $args, $donation->ID ), $defaults );
955
956
		// Allow overriding the price.
957
		if ( false !== $args['price'] ) {
958
			$item_price = $args['price'];
959
		} else {
960
961
			// Deal with variable pricing.
962
			if ( give_has_variable_prices( $donation->ID ) ) {
963
				$prices     = maybe_unserialize( give_get_meta( $form_id, '_give_donation_levels', true ) );
964
				$item_price = '';
965
				// Loop through prices.
966 View Code Duplication
				foreach ( $prices as $price ) {
967
					// Find a match between price_id and level_id.
968
					// First verify array keys exists THEN make the match.
969
					if ( ( isset( $args['price_id'] ) && isset( $price['_give_id']['level_id'] ) )
970
					     && $args['price_id'] == $price['_give_id']['level_id']
971
					) {
972
						$item_price = $price['_give_amount'];
973
					}
974
				}
975
				// Fallback to the lowest price point.
976
				if ( $item_price == '' ) {
977
					$item_price       = give_get_lowest_price_option( $donation->ID );
978
					$args['price_id'] = give_get_lowest_price_id( $donation->ID );
979
				}
980
			} else {
981
				// Simple form price.
982
				$item_price = give_get_form_price( $donation->ID );
983
			}
984
		}
985
986
		// Sanitizing the price here so we don't have a dozen calls later.
987
		$item_price = give_maybe_sanitize_amount( $item_price );
988
		$total      = round( $item_price, give_currency_decimal_filter() );
989
990
		// Add Options.
991
		$default_options = array();
992
		if ( false !== $args['price_id'] ) {
993
			$default_options['price_id'] = (int) $args['price_id'];
994
		}
995
		$options = wp_parse_args( $options, $default_options );
996
997
		// Do not allow totals to go negative.
998
		if ( $total < 0 ) {
999
			$total = 0;
1000
		}
1001
1002
		$donation = array(
1003
			'name'     => $donation->post_title,
1004
			'id'       => $donation->ID,
1005
			'price'    => round( $total, give_currency_decimal_filter() ),
1006
			'subtotal' => round( $total, give_currency_decimal_filter() ),
1007
			'price_id' => $args['price_id'],
1008
			'action'   => 'add',
1009
			'options'  => $options,
1010
		);
1011
1012
		$this->pending['donations'][] = $donation;
1013
1014
		$this->increase_subtotal( $total );
1015
1016
		return true;
1017
1018
	}
1019
1020
	/**
1021
	 * Remove a donation from the payment
1022
	 *
1023
	 * @since  1.5
1024
	 * @access public
1025
	 *
1026
	 * @param  int   $form_id The form ID to remove
1027
	 * @param  array $args Arguments to pass to identify (quantity, amount, price_id)
1028
	 *
1029
	 * @return bool           If the item was removed or not
1030
	 */
1031
	public function remove_donation( $form_id, $args = array() ) {
1032
1033
		// Set some defaults.
1034
		$defaults = array(
1035
			'quantity' => 1,
1036
			'price'    => false,
1037
			'price_id' => false,
1038
		);
1039
		$args     = wp_parse_args( $args, $defaults );
1040
1041
		$form = new Give_Donate_Form( $form_id );
1042
1043
		// Bail if this post isn't a valid give donation form.
1044
		if ( ! $form || $form->post_type !== 'give_forms' ) {
1045
			return false;
1046
		}
1047
1048
		$pending_args             = $args;
1049
		$pending_args['id']       = $form_id;
1050
		$pending_args['amount']   = $this->total;
1051
		$pending_args['price_id'] = false !== $args['price_id'] ? (int) $args['price_id'] : false;
1052
		$pending_args['quantity'] = $args['quantity'];
1053
		$pending_args['action']   = 'remove';
1054
1055
		$this->pending['donations'][] = $pending_args;
1056
1057
		$this->decrease_subtotal( $this->total );
1058
1059
		return true;
1060
	}
1061
1062
1063
	/**
1064
	 * Add a note to a payment
1065
	 *
1066
	 * @since  1.5
1067
	 * @access public
1068
	 *
1069
	 * @param  string $note The note to add
1070
	 *
1071
	 * @return void
1072
	 */
1073
	public function add_note( $note = false ) {
1074
		// Bail if no note specified.
1075
		if ( ! $note ) {
1076
			return false;
1077
		}
1078
1079
		give_insert_payment_note( $this->ID, $note );
1080
	}
1081
1082
	/**
1083
	 * Increase the payment's subtotal
1084
	 *
1085
	 * @since  1.5
1086
	 * @access private
1087
	 *
1088
	 * @param  float $amount The amount to increase the payment subtotal by.
1089
	 *
1090
	 * @return void
1091
	 */
1092
	private function increase_subtotal( $amount = 0.00 ) {
1093
		$amount         = (float) $amount;
1094
		$this->subtotal += $amount;
1095
1096
		$this->recalculate_total();
1097
	}
1098
1099
	/**
1100
	 * Decrease the payment's subtotal.
1101
	 *
1102
	 * @since  1.5
1103
	 * @access private
1104
	 *
1105
	 * @param  float $amount The amount to decrease the payment subtotal by.
1106
	 *
1107
	 * @return void
1108
	 */
1109
	private function decrease_subtotal( $amount = 0.00 ) {
1110
		$amount         = (float) $amount;
1111
		$this->subtotal -= $amount;
1112
1113
		if ( $this->subtotal < 0 ) {
1114
			$this->subtotal = 0;
1115
		}
1116
1117
		$this->recalculate_total();
1118
	}
1119
1120
	/**
1121
	 * Set or update the total for a payment.
1122
	 *
1123
	 * @since  1.5
1124
	 * @access private
1125
	 *
1126
	 * @return void
1127
	 */
1128
	private function recalculate_total() {
1129
		$this->total = $this->subtotal;
1130
	}
1131
1132
	/**
1133
	 * Set the payment status and run any status specific changes necessary.
1134
	 *
1135
	 * @since  1.5
1136
	 * @access public
1137
	 *
1138
	 * @param  string|bool $status The status to set the payment to.
1139
	 *
1140
	 * @return bool   $updated Returns if the status was successfully updated.
1141
	 */
1142
	public function update_status( $status = false ) {
1143
1144
		// standardize the 'complete(d)' status.
1145
		if ( $status == 'completed' || $status == 'complete' ) {
1146
			$status = 'publish';
1147
		}
1148
1149
		$old_status = ! empty( $this->old_status ) ? $this->old_status : false;
1150
1151
		if ( $old_status === $status ) {
1152
			return false; // Don't permit status changes that aren't changes.
1153
		}
1154
1155
		$do_change = apply_filters( 'give_should_update_payment_status', true, $this->ID, $status, $old_status );
1156
1157
		$updated = false;
1158
1159
		if ( $do_change ) {
1160
1161
			/**
1162
			 * Fires before changing payment status.
1163
			 *
1164
			 * @since 1.5
1165
			 *
1166
			 * @param int $payment_id Payments ID.
1167
			 * @param string $status The new status.
1168
			 * @param string $old_status The old status.
1169
			 */
1170
			do_action( 'give_before_payment_status_change', $this->ID, $status, $old_status );
1171
1172
			$update_fields = array(
1173
				'ID'          => $this->ID,
1174
				'post_status' => $status,
1175
				'edit_date'   => current_time( 'mysql' ),
1176
			);
1177
1178
			$updated = wp_update_post( apply_filters( 'give_update_payment_status_fields', $update_fields ) );
1179
1180
			$all_payment_statuses  = give_get_payment_statuses();
1181
			$this->status_nicename = array_key_exists( $status, $all_payment_statuses ) ? $all_payment_statuses[ $status ] : ucfirst( $status );
1182
1183
			// Process any specific status functions.
1184
			switch ( $status ) {
1185
				case 'refunded':
1186
					$this->process_refund();
1187
					break;
1188
				case 'failed':
1189
					$this->process_failure();
1190
					break;
1191
				case 'pending':
1192
					$this->process_pending();
1193
					break;
1194
				case 'cancelled':
1195
					$this->process_cancelled();
1196
					break;
1197
				case 'revoked':
1198
					$this->process_revoked();
1199
					break;
1200
			}
1201
1202
			/**
1203
			 * Fires after changing payment status.
1204
			 *
1205
			 * @since 1.5
1206
			 *
1207
			 * @param int $payment_id Payment ID.
1208
			 * @param string $status The new status.
1209
			 * @param string $old_status The old status.
1210
			 */
1211
			do_action( 'give_update_payment_status', $this->ID, $status, $old_status );
1212
1213
		}// End if().
1214
1215
		return $updated;
1216
1217
	}
1218
1219
	/**
1220
	 * Change the status of the payment to refunded, and run the necessary changes
1221
	 *
1222
	 * @since  1.5
1223
	 * @access public
1224
	 *
1225
	 * @return void
1226
	 */
1227
	public function refund() {
1228
		$this->old_status        = $this->status;
1229
		$this->status            = 'refunded';
1230
		$this->pending['status'] = $this->status;
1231
1232
		$this->save();
1233
	}
1234
1235
	/**
1236
	 * Get a post meta item for the payment
1237
	 *
1238
	 * @since  1.5
1239
	 * @access public
1240
	 *
1241
	 * @param  string  $meta_key The Meta Key
1242
	 * @param  boolean $single Return single item or array
1243
	 *
1244
	 * @return mixed             The value from the post meta
1245
	 */
1246
	public function get_meta( $meta_key = '_give_payment_meta', $single = true ) {
1247
1248
		$meta = give_get_meta( $this->ID, $meta_key, $single );
1249
1250
		/**
1251
		 * Filter the specific meta key value.
1252
		 *
1253
		 * @since 1.5
1254
		 */
1255
		$meta = apply_filters( "give_get_payment_meta_{$meta_key}", $meta, $this->ID );
1256
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1257
1258
		/**
1259
		 * Filter the all meta keys.
1260
		 *
1261
		 * @since 1.5
1262
		 */
1263
		return apply_filters( 'give_get_payment_meta', $meta, $this->ID, $meta_key );
1264
	}
1265
1266
	/**
1267
	 * Update the post meta
1268
	 *
1269
	 * @since  1.5
1270
	 * @access public
1271
	 *
1272
	 * @param  string $meta_key The meta key to update
1273
	 * @param  string $meta_value The meta value
1274
	 * @param  string $prev_value Previous meta value
1275
	 *
1276
	 * @return int|bool           Meta ID if the key didn't exist, true on successful update, false on failure
1277
	 */
1278
	public function update_meta( $meta_key = '', $meta_value = '', $prev_value = '' ) {
1279
		if ( empty( $meta_key ) ) {
1280
			return false;
1281
		}
1282
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1283
1284
		/**
1285
		 * Filter the single meta key while updating
1286
		 *
1287
		 * @since 1.5
1288
		 */
1289
		$meta_value = apply_filters( "give_update_payment_meta_{$meta_key}", $meta_value, $this->ID );
1290
1291
		return give_update_meta( $this->ID, $meta_key, $meta_value, $prev_value );
1292
	}
1293
1294
	/**
1295
	 * When a payment is set to a status of 'refunded' process the necessary actions to reduce stats
1296
	 *
1297
	 * @since  1.5
1298
	 * @access private
1299
	 *
1300
	 * @return void
1301
	 */
1302 View Code Duplication
	private function process_refund() {
1303
		$process_refund = true;
1304
1305
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1306
		if ( 'publish' != $this->old_status || 'refunded' != $this->status ) {
1307
			$process_refund = false;
1308
		}
1309
1310
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1311
		$process_refund = apply_filters( 'give_should_process_refund', $process_refund, $this );
1312
1313
		if ( false === $process_refund ) {
1314
			return;
1315
		}
1316
1317
		/**
1318
		 * Fires before refunding payment.
1319
		 *
1320
		 * @since 1.5
1321
		 *
1322
		 * @param Give_Payment $this Payment object.
1323
		 */
1324
		do_action( 'give_pre_refund_payment', $this );
1325
1326
		$decrease_earnings       = apply_filters( 'give_decrease_store_earnings_on_refund', true, $this );
1327
		$decrease_customer_value = apply_filters( 'give_decrease_customer_value_on_refund', true, $this );
1328
		$decrease_purchase_count = apply_filters( 'give_decrease_customer_purchase_count_on_refund', true, $this );
1329
1330
		$this->maybe_alter_stats( $decrease_earnings, $decrease_customer_value, $decrease_purchase_count );
1331
		$this->delete_sales_logs();
1332
1333
		// @todo: Refresh only range related stat cache
1334
		give_delete_donation_stats();
1335
1336
		/**
1337
		 * Fires after refunding payment.
1338
		 *
1339
		 * @since 1.5
1340
		 *
1341
		 * @param Give_Payment $this Payment object.
1342
		 */
1343
		do_action( 'give_post_refund_payment', $this );
1344
	}
1345
1346
	/**
1347
	 * Process when a payment is set to failed
1348
	 *
1349
	 * @since  1.5
1350
	 * @access private
1351
	 *
1352
	 * @return void
1353
	 */
1354
	private function process_failure() {
1355
1356
	}
1357
1358
	/**
1359
	 * Process when a payment moves to pending
1360
	 *
1361
	 * @since  1.5
1362
	 * @access private
1363
	 *
1364
	 * @return void
1365
	 */
1366 View Code Duplication
	private function process_pending() {
1367
		$process_pending = true;
1368
1369
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1370
		if ( 'publish' != $this->old_status || 'pending' != $this->status ) {
1371
			$process_pending = false;
1372
		}
1373
1374
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1375
		$process_pending = apply_filters( 'give_should_process_pending', $process_pending, $this );
1376
1377
		if ( false === $process_pending ) {
1378
			return;
1379
		}
1380
1381
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_pending', true, $this );
1382
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_pending', true, $this );
1383
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_pending', true, $this );
1384
1385
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1386
		$this->delete_sales_logs();
1387
1388
		$this->completed_date = false;
1389
		$this->update_meta( '_give_completed_date', '' );
1390
1391
		// @todo: Refresh only range related stat cache
1392
		give_delete_donation_stats();
1393
	}
1394
1395
	/**
1396
	 * Process when a payment moves to cancelled.
1397
	 *
1398
	 * @since  1.5
1399
	 * @access private
1400
	 *
1401
	 * @return void
1402
	 */
1403 View Code Duplication
	private function process_cancelled() {
1404
		$process_cancelled = true;
1405
1406
		// If the payment was not in publish or revoked status, don't decrement stats as they were never incremented.
1407
		if ( 'publish' != $this->old_status || 'cancelled' != $this->status ) {
1408
			$process_cancelled = false;
1409
		}
1410
1411
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1412
		$process_cancelled = apply_filters( 'give_should_process_cancelled', $process_cancelled, $this );
1413
1414
		if ( false === $process_cancelled ) {
1415
			return;
1416
		}
1417
1418
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_cancelled', true, $this );
1419
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_cancelled', true, $this );
1420
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_cancelled', true, $this );
1421
1422
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1423
		$this->delete_sales_logs();
1424
1425
		$this->completed_date = false;
1426
		$this->update_meta( '_give_completed_date', '' );
1427
1428
		// @todo: Refresh only range related stat cache
1429
		give_delete_donation_stats();
1430
	}
1431
1432
	/**
1433
	 * Process when a payment moves to revoked.
1434
	 *
1435
	 * @since  1.5
1436
	 * @return void
1437
	 */
1438 View Code Duplication
	private function process_revoked() {
1439
		$process_revoked = true;
1440
1441
		// If the payment was not in publish, don't decrement stats as they were never incremented.
1442
		if ( 'publish' != $this->old_status || 'revoked' != $this->status ) {
1443
			$process_revoked = false;
1444
		}
1445
1446
		// Allow extensions to filter for their own payment types, Example: Recurring Payments.
1447
		$process_revoked = apply_filters( 'give_should_process_revoked', $process_revoked, $this );
1448
1449
		if ( false === $process_revoked ) {
1450
			return;
1451
		}
1452
1453
		$decrease_earnings       = apply_filters( 'give_decrease_earnings_on_revoked', true, $this );
1454
		$decrease_donor_value    = apply_filters( 'give_decrease_donor_value_on_revoked', true, $this );
1455
		$decrease_donation_count = apply_filters( 'give_decrease_donors_donation_count_on_revoked', true, $this );
1456
1457
		$this->maybe_alter_stats( $decrease_earnings, $decrease_donor_value, $decrease_donation_count );
1458
		$this->delete_sales_logs();
1459
1460
		$this->completed_date = false;
1461
		$this->update_meta( '_give_completed_date', '' );
1462
1463
		// @todo: Refresh only range related stat cache
1464
		give_delete_donation_stats();
1465
	}
1466
1467
	/**
1468
	 * Used during the process of moving to refunded or pending, to decrement stats
1469
	 *
1470
	 * @since  1.5
1471
	 * @access private
1472
	 *
1473
	 * @param  bool $alter_store_earnings If the method should alter the store earnings
1474
	 * @param  bool $alter_customer_value If the method should reduce the donor value
1475
	 * @param  bool $alter_customer_purchase_count If the method should reduce the donor's purchase count
1476
	 *
1477
	 * @return void
1478
	 */
1479
	private function maybe_alter_stats( $alter_store_earnings, $alter_customer_value, $alter_customer_purchase_count ) {
1480
1481
		give_undo_donation( $this->ID );
1482
1483
		// Decrease store earnings.
1484
		if ( true === $alter_store_earnings ) {
1485
			give_decrease_total_earnings( $this->total );
1486
		}
1487
1488
		// Decrement the stats for the donor.
1489
		if ( ! empty( $this->customer_id ) ) {
1490
1491
			$donor = new Give_Donor( $this->customer_id );
1492
1493
			if ( true === $alter_customer_value ) {
1494
				$donor->decrease_value( $this->total );
1495
			}
1496
1497
			if ( true === $alter_customer_purchase_count ) {
1498
				$donor->decrease_donation_count();
1499
			}
1500
		}
1501
1502
	}
1503
1504
	/**
1505
	 * Delete sales logs for this donation
1506
	 *
1507
	 * @since  1.5
1508
	 * @access private
1509
	 *
1510
	 * @return void
1511
	 */
1512
	private function delete_sales_logs() {
1513
		// Remove related sale log entries.
1514
		Give()->logs->delete_logs( $this->ID );
1515
	}
1516
1517
	/**
1518
	 * Setup functions only, these are not to be used by developers.
1519
	 * These functions exist only to allow the setup routine to be backwards compatible with our old
1520
	 * helper functions.
1521
	 *
1522
	 * These will run whenever setup_payment is called, which should only be called once.
1523
	 * To update an attribute, update it directly instead of re-running the setup routine
1524
	 */
1525
1526
	/**
1527
	 * Setup the payment completed date
1528
	 *
1529
	 * @since  1.5
1530
	 * @access private
1531
	 *
1532
	 * @return string The date the payment was completed
1533
	 */
1534
	private function setup_completed_date() {
1535
		$payment = get_post( $this->ID );
1536
1537
		if ( 'pending' == $payment->post_status || 'preapproved' == $payment->post_status ) {
1538
			return false; // This payment was never completed.
1539
		}
1540
1541
		$date = ( $date = $this->get_meta( '_give_completed_date', true ) ) ? $date : $payment->modified_date;
1542
1543
		return $date;
1544
	}
1545
1546
	/**
1547
	 * Setup the payment mode
1548
	 *
1549
	 * @since  1.5
1550
	 * @access private
1551
	 *
1552
	 * @return string The payment mode
1553
	 */
1554
	private function setup_mode() {
1555
		return $this->get_meta( '_give_payment_mode' );
1556
	}
1557
1558
	/**
1559
	 * Setup the payment total
1560
	 *
1561
	 * @since  1.5
1562
	 * @access private
1563
	 *
1564
	 * @return float The payment total
1565
	 */
1566
	private function setup_total() {
1567
		$amount = $this->get_meta( '_give_payment_total', true );
1568
1569
		return round( floatval( $amount ), give_currency_decimal_filter() );
1570
	}
1571
1572
	/**
1573
	 * Setup the payment subtotal
1574
	 *
1575
	 * @since  1.5
1576
	 * @access private
1577
	 *
1578
	 * @return float The subtotal of the payment
1579
	 */
1580
	private function setup_subtotal() {
1581
		$subtotal = $this->total;
1582
1583
		return $subtotal;
1584
	}
1585
1586
	/**
1587
	 * Setup the currency code
1588
	 *
1589
	 * @since  1.5
1590
	 * @since  2.0 Set currency from _give_payment_currency meta key
1591
	 * @access private
1592
	 *
1593
	 * @return string The currency for the payment
1594
	 */
1595
	private function setup_currency() {
1596
		$currency = $this->get_meta( '_give_payment_currency', true );
1597
		$currency = ! empty( $currency ) ?
1598
			$currency :
1599
			apply_filters( 'give_payment_currency_default', give_get_currency(), $this );
1600
1601
		return $currency;
1602
	}
1603
1604
	/**
1605
	 * Setup the gateway used for the payment
1606
	 *
1607
	 * @since  1.5
1608
	 * @access private
1609
	 *
1610
	 * @return string The gateway
1611
	 */
1612
	private function setup_gateway() {
1613
		$gateway = $this->get_meta( '_give_payment_gateway', true );
1614
1615
		return $gateway;
1616
	}
1617
1618
	/**
1619
	 * Setup the donation ID
1620
	 *
1621
	 * @since  1.5
1622
	 * @access private
1623
	 *
1624
	 * @return string The donation ID
1625
	 */
1626
	private function setup_transaction_id() {
1627
		$transaction_id = $this->get_meta( '_give_payment_transaction_id', true );
1628
1629
		if ( empty( $transaction_id ) ) {
1630
			$gateway        = $this->gateway;
1631
			$transaction_id = apply_filters( "give_get_payment_transaction_id-{$gateway}", $this->ID );
1632
		}
1633
1634
		return $transaction_id;
1635
	}
1636
1637
	/**
1638
	 * Setup the IP Address for the payment
1639
	 *
1640
	 * @since  1.5
1641
	 * @since  2.0 Set ip address from _give_payment_donor_ip meta key
1642
	 * @access private
1643
	 *
1644
	 * @return string The IP address for the payment
1645
	 */
1646
	private function setup_ip() {
1647
		$ip = $this->get_meta( '_give_payment_donor_ip', true );
1648
1649
		return $ip;
1650
	}
1651
1652
	/**
1653
	 * Setup the donor ID.
1654
	 *
1655
	 * @since  1.5
1656
	 * @since  2.0 Set id from _give_payment_donor_id meta key
1657
	 * @access private
1658
	 *
1659
	 * @return int The Donor ID.
1660
	 */
1661
	private function setup_donor_id() {
1662
		$donor_id = $this->get_meta( '_give_payment_donor_id', true );
1663
1664
		return $donor_id;
1665
	}
1666
1667
	/**
1668
	 * Setup the User ID associated with the donation
1669
	 *
1670
	 * @since  1.5
1671
	 * @since  2.0 Get user id connect to donor from donor table instead of payment meta.
1672
	 *
1673
	 * @access private
1674
	 *
1675
	 * @return int The User ID
1676
	 */
1677
	private function setup_user_id() {
1678
1679
		$donor   = Give()->customers->get_customer_by( 'id', $this->customer_id );
1680
		$user_id = $donor ? absint( $donor->user_id ) : 0;
1681
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1682
1683
		return $user_id;
1684
	}
1685
1686
	/**
1687
	 * Setup the email address for the donation.
1688
	 *
1689
	 * @since  1.5
1690
	 * @since  2.0 Set email from _give_payment_donor_email meta key
1691
	 *
1692
	 * @access private
1693
	 *
1694
	 * @return string The email address for the payment.
1695
	 */
1696
	private function setup_email() {
1697
		$email = $this->get_meta( '_give_payment_donor_email', true );
1698
1699
		if ( empty( $email ) && $this->customer_id ) {
1700
			$email = Give()->donors->get_column( 'email', $this->customer_id );
1701
		}
1702
1703
		return $email;
1704
	}
1705
1706
	/**
1707
	 * Setup the user info.
1708
	 *
1709
	 * @since  1.5
1710
	 * @access private
1711
	 *
1712
	 * @return array The user info associated with the payment.
1713
	 */
1714
	private function setup_user_info() {
1715
		$defaults = array(
1716
			'first_name' => $this->first_name,
1717
			'last_name'  => $this->last_name,
1718
		);
1719
1720
		$user_info = isset( $this->payment_meta['user_info'] ) ? maybe_unserialize( $this->payment_meta['user_info'] ) : array();
1721
		$user_info = wp_parse_args( $user_info, $defaults );
1722
1723
		if ( empty( $user_info ) ) {
1724
			// Get the donor, but only if it's been created.
1725
			$donor = new Give_Donor( $this->customer_id );
1726
1727
			if ( $donor->id > 0 ) {
1728
				$name      = explode( ' ', $donor->name, 2 );
1729
				$user_info = array(
1730
					'first_name' => $name[0],
1731
					'last_name'  => $name[1],
1732
					'email'      => $donor->email,
1733
					'discount'   => 'none',
1734
				);
1735
			}
1736
		} else {
1737
			// Get the donor, but only if it's been created.
1738
			$donor = new Give_Donor( $this->customer_id );
1739
			if ( $donor->id > 0 ) {
1740
				foreach ( $user_info as $key => $value ) {
1741
					if ( ! empty( $value ) ) {
1742
						continue;
1743
					}
1744
1745
					switch ( $key ) {
1746
						case 'first_name':
1747
							$name = explode( ' ', $donor->name, 2 );
1748
1749
							$user_info[ $key ] = $name[0];
1750
							break;
1751
1752
						case 'last_name':
1753
							$name      = explode( ' ', $donor->name, 2 );
1754
							$last_name = ! empty( $name[1] ) ? $name[1] : '';
1755
1756
							$user_info[ $key ] = $last_name;
1757
							break;
1758
1759
						case 'email':
1760
							$user_info[ $key ] = $donor->email;
1761
							break;
1762
					}
1763
				}
1764
			}
1765
		}// End if().
1766
1767
		return $user_info;
1768
1769
	}
1770
1771
	/**
1772
	 * Setup the Address for the payment.
1773
	 *
1774
	 * @since  1.5
1775
	 * @access private
1776
	 *
1777
	 * @return array The Address information for the payment.
1778
	 */
1779
	private function setup_address() {
1780
		$address['line1']   = give_get_meta( $this->ID, '_give_donor_billing_address1', true, '' );
0 ignored issues
show
'' is of type string, but the function expects a boolean.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

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