PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.2.1
GiveWP – Donation Plugin and Fundraising Platform v2.2.1
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 / class-give-donor.php
give / includes Last commit date
admin 7 years ago api 7 years ago deprecated 7 years ago donors 7 years ago emails 7 years ago forms 7 years ago gateways 7 years ago libraries 7 years ago payments 7 years ago actions.php 7 years ago ajax-functions.php 7 years ago class-give-async-process.php 8 years ago class-give-background-updater.php 7 years ago class-give-cache.php 7 years ago class-give-cli-commands.php 8 years ago class-give-comment.php 7 years ago class-give-cron.php 8 years ago class-give-db-donor-meta.php 8 years ago class-give-db-donors.php 7 years ago class-give-db-form-meta.php 8 years ago class-give-db-logs-meta.php 8 years ago class-give-db-logs.php 7 years ago class-give-db-meta.php 7 years ago class-give-db-payment-meta.php 7 years ago class-give-db-sequential-ordering.php 7 years ago class-give-db-sessions.php 7 years ago class-give-db.php 8 years ago class-give-donate-form.php 8 years ago class-give-donor-wall-widget.php 7 years ago class-give-donor.php 7 years ago class-give-email-access.php 8 years ago class-give-html-elements.php 7 years ago class-give-license-handler.php 7 years ago class-give-logging.php 8 years ago class-give-readme-parser.php 8 years ago class-give-roles.php 8 years ago class-give-scripts.php 7 years ago class-give-session.php 7 years ago class-give-stats.php 8 years ago class-give-template-loader.php 8 years ago class-give-tooltips.php 8 years ago class-give-translation.php 8 years ago class-notices.php 7 years ago country-functions.php 8 years ago currency-functions.php 7 years ago error-tracking.php 8 years ago filters.php 7 years ago formatting.php 7 years ago import-functions.php 7 years ago install.php 7 years ago login-register.php 8 years ago misc-functions.php 7 years ago plugin-compatibility.php 8 years ago post-types.php 8 years ago price-functions.php 7 years ago process-donation.php 7 years ago shortcodes.php 7 years ago template-functions.php 8 years ago user-functions.php 7 years ago
class-give-donor.php
1654 lines
1 <?php
2 /**
3 * Donor
4 *
5 * @package Give
6 * @subpackage Classes/Give_Donor
7 * @copyright Copyright (c) 2016, WordImpress
8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 * @since 1.0
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Give_Donor Class
19 *
20 * This class handles customers.
21 *
22 * @since 1.0
23 */
24 class Give_Donor {
25
26 /**
27 * The donor ID
28 *
29 * @since 1.0
30 * @access public
31 *
32 * @var int
33 */
34 public $id = 0;
35
36 /**
37 * The donor's donation count.
38 *
39 * @since 1.0
40 * @access public
41 *
42 * @var int
43 */
44 public $purchase_count = 0;
45
46 /**
47 * The donor's lifetime value.
48 *
49 * @since 1.0
50 * @access public
51 *
52 * @var int
53 */
54 public $purchase_value = 0;
55
56 /**
57 * The donor's email.
58 *
59 * @since 1.0
60 * @access public
61 *
62 * @var string
63 */
64 public $email;
65
66 /**
67 * The donor's emails.
68 *
69 * @since 1.7
70 * @access public
71 *
72 * @var array
73 */
74 public $emails;
75
76 /**
77 * The donor's name.
78 *
79 * @since 1.0
80 * @access public
81 *
82 * @var string
83 */
84 public $name;
85
86 /**
87 * The donor creation date.
88 *
89 * @since 1.0
90 * @access public
91 *
92 * @var string
93 */
94 public $date_created;
95
96 /**
97 * The payment IDs associated with the donor.
98 *
99 * @since 1.0
100 * @access public
101 *
102 * @var string
103 */
104 public $payment_ids;
105
106 /**
107 * The user ID associated with the donor.
108 *
109 * @since 1.0
110 * @access public
111 *
112 * @var int
113 */
114 public $user_id;
115
116 /**
117 * Donor notes saved by admins.
118 *
119 * @since 1.0
120 * @access public
121 *
122 * @var array
123 */
124 public $notes;
125
126 /**
127 * Donor address.
128 *
129 * @since 1.0
130 * @access public
131 *
132 * @var array
133 */
134 public $address = array();
135
136 /**
137 * The Database Abstraction
138 *
139 * @since 1.0
140 * @access protected
141 *
142 * @var Give_DB_Donors
143 */
144 protected $db;
145
146 /**
147 * Give_Donor constructor.
148 *
149 * @param int|bool $_id_or_email
150 * @param bool $by_user_id
151 */
152 public function __construct( $_id_or_email = false, $by_user_id = false ) {
153
154 $this->db = Give()->donors;
155
156 if ( false === $_id_or_email || ( is_numeric( $_id_or_email ) && (int) $_id_or_email !== absint( $_id_or_email ) ) ) {
157 return false;
158 }
159
160 $by_user_id = is_bool( $by_user_id ) ? $by_user_id : false;
161
162 if ( is_numeric( $_id_or_email ) ) {
163 $field = $by_user_id ? 'user_id' : 'id';
164 } else {
165 $field = 'email';
166 }
167
168 $donor = $this->db->get_donor_by( $field, $_id_or_email );
169
170 if ( empty( $donor ) || ! is_object( $donor ) ) {
171 return false;
172 }
173
174 $this->setup_donor( $donor );
175
176 }
177
178 /**
179 * Setup Donor
180 *
181 * Set donor variables.
182 *
183 * @since 1.0
184 * @access private
185 *
186 * @param object $donor The Donor Object.
187 *
188 * @return bool If the setup was successful or not.
189 */
190 private function setup_donor( $donor ) {
191
192 if ( ! is_object( $donor ) ) {
193 return false;
194 }
195
196 // Get cached donors.
197 $donor_vars = Give_Cache::get_group( $donor->id, 'give-donors' );
198
199 if ( is_null( $donor_vars ) ) {
200 foreach ( $donor as $key => $value ) {
201
202 switch ( $key ) {
203
204 case 'notes':
205 $this->$key = $this->get_notes();
206 break;
207
208 default:
209 $this->$key = $value;
210 break;
211
212 }
213 }
214
215 // Get donor's all email including primary email.
216 $this->emails = (array) $this->get_meta( 'additional_email', false );
217 $this->emails = array( 'primary' => $this->email ) + $this->emails;
218
219 $this->setup_address();
220
221 Give_Cache::set_group( $donor->id, get_object_vars( $this ), 'give-donors' );
222 } else {
223 foreach ( $donor_vars as $donor_var => $value ) {
224 $this->$donor_var = $value;
225 }
226 }
227
228 // Donor ID and email are the only things that are necessary, make sure they exist.
229 if ( ! empty( $this->id ) && ! empty( $this->email ) ) {
230 return true;
231 }
232
233 return false;
234
235 }
236
237
238 /**
239 * Setup donor address.
240 *
241 * @since 2.0
242 * @access public
243 */
244 public function setup_address() {
245 global $wpdb;
246 $meta_type = Give()->donor_meta->meta_type;
247
248 $addresses = $wpdb->get_results( $wpdb->prepare( "
249 SELECT meta_key, meta_value FROM {$wpdb->donormeta}
250 WHERE meta_key
251 LIKE '%%%s%%'
252 AND {$meta_type}_id=%d
253 ", 'give_donor_address', $this->id ), ARRAY_N );
254
255 if ( empty( $addresses ) ) {
256 return $this->address;
257 }
258
259 foreach ( $addresses as $address ) {
260 $address[0] = str_replace( '_give_donor_address_', '', $address[0] );
261 $address[0] = explode( '_', $address[0] );
262
263 if ( 3 === count( $address[0] ) ) {
264 $this->address[ $address[0][0] ][ $address[0][2] ][ $address[0][1] ] = $address[1];
265 } else {
266 $this->address[ $address[0][0] ][ $address[0][1] ] = $address[1];
267 }
268 }
269 }
270
271 /**
272 * Returns the saved address for a donor
273 *
274 * @access public
275 *
276 * @since 2.1.3
277 *
278 * @param array $args donor address.
279 *
280 * @return array The donor's address, if any
281 */
282 public function get_donor_address( $args = array() ) {
283 $args = wp_parse_args(
284 $args,
285 array(
286 'address_type' => 'billing',
287 )
288 );
289
290 $default_address = array(
291 'line1' => '',
292 'line2' => '',
293 'city' => '',
294 'state' => '',
295 'country' => '',
296 'zip' => '',
297 );
298
299 // Backward compatibility.
300 if ( ! give_has_upgrade_completed( 'v20_upgrades_user_address' ) ) {
301
302 // Backward compatibility for user id param.
303 return wp_parse_args( (array) get_user_meta( $this->user_id, '_give_user_address', true ), $default_address );
304
305 }
306
307 if ( ! $this->id || empty( $this->address ) || ! array_key_exists( $args['address_type'], $this->address ) ) {
308 return $default_address;
309 }
310
311 switch ( true ) {
312 case is_string( end( $this->address[ $args['address_type'] ] ) ):
313 $address = wp_parse_args( $this->address[ $args['address_type'] ], $default_address );
314 break;
315
316 case is_array( end( $this->address[ $args['address_type'] ] ) ):
317 $address = wp_parse_args( array_shift( $this->address[ $args['address_type'] ] ), $default_address );
318 break;
319 }
320
321 return $address;
322 }
323
324 /**
325 * Magic __get function to dispatch a call to retrieve a private property.
326 *
327 * @since 1.0
328 * @access public
329 *
330 * @param $key
331 *
332 * @return mixed|\WP_Error
333 */
334 public function __get( $key ) {
335
336 if ( method_exists( $this, 'get_' . $key ) ) {
337
338 return call_user_func( array( $this, 'get_' . $key ) );
339
340 } else {
341
342 /* translators: %s: property key */
343 return new WP_Error( 'give-donor-invalid-property', sprintf( esc_html__( 'Can\'t get property %s.', 'give' ), $key ) );
344
345 }
346
347 }
348
349 /**
350 * Creates a donor.
351 *
352 * @since 1.0
353 * @access public
354 *
355 * @param array $data Array of attributes for a donor.
356 *
357 * @return bool|int False if not a valid creation, donor ID if user is found or valid creation.
358 */
359 public function create( $data = array() ) {
360
361 if ( $this->id != 0 || empty( $data ) ) {
362 return false;
363 }
364
365 $defaults = array(
366 'payment_ids' => '',
367 );
368
369 $args = wp_parse_args( $data, $defaults );
370 $args = $this->sanitize_columns( $args );
371
372 if ( empty( $args['email'] ) || ! is_email( $args['email'] ) ) {
373 return false;
374 }
375
376 if ( ! empty( $args['payment_ids'] ) && is_array( $args['payment_ids'] ) ) {
377 $args['payment_ids'] = implode( ',', array_unique( array_values( $args['payment_ids'] ) ) );
378 }
379
380 /**
381 * Fires before creating donors.
382 *
383 * @since 1.0
384 *
385 * @param array $args Donor attributes.
386 */
387 do_action( 'give_donor_pre_create', $args );
388
389 $created = false;
390
391 // The DB class 'add' implies an update if the donor being asked to be created already exists
392 if ( $this->db->add( $data ) ) {
393
394 // We've successfully added/updated the donor, reset the class vars with the new data
395 $donor = $this->db->get_donor_by( 'email', $args['email'] );
396
397 // Setup the donor data with the values from DB
398 $this->setup_donor( $donor );
399
400 $created = $this->id;
401 }
402
403 /**
404 * Fires after creating donors.
405 *
406 * @since 1.0
407 *
408 * @param bool|int $created False if not a valid creation, donor ID if user is found or valid creation.
409 * @param array $args Customer attributes.
410 */
411 do_action( 'give_donor_post_create', $created, $args );
412
413 return $created;
414
415 }
416
417 /**
418 * Updates a donor record.
419 *
420 * @since 1.0
421 * @access public
422 *
423 * @param array $data Array of data attributes for a donor (checked via whitelist).
424 *
425 * @return bool If the update was successful or not.
426 */
427 public function update( $data = array() ) {
428
429 if ( empty( $data ) ) {
430 return false;
431 }
432
433 $data = $this->sanitize_columns( $data );
434
435 /**
436 * Fires before updating donors.
437 *
438 * @since 1.0
439 *
440 * @param int $donor_id Donor id.
441 * @param array $data Donor attributes.
442 */
443 do_action( 'give_donor_pre_update', $this->id, $data );
444
445 $updated = false;
446
447 if ( $this->db->update( $this->id, $data ) ) {
448
449 $donor = $this->db->get_donor_by( 'id', $this->id );
450
451 $this->setup_donor( $donor );
452
453 $updated = true;
454 }
455
456 /**
457 * Fires after updating donors.
458 *
459 * @since 1.0
460 *
461 * @param bool $updated If the update was successful or not.
462 * @param int $donor_id Donor id.
463 * @param array $data Donor attributes.
464 */
465 do_action( 'give_donor_post_update', $updated, $this->id, $data );
466
467 return $updated;
468 }
469
470 /**
471 * Attach Payment
472 *
473 * Attach payment to the donor then triggers increasing stats.
474 *
475 * @since 1.0
476 * @access public
477 *
478 * @param int $payment_id The payment ID to attach to the donor.
479 * @param bool $update_stats For backwards compatibility, if we should increase the stats or not.
480 *
481 * @return bool If the attachment was successfully.
482 */
483 public function attach_payment( $payment_id = 0, $update_stats = true ) {
484
485 if ( empty( $payment_id ) ) {
486 return false;
487 }
488
489 if ( empty( $this->payment_ids ) ) {
490
491 $new_payment_ids = $payment_id;
492
493 } else {
494
495 $payment_ids = array_map( 'absint', explode( ',', $this->payment_ids ) );
496
497 if ( in_array( $payment_id, $payment_ids ) ) {
498 $update_stats = false;
499 }
500
501 $payment_ids[] = $payment_id;
502
503 $new_payment_ids = implode( ',', array_unique( array_values( $payment_ids ) ) );
504
505 }
506
507 /**
508 * Fires before attaching payments to donors.
509 *
510 * @since 1.0
511 *
512 * @param int $payment_id Payment id.
513 * @param int $donor_id Donor id.
514 */
515 do_action( 'give_donor_pre_attach_payment', $payment_id, $this->id );
516
517 $payment_added = $this->update( array( 'payment_ids' => $new_payment_ids ) );
518
519 if ( $payment_added ) {
520
521 $this->payment_ids = $new_payment_ids;
522
523 // We added this payment successfully, increment the stats
524 if ( $update_stats ) {
525 $payment_amount = give_donation_amount( $payment_id, array( 'type' => 'stats' ) );
526
527 if ( ! empty( $payment_amount ) ) {
528 $this->increase_value( $payment_amount );
529 }
530
531 $this->increase_purchase_count();
532 }
533 }
534
535 /**
536 * Fires after attaching payments to the donor.
537 *
538 * @since 1.0
539 *
540 * @param bool $payment_added If the attachment was successfully.
541 * @param int $payment_id Payment id.
542 * @param int $donor_id Donor id.
543 */
544 do_action( 'give_donor_post_attach_payment', $payment_added, $payment_id, $this->id );
545
546 return $payment_added;
547 }
548
549 /**
550 * Remove Payment
551 *
552 * Remove a payment from this donor, then triggers reducing stats.
553 *
554 * @since 1.0
555 * @access public
556 *
557 * @param int $payment_id The Payment ID to remove.
558 * @param bool $update_stats For backwards compatibility, if we should increase the stats or not.
559 *
560 * @return boolean If the removal was successful.
561 */
562 public function remove_payment( $payment_id = 0, $update_stats = true ) {
563
564 if ( empty( $payment_id ) ) {
565 return false;
566 }
567
568 $payment = new Give_Payment( $payment_id );
569
570 if ( 'publish' !== $payment->status && 'revoked' !== $payment->status ) {
571 $update_stats = false;
572 }
573
574 $new_payment_ids = '';
575
576 if ( ! empty( $this->payment_ids ) ) {
577
578 $payment_ids = array_map( 'absint', explode( ',', $this->payment_ids ) );
579
580 $pos = array_search( $payment_id, $payment_ids );
581 if ( false === $pos ) {
582 return false;
583 }
584
585 unset( $payment_ids[ $pos ] );
586 $payment_ids = array_filter( $payment_ids );
587
588 $new_payment_ids = implode( ',', array_unique( array_values( $payment_ids ) ) );
589
590 }
591
592 /**
593 * Fires before removing payments from customers.
594 *
595 * @since 1.0
596 *
597 * @param int $payment_id Payment id.
598 * @param int $donor_id Customer id.
599 */
600 do_action( 'give_donor_pre_remove_payment', $payment_id, $this->id );
601
602 $payment_removed = $this->update( array( 'payment_ids' => $new_payment_ids ) );
603
604 if ( $payment_removed ) {
605
606 $this->payment_ids = $new_payment_ids;
607
608 if ( $update_stats ) {
609 // We removed this payment successfully, decrement the stats
610 $payment_amount = give_donation_amount( $payment_id );
611
612 if ( ! empty( $payment_amount ) ) {
613 $this->decrease_value( $payment_amount );
614 }
615
616 $this->decrease_donation_count();
617 }
618 }
619
620 /**
621 * Fires after removing payments from donors.
622 *
623 * @since 1.0
624 *
625 * @param bool $payment_removed If the removal was successfully.
626 * @param int $payment_id Payment id.
627 * @param int $donor_id Donor id.
628 */
629 do_action( 'give_donor_post_remove_payment', $payment_removed, $payment_id, $this->id );
630
631 return $payment_removed;
632
633 }
634
635 /**
636 * Increase the donation count of a donor.
637 *
638 * @since 1.0
639 * @access public
640 *
641 * @param int $count The number to increase by.
642 *
643 * @return int The donation count.
644 */
645 public function increase_purchase_count( $count = 1 ) {
646
647 // Make sure it's numeric and not negative.
648 if ( ! is_numeric( $count ) || $count != absint( $count ) ) {
649 return false;
650 }
651
652 $new_total = (int) $this->purchase_count + (int) $count;
653
654 /**
655 * Fires before increasing the donor's donation count.
656 *
657 * @since 1.0
658 *
659 * @param int $count The number to increase by.
660 * @param int $donor_id Donor id.
661 */
662 do_action( 'give_donor_pre_increase_donation_count', $count, $this->id );
663
664 if ( $this->update( array( 'purchase_count' => $new_total ) ) ) {
665 $this->purchase_count = $new_total;
666 }
667
668 /**
669 * Fires after increasing the donor's donation count.
670 *
671 * @since 1.0
672 *
673 * @param int $purchase_count Donor donation count.
674 * @param int $count The number increased by.
675 * @param int $donor_id Donor id.
676 */
677 do_action( 'give_donor_post_increase_donation_count', $this->purchase_count, $count, $this->id );
678
679 return $this->purchase_count;
680 }
681
682 /**
683 * Decrease the donor donation count.
684 *
685 * @since 1.0
686 * @access public
687 *
688 * @param int $count The amount to decrease by.
689 *
690 * @return mixed If successful, the new count, otherwise false.
691 */
692 public function decrease_donation_count( $count = 1 ) {
693
694 // Make sure it's numeric and not negative
695 if ( ! is_numeric( $count ) || $count != absint( $count ) ) {
696 return false;
697 }
698
699 $new_total = (int) $this->purchase_count - (int) $count;
700
701 if ( $new_total < 0 ) {
702 $new_total = 0;
703 }
704
705 /**
706 * Fires before decreasing the donor's donation count.
707 *
708 * @since 1.0
709 *
710 * @param int $count The number to decrease by.
711 * @param int $donor_id Customer id.
712 */
713 do_action( 'give_donor_pre_decrease_donation_count', $count, $this->id );
714
715 if ( $this->update( array( 'purchase_count' => $new_total ) ) ) {
716 $this->purchase_count = $new_total;
717 }
718
719 /**
720 * Fires after decreasing the donor's donation count.
721 *
722 * @since 1.0
723 *
724 * @param int $purchase_count Donor's donation count.
725 * @param int $count The number decreased by.
726 * @param int $donor_id Donor id.
727 */
728 do_action( 'give_donor_post_decrease_donation_count', $this->purchase_count, $count, $this->id );
729
730 return $this->purchase_count;
731 }
732
733 /**
734 * Increase the donor's lifetime value.
735 *
736 * @since 1.0
737 * @access public
738 *
739 * @param float $value The value to increase by.
740 *
741 * @return mixed If successful, the new value, otherwise false.
742 */
743 public function increase_value( $value = 0.00 ) {
744
745 $new_value = floatval( $this->purchase_value ) + $value;
746
747 /**
748 * Fires before increasing donor lifetime value.
749 *
750 * @since 1.0
751 *
752 * @param float $value The value to increase by.
753 * @param int $donor_id Customer id.
754 */
755 do_action( 'give_donor_pre_increase_value', $value, $this->id );
756
757 if ( $this->update( array( 'purchase_value' => $new_value ) ) ) {
758 $this->purchase_value = $new_value;
759 }
760
761 /**
762 * Fires after increasing donor lifetime value.
763 *
764 * @since 1.0
765 *
766 * @param float $purchase_value Donor's lifetime value.
767 * @param float $value The value increased by.
768 * @param int $donor_id Donor id.
769 */
770 do_action( 'give_donor_post_increase_value', $this->purchase_value, $value, $this->id );
771
772 return $this->purchase_value;
773 }
774
775 /**
776 * Decrease a donor's lifetime value.
777 *
778 * @since 1.0
779 * @access public
780 *
781 * @param float $value The value to decrease by.
782 *
783 * @return mixed If successful, the new value, otherwise false.
784 */
785 public function decrease_value( $value = 0.00 ) {
786
787 $new_value = floatval( $this->purchase_value ) - $value;
788
789 if ( $new_value < 0 ) {
790 $new_value = 0.00;
791 }
792
793 /**
794 * Fires before decreasing donor lifetime value.
795 *
796 * @since 1.0
797 *
798 * @param float $value The value to decrease by.
799 * @param int $donor_id Donor id.
800 */
801 do_action( 'give_donor_pre_decrease_value', $value, $this->id );
802
803 if ( $this->update( array( 'purchase_value' => $new_value ) ) ) {
804 $this->purchase_value = $new_value;
805 }
806
807 /**
808 * Fires after decreasing donor lifetime value.
809 *
810 * @since 1.0
811 *
812 * @param float $purchase_value Donor lifetime value.
813 * @param float $value The value decreased by.
814 * @param int $donor_id Donor id.
815 */
816 do_action( 'give_donor_post_decrease_value', $this->purchase_value, $value, $this->id );
817
818 return $this->purchase_value;
819 }
820
821 /**
822 * Decrease/Increase a donor's lifetime value.
823 *
824 * This function will update donation stat on basis of current amount and new amount donation difference.
825 * Difference value can positive or negative. Negative value will decrease user donation stat while positive value
826 * increase donation stat.
827 *
828 * @since 1.0
829 * @access public
830 *
831 * @param float $curr_amount Current Donation amount.
832 * @param float $new_amount New (changed) Donation amount.
833 *
834 * @return mixed If successful, the new donation stat value, otherwise false.
835 */
836 public function update_donation_value( $curr_amount, $new_amount ) {
837 /**
838 * Payment total difference value can be:
839 * zero (in case amount not change)
840 * or -ve (in case amount decrease)
841 * or +ve (in case amount increase)
842 */
843 $payment_total_diff = $new_amount - $curr_amount;
844
845 // We do not need to update donation stat if donation did not change.
846 if ( ! $payment_total_diff ) {
847 return false;
848 }
849
850 if ( $payment_total_diff > 0 ) {
851 $this->increase_value( $payment_total_diff );
852 } else {
853 // Pass payment total difference as +ve value to decrease amount from user lifetime stat.
854 $this->decrease_value( - $payment_total_diff );
855 }
856
857 return $this->purchase_value;
858 }
859
860 /**
861 * Get the parsed notes for a donor as an array.
862 *
863 * @since 1.0
864 * @access public
865 *
866 * @param int $length The number of notes to get.
867 * @param int $paged What note to start at.
868 *
869 * @return array The notes requested.
870 */
871 public function get_notes( $length = 20, $paged = 1 ) {
872
873 $length = is_numeric( $length ) ? $length : 20;
874 $offset = is_numeric( $paged ) && $paged != 1 ? ( ( absint( $paged ) - 1 ) * $length ) : 0;
875
876 $all_notes = $this->get_raw_notes();
877 $notes_array = array_reverse( array_filter( explode( "\n\n", $all_notes ) ) );
878
879 $desired_notes = array_slice( $notes_array, $offset, $length );
880
881 return $desired_notes;
882
883 }
884
885 /**
886 * Get the total number of notes we have after parsing.
887 *
888 * @since 1.0
889 * @access public
890 *
891 * @return int The number of notes for the donor.
892 */
893 public function get_notes_count() {
894
895 $all_notes = $this->get_raw_notes();
896 $notes_array = array_reverse( array_filter( explode( "\n\n", $all_notes ) ) );
897
898 return count( $notes_array );
899
900 }
901
902 /**
903 * Get the total donation amount.
904 *
905 * @since 1.8.17
906 *
907 * @param array $args Pass any additional data.
908 *
909 * @return string|float
910 */
911 public function get_total_donation_amount( $args = array() ) {
912
913 /**
914 * Filter total donation amount.
915 *
916 * @since 1.8.17
917 *
918 * @param string|float $purchase_value Donor Purchase value.
919 * @param integer $donor_id Donor ID.
920 * @param array $args Pass additional data.
921 */
922 return apply_filters( 'give_get_total_donation_amount', $this->purchase_value, $this->id, $args );
923 }
924
925 /**
926 * Add a note for the donor.
927 *
928 * @since 1.0
929 * @access public
930 *
931 * @param string $note The note to add. Default is empty.
932 *
933 * @return string|boolean The new note if added successfully, false otherwise.
934 */
935 public function add_note( $note = '' ) {
936
937 $note = trim( $note );
938 if ( empty( $note ) ) {
939 return false;
940 }
941
942 $notes = $this->get_raw_notes();
943
944 if ( empty( $notes ) ) {
945 $notes = '';
946 }
947
948 $note_string = date_i18n( 'F j, Y H:i:s', current_time( 'timestamp' ) ) . ' - ' . $note;
949 $new_note = apply_filters( 'give_customer_add_note_string', $note_string );
950 $notes .= "\n\n" . $new_note;
951
952 /**
953 * Fires before donor note is added.
954 *
955 * @since 1.0
956 *
957 * @param string $new_note New note to add.
958 * @param int $donor_id Donor id.
959 */
960 do_action( 'give_donor_pre_add_note', $new_note, $this->id );
961
962 $updated = $this->update( array( 'notes' => $notes ) );
963
964 if ( $updated ) {
965 $this->notes = $this->get_notes();
966 }
967
968 /**
969 * Fires after donor note added.
970 *
971 * @since 1.0
972 *
973 * @param array $donor_notes Donor notes.
974 * @param string $new_note New note added.
975 * @param int $donor_id Donor id.
976 */
977 do_action( 'give_donor_post_add_note', $this->notes, $new_note, $this->id );
978
979 // Return the formatted note, so we can test, as well as update any displays
980 return $new_note;
981
982 }
983
984 /**
985 * Get the notes column for the donor
986 *
987 * @since 1.0
988 * @access private
989 *
990 * @return string The Notes for the donor, non-parsed.
991 */
992 private function get_raw_notes() {
993
994 $all_notes = $this->db->get_column( 'notes', $this->id );
995
996 return $all_notes;
997
998 }
999
1000 /**
1001 * Retrieve a meta field for a donor.
1002 *
1003 * @since 1.6
1004 * @access public
1005 *
1006 * @param string $meta_key The meta key to retrieve. Default is empty.
1007 * @param bool $single Whether to return a single value. Default is true.
1008 *
1009 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single is
1010 * true.
1011 */
1012 public function get_meta( $meta_key = '', $single = true ) {
1013 return Give()->donor_meta->get_meta( $this->id, $meta_key, $single );
1014 }
1015
1016 /**
1017 * Add a meta data field to a donor.
1018 *
1019 * @since 1.6
1020 * @access public
1021 *
1022 * @param string $meta_key Metadata name. Default is empty.
1023 * @param mixed $meta_value Metadata value.
1024 * @param bool $unique Optional. Whether the same key should not be added. Default is false.
1025 *
1026 * @return bool False for failure. True for success.
1027 */
1028 public function add_meta( $meta_key = '', $meta_value, $unique = false ) {
1029 return Give()->donor_meta->add_meta( $this->id, $meta_key, $meta_value, $unique );
1030 }
1031
1032 /**
1033 * Update a meta field based on donor ID.
1034 *
1035 * @since 1.6
1036 * @access public
1037 *
1038 * @param string $meta_key Metadata key. Default is empty.
1039 * @param mixed $meta_value Metadata value.
1040 * @param mixed $prev_value Optional. Previous value to check before removing. Default is empty.
1041 *
1042 * @return bool False on failure, true if success.
1043 */
1044 public function update_meta( $meta_key = '', $meta_value, $prev_value = '' ) {
1045 return Give()->donor_meta->update_meta( $this->id, $meta_key, $meta_value, $prev_value );
1046 }
1047
1048 /**
1049 * Remove metadata matching criteria from a donor.
1050 *
1051 * @since 1.6
1052 * @access public
1053 *
1054 * @param string $meta_key Metadata name. Default is empty.
1055 * @param mixed $meta_value Optional. Metadata value. Default is empty.
1056 *
1057 * @return bool False for failure. True for success.
1058 */
1059 public function delete_meta( $meta_key = '', $meta_value = '' ) {
1060 return Give()->donor_meta->delete_meta( $this->id, $meta_key, $meta_value );
1061 }
1062
1063 /**
1064 * Sanitize the data for update/create
1065 *
1066 * @since 1.0
1067 * @access private
1068 *
1069 * @param array $data The data to sanitize.
1070 *
1071 * @return array The sanitized data, based off column defaults.
1072 */
1073 private function sanitize_columns( $data ) {
1074
1075 $columns = $this->db->get_columns();
1076 $default_values = $this->db->get_column_defaults();
1077
1078 foreach ( $columns as $key => $type ) {
1079
1080 // Only sanitize data that we were provided
1081 if ( ! array_key_exists( $key, $data ) ) {
1082 continue;
1083 }
1084
1085 switch ( $type ) {
1086
1087 case '%s':
1088 if ( 'email' == $key ) {
1089 $data[ $key ] = sanitize_email( $data[ $key ] );
1090 } elseif ( 'notes' == $key ) {
1091 $data[ $key ] = strip_tags( $data[ $key ] );
1092 } else {
1093 $data[ $key ] = sanitize_text_field( $data[ $key ] );
1094 }
1095 break;
1096
1097 case '%d':
1098 if ( ! is_numeric( $data[ $key ] ) || (int) $data[ $key ] !== absint( $data[ $key ] ) ) {
1099 $data[ $key ] = $default_values[ $key ];
1100 } else {
1101 $data[ $key ] = absint( $data[ $key ] );
1102 }
1103 break;
1104
1105 case '%f':
1106 // Convert what was given to a float
1107 $value = floatval( $data[ $key ] );
1108
1109 if ( ! is_float( $value ) ) {
1110 $data[ $key ] = $default_values[ $key ];
1111 } else {
1112 $data[ $key ] = $value;
1113 }
1114 break;
1115
1116 default:
1117 $data[ $key ] = sanitize_text_field( $data[ $key ] );
1118 break;
1119
1120 }
1121 }
1122
1123 return $data;
1124 }
1125
1126 /**
1127 * Attach an email to the donor
1128 *
1129 * @since 1.7
1130 * @access public
1131 *
1132 * @param string $email The email address to attach to the donor
1133 * @param bool $primary Allows setting the email added as the primary
1134 *
1135 * @return bool If the email was added successfully
1136 */
1137 public function add_email( $email = '', $primary = false ) {
1138 if ( ! is_email( $email ) ) {
1139 return false;
1140 }
1141 $existing = new Give_Donor( $email );
1142
1143 if ( $existing->id > 0 ) {
1144 // Email address already belongs to another donor
1145 return false;
1146 }
1147
1148 if ( email_exists( $email ) ) {
1149 $user = get_user_by( 'email', $email );
1150 if ( $user->ID != $this->user_id ) {
1151 return false;
1152 }
1153 }
1154
1155 do_action( 'give_donor_pre_add_email', $email, $this->id, $this );
1156
1157 // Add is used to ensure duplicate emails are not added
1158 $ret = (bool) $this->add_meta( 'additional_email', $email );
1159
1160 do_action( 'give_donor_post_add_email', $email, $this->id, $this );
1161
1162 if ( $ret && true === $primary ) {
1163 $this->set_primary_email( $email );
1164 }
1165
1166 return $ret;
1167 }
1168
1169 /**
1170 * Remove an email from the donor.
1171 *
1172 * @since 1.7
1173 * @access public
1174 *
1175 * @param string $email The email address to remove from the donor.
1176 *
1177 * @return bool If the email was removed successfully.
1178 */
1179 public function remove_email( $email = '' ) {
1180 if ( ! is_email( $email ) ) {
1181 return false;
1182 }
1183
1184 do_action( 'give_donor_pre_remove_email', $email, $this->id, $this );
1185
1186 $ret = (bool) $this->delete_meta( 'additional_email', $email );
1187
1188 do_action( 'give_donor_post_remove_email', $email, $this->id, $this );
1189
1190 return $ret;
1191 }
1192
1193 /**
1194 * Set an email address as the donor's primary email.
1195 *
1196 * This will move the donor's previous primary email to an additional email.
1197 *
1198 * @since 1.7
1199 * @access public
1200 *
1201 * @param string $new_primary_email The email address to remove from the donor.
1202 *
1203 * @return bool If the email was set as primary successfully.
1204 */
1205 public function set_primary_email( $new_primary_email = '' ) {
1206 if ( ! is_email( $new_primary_email ) ) {
1207 return false;
1208 }
1209
1210 do_action( 'give_donor_pre_set_primary_email', $new_primary_email, $this->id, $this );
1211
1212 $existing = new Give_Donor( $new_primary_email );
1213
1214 if ( $existing->id > 0 && (int) $existing->id !== (int) $this->id ) {
1215 // This email belongs to another donor.
1216 return false;
1217 }
1218
1219 $old_email = $this->email;
1220
1221 // Update donor record with new email.
1222 $update = $this->update( array( 'email' => $new_primary_email ) );
1223
1224 // Remove new primary from list of additional emails.
1225 $remove = $this->remove_email( $new_primary_email );
1226
1227 // Add old email to additional emails list.
1228 $add = $this->add_email( $old_email );
1229
1230 $ret = $update && $remove && $add;
1231
1232 if ( $ret ) {
1233 $this->email = $new_primary_email;
1234 }
1235
1236 do_action( 'give_donor_post_set_primary_email', $new_primary_email, $this->id, $this );
1237
1238 return $ret;
1239 }
1240
1241 /**
1242 * Check if address valid or not.
1243 *
1244 * @since 2.0
1245 * @access private
1246 *
1247 * @param $address
1248 *
1249 * @return bool
1250 */
1251 private function is_valid_address( $address ) {
1252 $is_valid_address = true;
1253
1254 // Address ready to process even if only one value set.
1255 foreach ( $address as $address_type => $value ) {
1256 // @todo: Handle state field validation on basis of country.
1257 if ( in_array( $address_type, array( 'line2', 'state' ) ) ) {
1258 continue;
1259 }
1260
1261 if ( empty( $value ) ) {
1262 $is_valid_address = false;
1263 break;
1264 }
1265 }
1266
1267 return $is_valid_address;
1268 }
1269
1270 /**
1271 * Add donor address
1272 *
1273 * @since 2.0
1274 * @access public
1275 *
1276 * @param string $address_type
1277 * @param array $address {
1278 *
1279 * @type string $address2
1280 * @type string city
1281 * @type string zip
1282 * @type string state
1283 * @type string country
1284 * }
1285 *
1286 * @return bool
1287 */
1288 public function add_address( $address_type, $address ) {
1289 // Bailout.
1290 if ( empty( $address_type ) || ! $this->is_valid_address( $address ) || ! $this->id ) {
1291 return false;
1292 }
1293
1294 // Check if multiple address exist or not and set params.
1295 $multi_address_id = null;
1296 if ( $is_multi_address = ( false !== strpos( $address_type, '[]' ) ) ) {
1297 $address_type = $is_multi_address ? str_replace( '[]', '', $address_type ) : $address_type;
1298 } elseif ( $is_multi_address = ( false !== strpos( $address_type, '_' ) ) ) {
1299 $multi_address_id = $is_multi_address ? array_pop( explode( '_', $address_type ) ) : $address_type;
1300
1301 $address_type = $is_multi_address ? array_shift( explode( '_', $address_type ) ) : $address_type;
1302 }
1303
1304 // Bailout: do not save duplicate orders
1305 if ( $this->does_address_exist( $address_type, $address ) ) {
1306 return false;
1307 }
1308
1309 // Set default address.
1310 $address = wp_parse_args( $address, array(
1311 'line1' => '',
1312 'line2' => '',
1313 'city' => '',
1314 'state' => '',
1315 'country' => '',
1316 'zip' => '',
1317 ) );
1318
1319 // Set meta key prefix.
1320 global $wpdb;
1321 $meta_key_prefix = "_give_donor_address_{$address_type}_{address_name}";
1322 $meta_type = Give()->donor_meta->meta_type;
1323
1324 if ( $is_multi_address ) {
1325 if ( is_null( $multi_address_id ) ) {
1326 // Get latest address key to set multi address id.
1327 $multi_address_id = $wpdb->get_var( $wpdb->prepare( "
1328 SELECT meta_key FROM {$wpdb->donormeta}
1329 WHERE meta_key
1330 LIKE '%%%s%%'
1331 AND {$meta_type}_id=%d
1332 ORDER BY meta_id DESC
1333 LIMIT 1
1334 ", "_give_donor_address_{$address_type}_line1", $this->id ) );
1335
1336 if ( ! empty( $multi_address_id ) ) {
1337 $multi_address_id = absint( substr( strrchr( $multi_address_id, '_' ), 1 ) );
1338 $multi_address_id ++;
1339 } else {
1340 $multi_address_id = 0;
1341 }
1342 }
1343
1344 $meta_key_prefix = "_give_donor_address_{$address_type}_{address_name}_{$multi_address_id}";
1345 }
1346
1347 // Save donor address.
1348 foreach ( $address as $type => $value ) {
1349 $meta_key = str_replace( '{address_name}', $type, $meta_key_prefix );
1350 Give()->donor_meta->update_meta( $this->id, $meta_key, $value );
1351 }
1352
1353 $this->setup_address();
1354
1355 return true;
1356 }
1357
1358 /**
1359 * Remove donor address
1360 *
1361 * @since 2.0
1362 * @access public
1363 * @global wpdb $wpdb
1364 *
1365 * @param string $address_id
1366 *
1367 * @return bool
1368 */
1369 public function remove_address( $address_id ) {
1370 global $wpdb;
1371
1372 // Get address type.
1373 $is_multi_address = false !== strpos( $address_id, '_' ) ? true : false;
1374
1375 $address_type = false !== strpos( $address_id, '_' ) ? array_shift( explode( '_', $address_id ) ) : $address_id;
1376
1377 $address_count = false !== strpos( $address_id, '_' ) ? array_pop( explode( '_', $address_id ) ) : null;
1378
1379 // Set meta key prefix.
1380 $meta_key_prefix = "_give_donor_address_{$address_type}_%";
1381 if ( $is_multi_address && is_numeric( $address_count ) ) {
1382 $meta_key_prefix .= "_{$address_count}";
1383 }
1384
1385 $meta_type = Give()->donor_meta->meta_type;
1386
1387 // Process query.
1388 $row_affected = $wpdb->query( $wpdb->prepare( "
1389 DELETE FROM {$wpdb->donormeta}
1390 WHERE meta_key
1391 LIKE '%s'
1392 AND {$meta_type}_id=%d
1393 ", $meta_key_prefix, $this->id ) );
1394
1395 $this->setup_address();
1396
1397 return (bool) $row_affected;
1398 }
1399
1400 /**
1401 * Update donor address
1402 *
1403 * @since 2.0
1404 * @access public
1405 * @global wpdb $wpdb
1406 *
1407 * @param string $address_id
1408 * @param array $address
1409 *
1410 * @return bool
1411 */
1412 public function update_address( $address_id, $address ) {
1413 global $wpdb;
1414
1415 // Get address type.
1416 $is_multi_address = false !== strpos( $address_id, '_' ) ? true : false;
1417
1418 $address_type = false !== strpos( $address_id, '_' ) ? array_shift( explode( '_', $address_id ) ) : $address_id;
1419
1420 $address_count = false !== strpos( $address_id, '_' ) ? array_pop( explode( '_', $address_id ) ) : null;
1421
1422 // Set meta key prefix.
1423 $meta_key_prefix = "_give_donor_address_{$address_type}_%";
1424 if ( $is_multi_address && is_numeric( $address_count ) ) {
1425 $meta_key_prefix .= "_{$address_count}";
1426 }
1427
1428 $meta_type = Give()->donor_meta->meta_type;
1429
1430 // Process query.
1431 $row_affected = $wpdb->get_results( $wpdb->prepare( "
1432 SELECT meta_key FROM {$wpdb->donormeta}
1433 WHERE meta_key
1434 LIKE '%s'
1435 AND {$meta_type}_id=%d
1436 ", $meta_key_prefix, $this->id ) );
1437
1438 // Return result.
1439 if ( ! count( $row_affected ) ) {
1440 return false;
1441 }
1442
1443 // Update address.
1444 if ( ! $this->add_address( $address_id, $address ) ) {
1445 return false;
1446 }
1447
1448 return true;
1449 }
1450
1451
1452 /**
1453 * Check if donor already has current address
1454 *
1455 * @since 2.0
1456 * @access public
1457 *
1458 * @param string $current_address_type
1459 * @param array $current_address
1460 *
1461 * @return bool|null
1462 */
1463 public function does_address_exist( $current_address_type, $current_address ) {
1464 $status = false;
1465
1466 // Bailout.
1467 if ( empty( $current_address_type ) || empty( $current_address ) ) {
1468 return null;
1469 }
1470
1471 // Bailout.
1472 if ( empty( $this->address ) || empty( $this->address[ $current_address_type ] ) ) {
1473 return $status;
1474 }
1475
1476 // Get address.
1477 $address = $this->address[ $current_address_type ];
1478
1479 switch ( true ) {
1480
1481 // Single address.
1482 case is_string( end( $address ) ) :
1483 $status = $this->is_address_match( $current_address, $address );
1484 break;
1485
1486 // Multi address.
1487 case is_array( end( $address ) ):
1488 // Compare address.
1489 foreach ( $address as $saved_address ) {
1490 if ( empty( $saved_address ) ) {
1491 continue;
1492 }
1493
1494 // Exit loop immediately if address exist.
1495 if ( $status = $this->is_address_match( $current_address, $saved_address ) ) {
1496 break;
1497 }
1498 }
1499 break;
1500 }
1501
1502 return $status;
1503 }
1504
1505 /**
1506 * Compare address.
1507 *
1508 * @since 2.0
1509 * @access private
1510 *
1511 * @param array $address_1
1512 * @param array $address_2
1513 *
1514 * @return bool
1515 */
1516 private function is_address_match( $address_1, $address_2 ) {
1517 $result = array_diff( $address_1, $address_2 );
1518
1519 return empty( $result );
1520 }
1521
1522 /**
1523 * Split donor name into first name and last name
1524 *
1525 * @param int $id Donor ID
1526 *
1527 * @since 2.0
1528 * @return object
1529 */
1530 public function split_donor_name( $id ) {
1531 $first_name = $last_name = '';
1532 $donor = new Give_Donor( $id );
1533
1534 $split_donor_name = explode( ' ', $donor->name, 2 );
1535
1536 // Check for existence of first name after split of donor name.
1537 if ( is_array( $split_donor_name ) && ! empty( $split_donor_name[0] ) ) {
1538 $first_name = $split_donor_name[0];
1539 }
1540
1541 // Check for existence of last name after split of donor name.
1542 if ( is_array( $split_donor_name ) && ! empty( $split_donor_name[1] ) ) {
1543 $last_name = $split_donor_name[1];
1544 }
1545
1546 return (object) array( 'first_name' => $first_name, 'last_name' => $last_name );
1547 }
1548
1549 /**
1550 * Retrieves first name of donor with backward compatibility
1551 *
1552 * @since 2.0
1553 * @return string
1554 */
1555 public function get_first_name() {
1556 $first_name = $this->get_meta( '_give_donor_first_name' );
1557 if ( ! $first_name ) {
1558 $first_name = $this->split_donor_name( $this->id )->first_name;
1559 }
1560
1561 return $first_name;
1562 }
1563
1564 /**
1565 * Retrieves last name of donor with backward compatibility
1566 *
1567 * @since 2.0
1568 * @return string
1569 */
1570 public function get_last_name() {
1571 $first_name = $this->get_meta( '_give_donor_first_name' );
1572 $last_name = $this->get_meta( '_give_donor_last_name' );
1573
1574 // This condition will prevent unnecessary splitting of donor name to fetch last name.
1575 if ( ! $first_name && ! $last_name ) {
1576 $last_name = $this->split_donor_name( $this->id )->last_name;
1577 }
1578
1579 return ( $last_name ) ? $last_name : '';
1580 }
1581
1582 /**
1583 * Retrieves company name of donor
1584 *
1585 * @since 2.1
1586 *
1587 * @return string $company_name Donor Company Name
1588 */
1589 public function get_company_name() {
1590 $company_name = $this->get_meta( '_give_donor_company' );
1591
1592 return $company_name;
1593 }
1594
1595 /**
1596 * Retrieves last donation for the donor.
1597 *
1598 * @since 2.1
1599 *
1600 * @return string $company_name Donor Company Name
1601 */
1602 public function get_last_donation() {
1603
1604 $payments = array_unique( array_values( explode( ',', $this->payment_ids ) ) );
1605
1606 return end( $payments );
1607
1608 }
1609
1610 /**
1611 * Retrieves last donation for the donor.
1612 *
1613 * @since 2.1
1614 *
1615 * @param bool $formatted Whether to return with the date format or not.
1616 *
1617 * @return string The date of the last donation.
1618 */
1619 public function get_last_donation_date( $formatted = false ) {
1620 $completed_data = '';
1621
1622 // Return if donation id is invalid.
1623 if( ! ( $last_donation = absint( $this->get_last_donation() ) ) ) {
1624 return $completed_data;
1625 }
1626
1627 $completed_data = give_get_payment_completed_date( $last_donation );
1628
1629 if ( $formatted ) {
1630 return date_i18n( give_date_format(), strtotime( $completed_data ) );
1631 }
1632
1633 return $completed_data;
1634
1635 }
1636
1637 /**
1638 * Retrieves a donor's initials (first name and last name).
1639 *
1640 * @since 2.1
1641 *
1642 * @return string The donor's two initials (no middle).
1643 */
1644 public function get_donor_initals() {
1645
1646 $first_name_initial = mb_substr( $this->get_first_name(), 0, 1, 'utf-8' );
1647 $last_name_initial = mb_substr( $this->get_last_name(), 0, 1, 'utf-8' );
1648
1649 return apply_filters( 'get_donor_initals', $first_name_initial . $last_name_initial );
1650
1651 }
1652
1653 }
1654