PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.13
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.13
1.8.13.1 1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 All 212 releases
charitable / includes / abstracts / abstract-class-charitable-abstract-donation.php

abstract-class-charitable-abstract-donation.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.8.13, at includes/abstracts/abstract-class-charitable-abstract-donation.php

1,436 lines 34.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Donation model.
4 *
5 * @package Charitable/Classes/Charitable_Donation
6 * @author David Bisset
7 * @copyright Copyright (c) 2023, WP Charitable LLC
8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 * @since 1.4.0
10 * @version 1.6.55
11 */
12
13 // Exit if accessed directly.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 if ( ! class_exists( 'Charitable_Abstract_Donation' ) ) :
19
20 /**
21 * Donation Model
22 *
23 * @since 1.4.0
24 *
25 * @property int $ID
26 * @property int $post_author
27 * @property string $post_date
28 * @property string $post_date_gmt
29 * @property string $post_content
30 * @property string $post_title
31 * @property string $post_excerpt
32 * @property string $post_status
33 * @property string $comment_status
34 * @property string $ping_status
35 * @property string $post_password
36 * @property string $post_name
37 * @property string $to_ping
38 * @property string $pinged
39 * @property string $post_modified
40 * @property string $post_modified_gmt
41 * @property string $post_content_filtered
42 * @property int $post_parent
43 * @property string $guid
44 * @property int $menu_order
45 * @property string $post_type
46 * @property string $post_mime_type
47 * @property int $comment_count
48 * @property string $filter
49 */
50 abstract class Charitable_Abstract_Donation {
51
52 /**
53 * The donation ID.
54 *
55 * @var int
56 */
57 protected $donation_id;
58
59 /**
60 * The donation type.
61 *
62 * @var string
63 */
64 protected $donation_type;
65
66 /**
67 * Charitable_Donation donation data for the donation plan this donation is part of.
68 *
69 * @since 1.4.5
70 *
71 * @var false|Charitable_Donation
72 */
73 protected $donation_plan;
74
75 /**
76 * The database record for this donation from the Posts table.
77 *
78 * @var WP_Post
79 */
80 protected $donation_data;
81
82 /**
83 * The Campaign Donations table.
84 *
85 * @var Charitable_Campaign_Donations_DB
86 */
87 protected $campaign_donations_db;
88
89 /**
90 * The payment gateway used to process the donation.
91 *
92 * @var Charitable_Gateway_Interface
93 */
94 protected $gateway;
95
96 /**
97 * Gateway transaction ID.
98 *
99 * @since 1.4.6
100 *
101 * @var mixed
102 */
103 protected $gateway_transaction_id;
104
105 /**
106 * The campaign donations made as part of this donation.
107 *
108 * @var Object
109 */
110 protected $campaign_donations;
111
112 /**
113 * The Charitable_Donor object of the person who donated.
114 *
115 * @var Charitable_Donor
116 */
117 protected $donor;
118
119 /**
120 * The Charitable_Donation_Log object for this donation.
121 *
122 * @since 1.5.4
123 *
124 * @var Charitable_Donation_Log
125 */
126 protected $log;
127
128 /**
129 * The Charitable_Object_Fields object for this donation.
130 *
131 * @since 1.5.0
132 *
133 * @var Charitable_Object_Fields
134 */
135 protected $fields;
136
137 /**
138 * Instantiate a new donation object based off the ID.
139 *
140 * @since 1.0.0
141 *
142 * @param mixed $donation The donation ID or WP_Post object.
143 */
144 public function __construct( $donation ) {
145 if ( ! is_a( $donation, 'WP_Post' ) ) {
146 $donation = get_post( $donation );
147 }
148
149 $this->donation_id = $donation->ID;
150 $this->donation_data = $donation;
151 }
152
153 /**
154 * Magic getter.
155 *
156 * @since 1.0.0
157 *
158 * @param string $key The key of the field we're looking for.
159 * @return mixed
160 */
161 public function __get( $key ) {
162 if ( method_exists( $this, 'get_' . $key ) ) {
163 $method = 'get_' . $key;
164 return $this->$method;
165 }
166
167 return $this->donation_data->$key;
168 }
169
170 /**
171 * Return a field value.
172 *
173 * @since 1.5.0
174 *
175 * @param string $key The key of the field we're looking for.
176 * @return mixed
177 */
178 public function get( $key ) {
179 if ( $this->fields()->has_value_callback( $key ) ) {
180 return $this->fields()->get( $key );
181 }
182
183 /* Look for a local method. */
184 if ( method_exists( $this, 'get_' . $key ) ) {
185 $method = 'get_' . $key;
186 return $this->$method();
187 }
188
189 return $this->__get( $key );
190 }
191
192 /**
193 * Limit properties to be serialized.
194 *
195 * @since 1.6.18
196 *
197 * @return array
198 */
199 public function __sleep() {
200 return array(
201 'donation_id',
202 'donation_type',
203 'donation_plan',
204 'donation_data',
205 'campaign_donations_db',
206 'gateway_transaction_id',
207 'campaign_donations',
208 'donor',
209 );
210 }
211
212 /**
213 * Return the Charitable_Object_Fields instance.
214 *
215 * @since 1.5.0
216 *
217 * @return Charitable_Object_Fields
218 */
219 public function fields() {
220 if ( ! isset( $this->fields ) ) {
221 $this->fields = new Charitable_Object_Fields( charitable()->donation_fields(), $this );
222 }
223
224 return $this->fields;
225 }
226
227 /**
228 * Checks whether the donation has a donor's email address.
229 *
230 * @since 1.6.0
231 *
232 * @return boolean
233 */
234 public function has_valid_email() {
235 return $this->get_donor()->has_valid_email();
236 }
237
238 /**
239 * Return the donation number. By default, this is the ID, but it can be filtered.
240 *
241 * @since 1.0.0
242 *
243 * @return string
244 */
245 public function get_number() {
246 /**
247 * Filter the donation number.
248 *
249 * @since 1.0.0
250 *
251 * @param int $donation_id The donation ID.
252 */
253 return apply_filters( 'charitable_donation_number', $this->donation_id );
254 }
255
256 /**
257 * Get the donation data.
258 *
259 * @since 1.0.0
260 *
261 * @return Charitable_Campaign_Donations_DB
262 */
263 public function get_campaign_donations_db() {
264 if ( ! isset( $this->campaign_donations_db ) ) {
265 $this->campaign_donations_db = new Charitable_Campaign_Donations_DB();
266 }
267
268 return $this->campaign_donations_db;
269 }
270
271 /**
272 * The amount donated on this donation.
273 *
274 * @since 1.0.0
275 *
276 * @param boolean $sanitize Whether the value should be sanitized as a monetary amount.
277 * @return float|string
278 */
279 public function get_total_donation_amount( $sanitize = false ) {
280 $amount = $this->get_campaign_donations_db()->get_donation_total_amount( $this->donation_id );
281
282 if ( $sanitize ) {
283 $amount = Charitable_Currency::get_instance()->sanitize_monetary_amount( (string) $amount );
284 }
285
286 return $amount;
287 }
288
289 /**
290 * Return the formatted donation amount.
291 *
292 * @since 1.5.0
293 *
294 * @return string
295 */
296 public function get_amount_formatted() {
297 return charitable_format_money( $this->get_total_donation_amount(), false, false, $this->get_currency() );
298 }
299
300 /**
301 * Get the donation subtotal.
302 *
303 * Without any extensions, this will always be the same as the total.
304 * However, if Gift Aid or Fee Relief are used, the total donation may
305 * be greater than the subtotal.
306 *
307 * @since 1.6.54
308 *
309 * @return float
310 */
311 public function get_subtotal() {
312 return $this->get_total_donation_amount( true );
313 }
314
315 /**
316 * Get the donation subtotal.
317 *
318 * Without any extensions, this will always be the same as the total.
319 * However, if Gift Aid or Fee Relief are used, the total donation may
320 * be greater than the subtotal.
321 *
322 * @since 1.6.54
323 *
324 * @return float
325 */
326 public function get_total() {
327 /**
328 * Filter the total donation amount.
329 *
330 * @since 1.6.54
331 *
332 * @param float $subtotal The subtotal donation amount.
333 * @param Charitable_Abstract_Donation $donation This donation object.
334 */
335 return apply_filters( 'charitable_donation_total', $this->get_subtotal(), $this );
336 }
337
338 /**
339 * Return the campaigns donated to in this donation.
340 *
341 * @since 1.0.0
342 *
343 * @return object[]
344 */
345 public function get_campaign_donations() {
346 if ( ! isset( $this->campaign_donations ) ) {
347 $this->campaign_donations = $this->get_campaign_donations_db()->get_donation_records( $this->donation_id );
348 }
349
350 return $this->campaign_donations;
351 }
352
353 /**
354 * Returns an array of the campaigns that were donated to.
355 *
356 * @since 1.0.0
357 *
358 * @return string[]
359 */
360 public function get_campaigns() {
361 return array_map( array( $this, 'get_campaign_name' ), $this->get_campaign_donations() );
362 }
363
364 /**
365 * Returns the campaign name from a campaign donation record.
366 *
367 * @since 1.0.0
368 *
369 * @return string
370 */
371 public function get_campaign_name( $campaign_donation ) {
372 return $campaign_donation->campaign_name;
373 }
374
375 /**
376 * Return a comma separated list of the campaigns that were donated to.
377 *
378 * @since 1.0.0
379 *
380 * @param boolean $linked Whether to return the campaigns with links to the campaign pages.
381 * @return string
382 */
383 public function get_campaigns_donated_to( $linked = false ) {
384 $campaigns = $linked ? $this->get_campaigns_links() : $this->get_campaigns();
385
386 return implode( ', ', $campaigns );
387 }
388
389 /**
390 * Return a comma separated list of the campaigns that were donated to, with links to the campaigns.
391 *
392 * @since 1.0.0
393 *
394 * @return string[]
395 */
396 public function get_campaigns_links() {
397 $links = array();
398
399 foreach ( $this->get_campaign_donations() as $campaign ) {
400
401 if ( ! isset( $links[ $campaign->campaign_id ] ) ) {
402
403 $links[ $campaign->campaign_id ] = sprintf(
404 '<a href="%s" aria-label="%s">%s</a>',
405 get_permalink( $campaign->campaign_id ),
406 sprintf( '%s %s', _x( 'Go to', 'go to campaign', 'charitable' ), get_the_title( $campaign->campaign_id ) ),
407 get_the_title( $campaign->campaign_id )
408 );
409
410 }
411 }
412
413 return $links;
414 }
415
416 /**
417 * Return an array of the categories of the campaigns that were donated to.
418 *
419 * @uses wp_get_object_terms
420 * @uses wp_list_pluck
421 * @uses Charitable_Donation::get_campaign_donations
422 *
423 * @since 1.4.2
424 *
425 * @param string $taxonomy The taxonomy. Defaults to 'campaign_category'.
426 * @param array $args Optional arguments to pass to `wp_get_object_terms`.
427 * @return array|WP_Error The requested term data or empty array if no terms found.
428 * WP_Error if any of the $taxonomies don't exist.
429 */
430 public function get_campaign_categories_donated_to( $taxonomy = 'campaign_category', $args = array() ) {
431 $campaigns = wp_list_pluck( $this->get_campaign_donations(), 'campaign_id' );
432
433 return wp_get_object_terms( $campaigns, $taxonomy, $args );
434 }
435
436 /**
437 * Return a comma separated list of categories for the campaigns that were donated to.
438 *
439 * @uses Charitable_Donation::get_campaign_categories_donated_to
440 *
441 * @since 1.5.0
442 *
443 * @return string
444 */
445 public function get_campaign_categories_list() {
446 $categories = $this->get_campaign_categories_donated_to(
447 'campaign_category',
448 array(
449 'fields' => 'names',
450 )
451 );
452
453 if ( is_wp_error( $categories ) ) {
454 return '';
455 }
456
457 return implode( ', ', $categories );
458 }
459
460 /**
461 * Return a simple donation summary showing the campaigns that were donated to,
462 * and the amount of the donation.
463 *
464 * @since 1.5.0
465 *
466 * @return string
467 */
468 public function get_donation_summary() {
469 return implode( '', array_map( array( $this, 'get_donation_summary_line' ), $this->get_campaign_donations() ) );
470 }
471
472 /**
473 * Return a single line of a donation summary.
474 *
475 * @since 1.5.0
476 *
477 * @param object $campaign_donation A campaign donation object.
478 * @return string
479 */
480 protected function get_donation_summary_line( $campaign_donation ) {
481 $line_item = sprintf(
482 '%s: %s%s',
483 $campaign_donation->campaign_name,
484 charitable_format_money( $campaign_donation->amount, false, false, $this->get_currency() ),
485 PHP_EOL
486 );
487
488 /**
489 * Filter the line item.
490 *
491 * @since 1.0.0
492 * @since 1.5.0 Filter was previously defined in Charitable_Email::get_donation_summary()
493 * and included an array of shortcode arguments and a Charitable_Email object.
494 *
495 * @param string $line_item The line of text.
496 * @param object $campaign_donation A campaign donation object.
497 */
498 return apply_filters( 'charitable_donation_summary_line_item_email', $line_item, $campaign_donation );
499 }
500
501 /**
502 * Return the date of the donation.
503 *
504 * @since 1.0.0
505 *
506 * @param string $format The specified date format.
507 * @return string
508 */
509 public function get_date( $format = '' ) {
510 if ( empty( $format ) ) {
511 $format = get_option( 'date_format' );
512 }
513
514 return date_i18n( $format, strtotime( $this->donation_data->post_date ) );
515 }
516
517 /**
518 * Return the time of the donation.
519 *
520 * @since 1.5.0
521 *
522 * @param string $format Time format.
523 * @return string
524 */
525 public function get_time( $format = '' ) {
526 if ( empty( $format ) ) {
527 $format = get_option( 'time_format' );
528 }
529
530 return mysql2date( $format, $this->donation_data->post_date );
531 }
532
533 /**
534 * The name of the gateway used to process the donation.
535 *
536 * @since 1.0.0
537 *
538 * @return string
539 */
540 public function get_gateway() {
541 return get_post_meta( $this->donation_id, 'donation_gateway', true );
542 }
543
544 /**
545 * Return the unique donation key.
546 *
547 * @since 1.0.0
548 *
549 * @return string The key identifier of the donation.
550 */
551 public function get_donation_key() {
552 return get_post_meta( $this->donation_id, 'donation_key', true );
553 }
554
555 /**
556 * Return the donor data.
557 *
558 * @since 1.2.0
559 *
560 * @return array The donor data.
561 */
562 public function get_donor_data() {
563 return get_post_meta( $this->donation_id, 'donor', true );
564 }
565
566 /**
567 * The public label of the gateway used to process the donation.
568 *
569 * @since 1.0.0
570 *
571 * @return string
572 */
573 public function get_gateway_label() {
574 $gateway = $this->get_gateway_object();
575 $label = $gateway ? $gateway->get_label() : ucfirst( $this->get_gateway() );
576
577 /**
578 * Filter the gateway label.
579 *
580 * @since 1.2.0
581 *
582 * @param string $label The label.
583 * @param Charitable_Donation $donation This `Charitable_Donation` instance.
584 */
585 return apply_filters( 'charitable_donation_gateway_label', $label, $this );
586 }
587
588 /**
589 * Returns the gateway's object helper.
590 *
591 * @since 1.0.0
592 *
593 * @return false|Charitable_Gateway
594 */
595 public function get_gateway_object() {
596 $object = charitable_get_helper( 'gateways' )->get_gateway_object( $this->get_gateway() );
597
598 if ( is_null( $object ) ) {
599 return false;
600 }
601
602 return $object;
603 }
604
605 /**
606 * The status of this donation.
607 *
608 * @since 1.0.0
609 * @since 1.5.0 Deprecated $label argument. Use Charitable_Donation::get_status_label() instead.
610 *
611 * @param boolean $label Whether to return the label. If not, returns the key.
612 * @return string
613 */
614 public function get_status( $label = false ) {
615 $status = $this->donation_data->post_status;
616
617 if ( $label ) {
618 charitable_get_deprecated()->deprecated_argument(
619 __METHOD__,
620 '1.5.0',
621 __( 'The $label argument is deprecated. Use Charitable_Donation::get_status_label() instead.', 'charitable' )
622 );
623 return $this->get_status_label( $status );
624 }
625
626 return $status;
627 }
628
629 /**
630 * Return the donation status label.
631 *
632 * @since 1.5.0
633 *
634 * @param string $status Optional. The status to return the label for.
635 * @return string
636 */
637 public function get_status_label( $status = '' ) {
638 $statuses = charitable_get_valid_donation_statuses();
639 $status = empty( $status ) ? $this->get_status() : $status;
640
641 return array_key_exists( $status, $statuses ) ? $statuses[ $status ] : $status;
642 }
643
644 /**
645 * Checks the order status against a passed in status.
646 *
647 * @since 1.3.6
648 *
649 * @param string|array $status A status or array of statuses to check against.
650 * @return boolean
651 */
652 public function has_status( $status ) {
653 $donation_status = $this->get_status();
654 $has_status = ( is_array( $status ) && in_array( $donation_status, $status ) ) || $donation_status === $status;
655
656 /**
657 * Filter whether the donation has the status.
658 *
659 * @since 1.3.6
660 *
661 * @param boolean $has_status Whether the donation has the status.
662 * @param Charitable_Donation $donation This instance of `Charitable_Donation`.
663 * @param string|array $status The status we are checking for.
664 */
665 return apply_filters( 'charitable_donation_has_status', $has_status, $this, $status );
666 }
667
668 /**
669 * Returns the donation ID.
670 *
671 * @since 1.0.0
672 *
673 * @return int
674 */
675 public function get_donation_id() {
676 return $this->donation_id;
677 }
678
679 /**
680 * Returns the donation type.
681 *
682 * @since 1.4.5
683 *
684 * @return string
685 */
686 public function get_donation_type() {
687 return $this->donation_type;
688 }
689
690 /**
691 * Returns the customer note attached to the donation.
692 *
693 * @since 1.0.0
694 *
695 * @return string
696 */
697 public function get_notes() {
698 return $this->donation_data->post_content;
699 }
700
701 /**
702 * Returns the donor ID of the donor.
703 *
704 * @since 1.0.0
705 *
706 * @return int|false
707 */
708 public function get_donor_id() {
709 $campaign_donation = current( $this->get_campaign_donations() );
710
711 if ( ! is_object( $campaign_donation ) ) {
712 return false;
713 }
714
715 return $campaign_donation->donor_id;
716 }
717
718 /**
719 * Returns the donor who made this donation.
720 *
721 * @since 1.0.0
722 *
723 * @return Charitable_Donor
724 */
725 public function get_donor() {
726 if ( ! isset( $this->donor ) ) {
727 $this->donor = new Charitable_Donor( $this->get_donor_id(), $this->donation_id );
728 }
729
730 return $this->donor;
731 }
732
733 /**
734 * Returns the donor address.
735 *
736 * @since 1.2.0
737 *
738 * @return string
739 */
740 public function get_donor_address() {
741 return $this->get_donor()->get_address();
742 }
743
744 /**
745 * Return whether the donation has been manually edited.
746 *
747 * @since 1.5.0
748 *
749 * @return boolean
750 */
751 public function was_manually_edited() {
752 return (bool) get_post_meta( $this->ID, '_donation_manually_edited', true );
753 }
754
755 /**
756 * Return 'Yes' or 'No' for whether a donation was made in test mode.
757 *
758 * @since 1.5.0
759 *
760 * @param boolean $text Whether to return a boolean value or readable text.
761 * @return string|boolean
762 */
763 public function get_test_mode( $text = true ) {
764 $test_mode = intval( get_post_meta( $this->donation_id, 'test_mode', true ) );
765
766 if ( $text ) {
767 return $test_mode ? __( 'Yes', 'charitable' ) : __( 'No', 'charitable' );
768 }
769
770 return abs( $test_mode );
771 }
772
773 /**
774 * Check whether contact consent was given.
775 *
776 * @since 1.6.0
777 *
778 * @return string
779 */
780 public function get_contact_consent() {
781 $consent = get_post_meta( $this->ID, 'contact_consent', true );
782
783 /* The donor hasn't given their consent, or has withdrawn it. */
784 if ( ! $this->get_donor()->contact_consent ) {
785 return $consent ? __( 'Withdrawn', 'charitable' ) : __( 'Not Given', 'charitable' );
786 }
787
788 return $consent ? __( 'Given', 'charitable' ) : __( 'Given Later', 'charitable' );
789 }
790
791 /**
792 * Checks whether contact consent was explicitly set for this donation.
793 *
794 * If the donation form did not include a contact_consent field, this will
795 * return false. Otherwise, it will return true (including if the donor
796 * did not give their consent).
797 *
798 * @since 1.6.0
799 *
800 * @return boolean
801 */
802 public function contact_consent_explicitly_set() {
803 $consent = get_post_meta( $this->ID, 'contact_consent' );
804
805 return ! empty( $consent );
806 }
807
808 /**
809 * Return an array of meta relating to the donation.
810 *
811 * @since 1.2.0
812 *
813 * @return mixed[]
814 */
815 public function get_donation_meta() {
816 $fields = charitable()->donation_fields()->get_meta_fields();
817 $meta = array_map( array( $this, 'parse_donation_meta_field' ), $fields );
818 $meta = array_combine( array_keys( $fields ), $meta );
819
820 /**
821 * Filter the donation meta.
822 *
823 * @since 1.2.0
824 *
825 * @param array $meta Set of meta values in an array of arrays, with
826 * each array containing a 'label' and a 'value'.
827 * @param Charitable_Donation $donation This instance of `Charitable_Donation`.
828 */
829 return apply_filters( 'charitable_donation_admin_meta', $meta, $this );
830 }
831
832 /**
833 * Checks whether the donation is from the current user.
834 *
835 * @since 1.4.0
836 *
837 * @return boolean
838 */
839 public function is_from_current_user() {
840 /* If the donation key is stored in the session, the user can access this receipt */
841 if ( charitable_get_session()->has_donation_key( $this->get_donation_key() ) ) {
842 return true;
843 }
844
845 if ( ! is_user_logged_in() ) {
846 return false;
847 }
848
849 /* Retrieve the donor and current logged in user */
850 $donor = $this->get_donor();
851 $user = wp_get_current_user();
852
853 /* Make sure they match */
854 if ( $donor->ID ) {
855 return $donor->ID == $user->ID;
856 }
857
858 return $donor->get_email() == $user->user_email;
859 }
860
861 /**
862 * Check whether this donation can be refunded in the gateway automatically.
863 *
864 * @since 1.6.0
865 *
866 * @return boolean
867 */
868 public function is_refundable_in_gateway() {
869 $gateway = $this->get_gateway_object();
870 return $gateway && $gateway->is_donation_refundable( $this );
871 }
872
873 /**
874 * Return the donation log object for this donation.
875 *
876 * @since 1.5.4
877 *
878 * @return Charitable_Donation_Log
879 */
880 public function log() {
881 if ( ! isset( $this->log ) ) {
882 $this->log = new Charitable_Donation_Log( $this->ID );
883 }
884
885 return $this->log;
886 }
887
888 /**
889 * Get a donation's log.
890 *
891 * @since 1.0.0
892 * @since 1.3.0 Deprecated $donation_id arg. Method is now expected to be called in an object context.
893 * i.e. $donation->get_donation_log().
894 *
895 * @return array
896 */
897 public function get_donation_log( $donation_id = null ) {
898 if ( $donation_id ) {
899 charitable_get_deprecated()->deprecated_argument(
900 __METHOD__,
901 '1.3.0',
902 sprintf( __( '$donation_id is no longer required as get_donation_log() is used in object context. Use $donation->log()->get_meta_log() instead.', 'charitable' ) )
903 );
904 }
905
906 return $this->log()->get_meta_log();
907 }
908
909 /**
910 * Update the status of the donation.
911 *
912 * @uses wp_update_post()
913 *
914 * @since 1.0.0
915 *
916 * @param string $new_status The status to update the donation to.
917 * @return int The value 0 on failure. The donation ID on success.
918 */
919 public function update_status( $new_status ) {
920 $statuses = charitable_get_valid_donation_statuses();
921
922 if ( $new_status === 'complete' ) {
923 $new_status = 'charitable-completed';
924 }
925
926 $new_status = apply_filters( 'charitable_donation_update_status', $new_status, $statuses );
927
928 if ( false === charitable_is_valid_donation_status( $new_status ) ) {
929 $original_new_status = $new_status;
930 $new_status = array_search( $new_status, $statuses );
931
932 /**
933 * Log a warning if the status is not valid.
934 */
935 if ( charitable_is_debug() ) {
936 // @codingStandardsIgnoreStart
937 error_log('update_status-------');
938 error_log( print_r( $new_status, true ) );
939 error_log( print_r( $original_new_status, true ) );
940 error_log( print_r( $statuses, true ) );
941 // @codingStandardsIgnoreEnd
942 }
943
944 if ( false === $new_status ) {
945 charitable_get_deprecated()->doing_it_wrong(
946 __METHOD__,
947 /* translators: %s: status */
948 sprintf( '%s is not a valid donation status.', $original_new_status ),
949 '1.0.0'
950 );
951 return 0;
952 }
953 }
954
955 $old_status = $this->get_status();
956
957 if ( $old_status === $new_status ) {
958 return 0;
959 }
960
961 /* This actually updates the post status */
962 $this->donation_data->post_status = $new_status;
963
964 $donation_id = wp_update_post( $this->donation_data );
965
966 if ( is_wp_error( $donation_id ) ) {
967 return 0;
968 }
969
970 $message = sprintf(
971 /* translators: %$1s: old status; %$2s: new status. */
972 __( 'Donation status updated from %1$s to %2$s.', 'charitable' ),
973 isset( $statuses[ $old_status ] ) ? $statuses[ $old_status ] : $old_status,
974 isset( $statuses[ $new_status ] ) ? $statuses[ $new_status ] : $new_status
975 );
976
977 $this->log()->add( $message );
978
979 /**
980 * Handle specific Charitable status transitions.
981 *
982 * @since 1.5.0
983 *
984 * @param Charitable_Donation $donation This instance of `Charitable_Donation`.
985 */
986 do_action( 'charitable_donation_status_from_' . $old_status . '_to_' . $new_status, $this );
987
988 /**
989 * Handle specific Charitable status change.
990 *
991 * @since 1.5.0
992 *
993 * @param Charitable_Donation $donation This instance of `Charitable_Donation`.
994 * @param string $old_status The previous donation status.
995 */
996 do_action( 'charitable_donation_status_' . $new_status, $this, $old_status );
997
998 /**
999 * Handle all Charitable status changes.
1000 *
1001 * @since 1.5.0
1002 *
1003 * @param Charitable_Donation $donation This instance of `Charitable_Donation`.
1004 * @param string $new_status The new donation status.
1005 * @param string $old_status The previous donation status.
1006 */
1007 do_action( 'charitable_donation_status_changed', $this, $new_status, $old_status );
1008
1009 return $donation_id;
1010 }
1011
1012 /**
1013 * Add a message to the donation log.
1014 *
1015 * @since 1.0.0
1016 * @since 1.3.0 First parameter changed from $donation_id to $message, as function is now expected
1017 * to be used in an object context. i.e.: $donation->update_donation_log( 'my message' )
1018 * @since 1.5.0 Removed second parameter ($deprecated_message), which was only used for backwards
1019 * compatibility. We now use func_get_arg() instead to get the second passed argument.
1020 * @since 1.5.4 Now uses Charitable_Donation_Log::add() and returns a result.
1021 *
1022 * @param string $message The message to add to the log.
1023 * @return int|bool Meta ID if the key didn't exist, true on successful update,
1024 * false on failure.
1025 */
1026 public function update_donation_log( $message ) {
1027 if ( is_int( $message ) ) {
1028 charitable_get_deprecated()->deprecated_argument(
1029 __METHOD__,
1030 '1.3.0',
1031 sprintf( __( '$donation_id is no longer required as update_donation_log() is used in object context. Use $donation->update_donation_log($message)', 'charitable' ) )
1032 );
1033
1034 $message = func_get_arg( 1 );
1035 }
1036
1037 return $this->log()->add( $message );
1038 }
1039
1040 /**
1041 * Return the parent donation, if exists
1042 *
1043 * @since 1.4.5
1044 *
1045 * @return int
1046 */
1047 public function get_donation_plan_id() {
1048 return $this->donation_data->post_parent;
1049 }
1050
1051 /**
1052 * Return the parent donation, if exists.
1053 *
1054 * @since 1.4.5
1055 *
1056 * @return false|Charitable_Abstract_Donation
1057 */
1058 public function get_donation_plan() {
1059 if ( ! isset( $this->donation_plan ) ) {
1060 if ( $this->donation_data->post_parent > 0 ) {
1061 $this->donation_plan = charitable_get_donation( $this->donation_data->post_parent );
1062 } else {
1063 $this->donation_plan = false;
1064 }
1065 }
1066
1067 return $this->donation_plan;
1068 }
1069
1070
1071
1072 /**
1073 * Save the gateway's payment ID
1074 *
1075 * @since 1.8.7
1076 *
1077 * @param string $value The payment ID.
1078 * @return bool
1079 */
1080 public function set_gateway_payment_id( $value ) {
1081 $key = '_gateway_payment_id';
1082 $value = charitable_sanitize_donation_meta( $value, $key );
1083 return update_post_meta( $this->donation_id, $key, $value );
1084 }
1085
1086 /**
1087 * Get the gateway's payment ID
1088 *
1089 * @since 1.8.7
1090 *
1091 * @return string
1092 */
1093 public function get_gateway_payment_id() {
1094 return get_post_meta( $this->donation_id, '_gateway_payment_id', true );
1095 }
1096
1097 /**
1098 * Save the gateway's transaction ID
1099 *
1100 * @since 1.8.7
1101 *
1102 * @param string $value The transaction ID.
1103 * @return bool
1104 */
1105 public function set_gateway_transaction_id( $value ) {
1106 $key = '_gateway_transaction_id';
1107 $value = charitable_sanitize_donation_meta( $value, $key );
1108 return update_post_meta( $this->donation_id, $key, $value );
1109 }
1110
1111 /**
1112 * Get the gateway's transaction ID
1113 *
1114 * @since 1.8.7
1115 *
1116 * @return mixed
1117 */
1118 public function get_gateway_transaction_id() {
1119 if ( ! isset( $this->gateway_transaction_id ) ) {
1120 $this->gateway_transaction_id = get_post_meta( $this->donation_id, '_gateway_transaction_id', true );
1121 }
1122
1123 return $this->gateway_transaction_id;
1124 }
1125
1126 /**
1127 * Save the gateway's transaction URL
1128 *
1129 * @since 1.8.7
1130 *
1131 * @param string $value The transaction URL.
1132 * @return bool
1133 */
1134 public function set_gateway_transaction_url( $value ) {
1135 $key = '_gateway_transaction_url';
1136 $value = charitable_sanitize_donation_meta( $value, $key );
1137 return update_post_meta( $this->donation_id, $key, $value );
1138 }
1139
1140 /**
1141 * Get the gateway's transaction URL
1142 *
1143 * @since 1.8.7
1144 *
1145 * @return mixed
1146 */
1147 public function get_gateway_transaction_url() {
1148 return get_post_meta( $this->donation_id, '_gateway_transaction_url', true );
1149 }
1150
1151 /**
1152 * Save the receipt URL
1153 *
1154 * @since 1.8.7
1155 *
1156 * @param string $value The receipt URL.
1157 * @return bool
1158 */
1159 public function set_receipt_url( $value ) {
1160 $key = '_donation_receipt_url';
1161 $value = charitable_sanitize_donation_meta( $value, $key );
1162 return update_post_meta( $this->donation_id, $key, $value );
1163 }
1164
1165 /**
1166 * Get the receipt URL
1167 *
1168 * @since 1.8.7
1169 *
1170 * @return string
1171 */
1172 public function get_receipt_url() {
1173 return get_post_meta( $this->donation_id, '_donation_receipt_url', true );
1174 }
1175
1176
1177 /**
1178 * Save the gateway's subscription ID
1179 *
1180 * @since 1.8.7
1181 *
1182 * @param string $value The subscription ID.
1183 * @return bool
1184 */
1185 public function set_gateway_subscription_id( $value ) {
1186 $key = '_gateway_subscription_id';
1187 $value = charitable_sanitize_donation_meta( $value, $key );
1188 return update_post_meta( $this->donation_id, $key, $value );
1189 }
1190
1191 /**
1192 * Get the gateway's subscription ID
1193 *
1194 * @since 1.8.7
1195 *
1196 * @return string
1197 */
1198 public function get_gateway_subscription_id() {
1199 return get_post_meta( $this->donation_id, '_gateway_subscription_id', true );
1200 }
1201
1202 /**
1203 * Save the gateway's plan variation ID
1204 *
1205 * @since 1.8.7
1206 *
1207 * @param string $value The plan variation ID.
1208 * @return bool
1209 */
1210 public function set_gateway_plan_variation_id( $value ) {
1211 $key = '_gateway_plan_variation_id';
1212 $value = charitable_sanitize_donation_meta( $value, $key );
1213 return update_post_meta( $this->donation_id, $key, $value );
1214 }
1215
1216 /**
1217 * Get the gateway's plan variation ID
1218 *
1219 * @since 1.8.7
1220 *
1221 * @return string
1222 */
1223 public function get_gateway_plan_variation_id() {
1224 return get_post_meta( $this->donation_id, '_gateway_plan_variation_id', true );
1225 }
1226
1227
1228
1229
1230 /**
1231 * Return the date that the donation data was erased.
1232 *
1233 * @since 1.6.0
1234 *
1235 * @param string $format The format in which to return the date of erasure.
1236 * @return false|string The date of erasure, or false if the data has not been erased.
1237 */
1238 public function get_data_erasure_date( $format = null ) {
1239 $date = get_post_meta( $this->donation_id, 'data_erased', true );
1240
1241 if ( ! $date ) {
1242 return false;
1243 }
1244
1245 if ( is_null( $format ) ) {
1246 $format = get_option( 'date_format' );
1247 }
1248
1249 return mysql2date( $format, $date );
1250 }
1251
1252 /**
1253 * Get the currency used for this donation. If none was saved, use the
1254 * default currency.
1255 *
1256 * @since 1.6.55
1257 *
1258 * @return string
1259 */
1260 public function get_currency() {
1261 $currency = get_post_meta( $this->ID, 'currency', true );
1262 if ( ! $currency ) {
1263 $currency = charitable_get_currency();
1264 }
1265 return $currency;
1266 }
1267
1268 /**
1269 * Return an array containing a label and value for a donation meta field.
1270 *
1271 * @since 1.5.0
1272 *
1273 * @param Charitable_Donation_Field $field Instance of `Charitable_Donation_Field`.
1274 * @return array
1275 */
1276 protected function parse_donation_meta_field( Charitable_Donation_Field $field ) {
1277 $value = charitable_get_sanitized_donation_field_value( $this->get( $field->field ), $field->field );
1278
1279 if ( empty( $value ) ) {
1280 $value = '-';
1281 }
1282
1283 if ( 'donor_address' !== $field->field ) {
1284 $value = esc_html( $value );
1285 }
1286
1287 return array(
1288 'label' => $field->label,
1289 'value' => $value,
1290 );
1291 }
1292
1293 /**
1294 * Deprecated Methods
1295 */
1296
1297 /**
1298 * Return array of valid donations statuses.
1299 *
1300 * @deprecated 1.7.0
1301 *
1302 * @see charitable_get_valid_donation_statuses
1303 *
1304 * @since 1.0.0
1305 * @since 1.4.0 Deprecated
1306 *
1307 * @return array
1308 */
1309 public function get_valid_donation_statuses() {
1310 charitable_get_deprecated()->deprecated_function(
1311 __METHOD__,
1312 '1.4.0',
1313 'charitable_get_valid_donation_statuses'
1314 );
1315
1316 return charitable_get_valid_donation_statuses();
1317 }
1318
1319 /**
1320 * Returns whether the donation status is valid.
1321 *
1322 * @deprecated 1.7.0
1323 *
1324 * @see charitable_is_valid_donation_status
1325 *
1326 * @since 1.0.0
1327 * @since 1.4.0 Deprecated.
1328 *
1329 * @return boolean
1330 */
1331 public function is_valid_donation_status( $status ) {
1332 charitable_get_deprecated()->deprecated_function(
1333 __METHOD__,
1334 '1.4.0',
1335 'charitable_is_valid_donation_status'
1336 );
1337
1338 return charitable_is_valid_donation_status( $status );
1339 }
1340
1341 /**
1342 * Returns the donation statuses that signify a donation was complete.
1343 *
1344 * By default, this is just 'charitable-completed'. However, 'charitable-preapproval'
1345 * is also counted.
1346 *
1347 * @deprecated 1.7.0
1348 *
1349 * @see charitable_get_approval_statuses
1350 *
1351 * @since 1.0.0
1352 *
1353 * @return string[]
1354 */
1355 public function get_approval_statuses() {
1356 charitable_get_deprecated()->deprecated_function(
1357 __METHOD__,
1358 '1.4.0',
1359 'charitable_get_approval_statuses'
1360 );
1361
1362 return charitable_get_approval_statuses();
1363 }
1364
1365 /**
1366 * Returns whether the passed status is an confirmed status.
1367 *
1368 * @deprecated 1.7.0
1369 *
1370 * @see charitable_is_approved_status
1371 *
1372 * @since 1.0.0
1373 * @since 1.4.0 Deprecated.
1374 *
1375 * @return boolean
1376 */
1377 public function is_approved_status( $status ) {
1378 charitable_get_deprecated()->deprecated_function(
1379 __METHOD__,
1380 '1.4.0',
1381 'charitable_is_approved_status'
1382 );
1383
1384 return charitable_is_approved_status( $status );
1385 }
1386
1387 /**
1388 * Sanitize meta values before they are persisted to the database.
1389 *
1390 * @deprecated 1.7.0
1391 *
1392 * @see charitable_sanitize_donation_meta
1393 *
1394 * @since 1.0.0
1395 * @since 1.4.0
1396 *
1397 * @param mixed $value
1398 * @param string $key
1399 * @return mixed
1400 */
1401 public function sanitize_meta( $value, $key ) {
1402 charitable_get_deprecated()->deprecated_function(
1403 __METHOD__,
1404 '1.4.0',
1405 'charitable_sanitize_donation_meta()'
1406 );
1407
1408 return charitable_sanitize_donation_meta( $value, $key );
1409 }
1410
1411 /**
1412 * Flush the donations cache for every campaign receiving a donation.
1413 *
1414 * @deprecated 1.7.0
1415 *
1416 * @see charitable_flush_campaigns_donation_cache
1417 *
1418 * @since 1.0.0
1419 * @since 1.4.0 Deprecated.
1420 *
1421 * @param int $donation_id
1422 * @return void
1423 */
1424 public function flush_campaigns_donation_cache( $donation_id ) {
1425 charitable_get_deprecated()->deprecated_function(
1426 __METHOD__,
1427 '1.4.0',
1428 'charitable_sanitize_donation_meta()'
1429 );
1430
1431 return charitable_flush_campaigns_donation_cache( $donation_id );
1432 }
1433 }
1434
1435 endif;
1436