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