PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.4.7
GiveWP – Donation Plugin and Fundraising Platform v2.4.7
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 / 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 frontend 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 7 years ago class-give-background-updater.php 7 years ago class-give-cache-setting.php 7 years ago class-give-cache.php 7 years ago class-give-cli-commands.php 7 years ago class-give-comment.php 7 years ago class-give-cron.php 7 years ago class-give-db-comments-meta.php 7 years ago class-give-db-comments.php 7 years ago class-give-db-donor-meta.php 7 years ago class-give-db-donors.php 7 years ago class-give-db-form-meta.php 7 years ago class-give-db-logs-meta.php 7 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 7 years ago class-give-donate-form.php 7 years ago class-give-donor-wall-widget.php 7 years ago class-give-donor.php 7 years ago class-give-email-access.php 7 years ago class-give-license-handler.php 7 years ago class-give-logging.php 7 years ago class-give-readme-parser.php 7 years ago class-give-roles.php 7 years ago class-give-scripts.php 7 years ago class-give-session.php 7 years ago class-give-stats.php 7 years ago class-give-template-loader.php 8 years ago class-give-tooltips.php 7 years ago class-give-translation.php 8 years ago class-notices.php 7 years ago country-functions.php 7 years ago currencies-list.php 7 years ago currency-functions.php 7 years ago error-tracking.php 7 years ago filters.php 7 years ago formatting.php 7 years ago install.php 7 years ago login-register.php 7 years ago misc-functions.php 7 years ago plugin-compatibility.php 7 years ago post-types.php 7 years ago price-functions.php 7 years ago process-donation.php 7 years ago setting-functions.php 7 years ago shortcodes.php 7 years ago template-functions.php 7 years ago user-functions.php 7 years ago
class-give-donor.php
1688 lines
1 <?php
2 /**
3 * Donor
4 *
5 * @package Give
6 * @subpackage Classes/Give_Donor
7 * @copyright Copyright (c) 2016, GiveWP
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 // Backward compatibility.
949 $note_string = date_i18n( 'F j, Y H:i:s', current_time( 'timestamp' ) ) . ' - ' . $note;
950 $formatted_new_note = apply_filters( 'give_customer_add_note_string', $note_string );
951 $notes .= "\n\n" . $formatted_new_note;
952
953 /**
954 * Fires before donor note is added.
955 *
956 * @since 1.0
957 *
958 * @param string $formatted_new_note Formatted new note to add.
959 * @param int $donor_id Donor id.
960 */
961 do_action( 'give_donor_pre_add_note', $formatted_new_note, $this->id );
962
963 if ( ! give_has_upgrade_completed( 'v230_move_donor_note' ) ) {
964 // Backward compatibility.
965 $updated = $this->update( array( 'notes' => $notes ) );
966 } else {
967 $updated = Give()->comment->db->add(
968 array(
969 'comment_content' => $note,
970 'user_id' => get_current_user_id(),
971 'comment_parent' => $this->id,
972 'comment_type' => 'donor',
973 )
974 );
975 }
976
977 if ( $updated ) {
978 $this->notes = $this->get_notes();
979 }
980
981 /**
982 * Fires after donor note added.
983 *
984 * @since 1.0
985 *
986 * @param array $donor_notes Donor notes.
987 * @param string $formatted_new_note Formatted new note added.
988 * @param int $donor_id Donor id.
989 */
990 do_action( 'give_donor_post_add_note', $this->notes, $formatted_new_note, $this->id );
991
992 // Return the formatted note, so we can test, as well as update any displays
993 return $formatted_new_note;
994 }
995
996 /**
997 * Get the notes column for the donor
998 *
999 * @since 1.0
1000 * @access private
1001 *
1002 * @return string The Notes for the donor, non-parsed.
1003 */
1004 private function get_raw_notes() {
1005 $all_notes = '';
1006 $comments = Give()->comment->db->get_results_by( array( 'comment_parent' => $this->id ) );
1007
1008 // Generate notes output as we are doing before 2.3.0.
1009 if( ! empty( $comments ) ) {
1010 /* @var stdClass $comment */
1011 foreach ( $comments as $comment ) {
1012 $all_notes .= date_i18n( 'F j, Y H:i:s', strtotime( $comment->comment_date ) ) . " - {$comment->comment_content}\n\n";
1013 }
1014 }
1015
1016 // Backward compatibility.
1017 if( ! give_has_upgrade_completed('v230_move_donor_note') ) {
1018 $all_notes = $this->db->get_column( 'notes', $this->id );
1019 }
1020
1021 return $all_notes;
1022
1023 }
1024
1025 /**
1026 * Retrieve a meta field for a donor.
1027 *
1028 * @since 1.6
1029 * @access public
1030 *
1031 * @param string $meta_key The meta key to retrieve. Default is empty.
1032 * @param bool $single Whether to return a single value. Default is true.
1033 *
1034 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single is
1035 * true.
1036 */
1037 public function get_meta( $meta_key = '', $single = true ) {
1038 return Give()->donor_meta->get_meta( $this->id, $meta_key, $single );
1039 }
1040
1041 /**
1042 * Add a meta data field to a donor.
1043 *
1044 * @since 1.6
1045 * @access public
1046 *
1047 * @param string $meta_key Metadata name. Default is empty.
1048 * @param mixed $meta_value Metadata value.
1049 * @param bool $unique Optional. Whether the same key should not be added. Default is false.
1050 *
1051 * @return bool False for failure. True for success.
1052 */
1053 public function add_meta( $meta_key = '', $meta_value, $unique = false ) {
1054 return Give()->donor_meta->add_meta( $this->id, $meta_key, $meta_value, $unique );
1055 }
1056
1057 /**
1058 * Update a meta field based on donor ID.
1059 *
1060 * @since 1.6
1061 * @access public
1062 *
1063 * @param string $meta_key Metadata key. Default is empty.
1064 * @param mixed $meta_value Metadata value.
1065 * @param mixed $prev_value Optional. Previous value to check before removing. Default is empty.
1066 *
1067 * @return bool False on failure, true if success.
1068 */
1069 public function update_meta( $meta_key = '', $meta_value, $prev_value = '' ) {
1070 return Give()->donor_meta->update_meta( $this->id, $meta_key, $meta_value, $prev_value );
1071 }
1072
1073 /**
1074 * Remove metadata matching criteria from a donor.
1075 *
1076 * @since 1.6
1077 * @access public
1078 *
1079 * @param string $meta_key Metadata name. Default is empty.
1080 * @param mixed $meta_value Optional. Metadata value. Default is empty.
1081 *
1082 * @return bool False for failure. True for success.
1083 */
1084 public function delete_meta( $meta_key = '', $meta_value = '' ) {
1085 return Give()->donor_meta->delete_meta( $this->id, $meta_key, $meta_value );
1086 }
1087
1088 /**
1089 * Sanitize the data for update/create
1090 *
1091 * @since 1.0
1092 * @access private
1093 *
1094 * @param array $data The data to sanitize.
1095 *
1096 * @return array The sanitized data, based off column defaults.
1097 */
1098 private function sanitize_columns( $data ) {
1099
1100 $columns = $this->db->get_columns();
1101 $default_values = $this->db->get_column_defaults();
1102
1103 foreach ( $columns as $key => $type ) {
1104
1105 // Only sanitize data that we were provided
1106 if ( ! array_key_exists( $key, $data ) ) {
1107 continue;
1108 }
1109
1110 switch ( $type ) {
1111
1112 case '%s':
1113 if ( 'email' == $key ) {
1114 $data[ $key ] = sanitize_email( $data[ $key ] );
1115 } elseif ( 'notes' == $key ) {
1116 $data[ $key ] = strip_tags( $data[ $key ] );
1117 } else {
1118 $data[ $key ] = sanitize_text_field( $data[ $key ] );
1119 }
1120 break;
1121
1122 case '%d':
1123 if ( ! is_numeric( $data[ $key ] ) || (int) $data[ $key ] !== absint( $data[ $key ] ) ) {
1124 $data[ $key ] = $default_values[ $key ];
1125 } else {
1126 $data[ $key ] = absint( $data[ $key ] );
1127 }
1128 break;
1129
1130 case '%f':
1131 // Convert what was given to a float
1132 $value = floatval( $data[ $key ] );
1133
1134 if ( ! is_float( $value ) ) {
1135 $data[ $key ] = $default_values[ $key ];
1136 } else {
1137 $data[ $key ] = $value;
1138 }
1139 break;
1140
1141 default:
1142 $data[ $key ] = sanitize_text_field( $data[ $key ] );
1143 break;
1144
1145 }
1146 }
1147
1148 return $data;
1149 }
1150
1151 /**
1152 * Attach an email to the donor
1153 *
1154 * @since 1.7
1155 * @access public
1156 *
1157 * @param string $email The email address to attach to the donor
1158 * @param bool $primary Allows setting the email added as the primary
1159 *
1160 * @return bool If the email was added successfully
1161 */
1162 public function add_email( $email = '', $primary = false ) {
1163 if ( ! is_email( $email ) ) {
1164 return false;
1165 }
1166 $existing = new Give_Donor( $email );
1167
1168 if ( $existing->id > 0 ) {
1169 // Email address already belongs to another donor
1170 return false;
1171 }
1172
1173 if ( email_exists( $email ) ) {
1174 $user = get_user_by( 'email', $email );
1175 if ( $user->ID != $this->user_id ) {
1176 return false;
1177 }
1178 }
1179
1180 do_action( 'give_donor_pre_add_email', $email, $this->id, $this );
1181
1182 // Add is used to ensure duplicate emails are not added
1183 $ret = (bool) $this->add_meta( 'additional_email', $email );
1184
1185 do_action( 'give_donor_post_add_email', $email, $this->id, $this );
1186
1187 if ( $ret && true === $primary ) {
1188 $this->set_primary_email( $email );
1189 }
1190
1191 return $ret;
1192 }
1193
1194 /**
1195 * Remove an email from the donor.
1196 *
1197 * @since 1.7
1198 * @access public
1199 *
1200 * @param string $email The email address to remove from the donor.
1201 *
1202 * @return bool If the email was removed successfully.
1203 */
1204 public function remove_email( $email = '' ) {
1205 if ( ! is_email( $email ) ) {
1206 return false;
1207 }
1208
1209 do_action( 'give_donor_pre_remove_email', $email, $this->id, $this );
1210
1211 $ret = (bool) $this->delete_meta( 'additional_email', $email );
1212
1213 do_action( 'give_donor_post_remove_email', $email, $this->id, $this );
1214
1215 return $ret;
1216 }
1217
1218 /**
1219 * Set an email address as the donor's primary email.
1220 *
1221 * This will move the donor's previous primary email to an additional email.
1222 *
1223 * @since 1.7
1224 * @access public
1225 *
1226 * @param string $new_primary_email The email address to remove from the donor.
1227 *
1228 * @return bool If the email was set as primary successfully.
1229 */
1230 public function set_primary_email( $new_primary_email = '' ) {
1231 if ( ! is_email( $new_primary_email ) ) {
1232 return false;
1233 }
1234
1235 do_action( 'give_donor_pre_set_primary_email', $new_primary_email, $this->id, $this );
1236
1237 $existing = new Give_Donor( $new_primary_email );
1238
1239 if ( $existing->id > 0 && (int) $existing->id !== (int) $this->id ) {
1240 // This email belongs to another donor.
1241 return false;
1242 }
1243
1244 $old_email = $this->email;
1245
1246 // Update donor record with new email.
1247 $update = $this->update( array( 'email' => $new_primary_email ) );
1248
1249 // Remove new primary from list of additional emails.
1250 $remove = $this->remove_email( $new_primary_email );
1251
1252 // Add old email to additional emails list.
1253 $add = $this->add_email( $old_email );
1254
1255 $ret = $update && $remove && $add;
1256
1257 if ( $ret ) {
1258 $this->email = $new_primary_email;
1259 }
1260
1261 do_action( 'give_donor_post_set_primary_email', $new_primary_email, $this->id, $this );
1262
1263 return $ret;
1264 }
1265
1266 /**
1267 * Check if address valid or not.
1268 *
1269 * @since 2.0
1270 * @access private
1271 *
1272 * @param $address
1273 *
1274 * @return bool
1275 */
1276 private function is_valid_address( $address ) {
1277 $is_valid_address = true;
1278
1279 // Address ready to process even if only one value set.
1280 foreach ( $address as $address_type => $value ) {
1281 // @todo: Handle state field validation on basis of country.
1282 if ( in_array( $address_type, array( 'line2', 'state' ) ) ) {
1283 continue;
1284 }
1285
1286 if ( empty( $value ) ) {
1287 $is_valid_address = false;
1288 break;
1289 }
1290 }
1291
1292 return $is_valid_address;
1293 }
1294
1295 /**
1296 * Add donor address
1297 *
1298 * @since 2.0
1299 * @access public
1300 *
1301 * @param string $address_type
1302 * @param array $address {
1303 *
1304 * @type string $address2
1305 * @type string city
1306 * @type string zip
1307 * @type string state
1308 * @type string country
1309 * }
1310 *
1311 * @return bool
1312 */
1313 public function add_address( $address_type, $address ) {
1314 // Bailout.
1315 if ( empty( $address_type ) || ! $this->is_valid_address( $address ) || ! $this->id ) {
1316 return false;
1317 }
1318
1319 // Check if multiple address exist or not and set params.
1320 $multi_address_id = null;
1321 if ( $is_multi_address = ( false !== strpos( $address_type, '[]' ) ) ) {
1322 $address_type = $is_multi_address ? str_replace( '[]', '', $address_type ) : $address_type;
1323 } elseif ( $is_multi_address = ( false !== strpos( $address_type, '_' ) ) ) {
1324 $exploded_address_type = explode( '_', $address_type );
1325 $multi_address_id = $is_multi_address ? array_pop( $exploded_address_type ) : $address_type;
1326
1327 $address_type = $is_multi_address ? array_shift( $exploded_address_type ) : $address_type;
1328 }
1329
1330 // Bailout: do not save duplicate orders
1331 if ( $this->does_address_exist( $address_type, $address ) ) {
1332 return false;
1333 }
1334
1335 // Set default address.
1336 $address = wp_parse_args( $address, array(
1337 'line1' => '',
1338 'line2' => '',
1339 'city' => '',
1340 'state' => '',
1341 'country' => '',
1342 'zip' => '',
1343 ) );
1344
1345 // Set meta key prefix.
1346 global $wpdb;
1347 $meta_key_prefix = "_give_donor_address_{$address_type}_{address_name}";
1348 $meta_type = Give()->donor_meta->meta_type;
1349
1350 if ( $is_multi_address ) {
1351 if ( is_null( $multi_address_id ) ) {
1352 // Get latest address key to set multi address id.
1353 $multi_address_id = $wpdb->get_var( $wpdb->prepare( "
1354 SELECT meta_key FROM {$wpdb->donormeta}
1355 WHERE meta_key
1356 LIKE '%%%s%%'
1357 AND {$meta_type}_id=%d
1358 ORDER BY meta_id DESC
1359 LIMIT 1
1360 ", "_give_donor_address_{$address_type}_line1", $this->id ) );
1361
1362 if ( ! empty( $multi_address_id ) ) {
1363 $multi_address_id = absint( substr( strrchr( $multi_address_id, '_' ), 1 ) );
1364 $multi_address_id ++;
1365 } else {
1366 $multi_address_id = 0;
1367 }
1368 }
1369
1370 $meta_key_prefix = "_give_donor_address_{$address_type}_{address_name}_{$multi_address_id}";
1371 }
1372
1373 // Save donor address.
1374 foreach ( $address as $type => $value ) {
1375 $meta_key = str_replace( '{address_name}', $type, $meta_key_prefix );
1376 Give()->donor_meta->update_meta( $this->id, $meta_key, $value );
1377 }
1378
1379 $this->setup_address();
1380
1381 return true;
1382 }
1383
1384 /**
1385 * Remove donor address
1386 *
1387 * @since 2.0
1388 * @access public
1389 * @global wpdb $wpdb
1390 *
1391 * @param string $address_id
1392 *
1393 * @return bool
1394 */
1395 public function remove_address( $address_id ) {
1396 global $wpdb;
1397
1398 // Get address type.
1399 $is_multi_address = false !== strpos( $address_id, '_' ) ? true : false;
1400
1401 $address_type = false !== strpos( $address_id, '_' ) ? array_shift( explode( '_', $address_id ) ) : $address_id;
1402
1403 $address_count = false !== strpos( $address_id, '_' ) ? array_pop( explode( '_', $address_id ) ) : null;
1404
1405 // Set meta key prefix.
1406 $meta_key_prefix = "_give_donor_address_{$address_type}_%";
1407 if ( $is_multi_address && is_numeric( $address_count ) ) {
1408 $meta_key_prefix .= "_{$address_count}";
1409 }
1410
1411 $meta_type = Give()->donor_meta->meta_type;
1412
1413 // Process query.
1414 $row_affected = $wpdb->query( $wpdb->prepare( "
1415 DELETE FROM {$wpdb->donormeta}
1416 WHERE meta_key
1417 LIKE '%s'
1418 AND {$meta_type}_id=%d
1419 ", $meta_key_prefix, $this->id ) );
1420
1421 $this->setup_address();
1422
1423 return (bool) $row_affected;
1424 }
1425
1426 /**
1427 * Update donor address
1428 *
1429 * @since 2.0
1430 * @access public
1431 * @global wpdb $wpdb
1432 *
1433 * @param string $address_id
1434 * @param array $address
1435 *
1436 * @return bool
1437 */
1438 public function update_address( $address_id, $address ) {
1439 global $wpdb;
1440
1441 // Get address type.
1442 $is_multi_address = false !== strpos( $address_id, '_' ) ? true : false;
1443 $exploded_address_id = explode( '_', $address_id );
1444
1445 $address_type = false !== strpos( $address_id, '_' ) ? array_shift( $exploded_address_id ) : $address_id;
1446
1447 $address_count = false !== strpos( $address_id, '_' ) ? array_pop( $exploded_address_id ) : null;
1448
1449 // Set meta key prefix.
1450 $meta_key_prefix = "_give_donor_address_{$address_type}_%";
1451 if ( $is_multi_address && is_numeric( $address_count ) ) {
1452 $meta_key_prefix .= "_{$address_count}";
1453 }
1454
1455 $meta_type = Give()->donor_meta->meta_type;
1456
1457 // Process query.
1458 $row_affected = $wpdb->get_results( $wpdb->prepare( "
1459 SELECT meta_key FROM {$wpdb->donormeta}
1460 WHERE meta_key
1461 LIKE '%s'
1462 AND {$meta_type}_id=%d
1463 ", $meta_key_prefix, $this->id ) );
1464
1465 // Return result.
1466 if ( ! count( $row_affected ) ) {
1467 return false;
1468 }
1469
1470 // Update address.
1471 if ( ! $this->add_address( $address_id, $address ) ) {
1472 return false;
1473 }
1474
1475 return true;
1476 }
1477
1478
1479 /**
1480 * Check if donor already has current address
1481 *
1482 * @since 2.0
1483 * @access public
1484 *
1485 * @param string $current_address_type
1486 * @param array $current_address
1487 *
1488 * @return bool|null
1489 */
1490 public function does_address_exist( $current_address_type, $current_address ) {
1491 $status = false;
1492
1493 // Bailout.
1494 if ( empty( $current_address_type ) || empty( $current_address ) ) {
1495 return null;
1496 }
1497
1498 // Bailout.
1499 if ( empty( $this->address ) || empty( $this->address[ $current_address_type ] ) ) {
1500 return $status;
1501 }
1502
1503 // Get address.
1504 $address = $this->address[ $current_address_type ];
1505
1506 switch ( true ) {
1507
1508 // Single address.
1509 case is_string( end( $address ) ) :
1510 $status = $this->is_address_match( $current_address, $address );
1511 break;
1512
1513 // Multi address.
1514 case is_array( end( $address ) ):
1515 // Compare address.
1516 foreach ( $address as $saved_address ) {
1517 if ( empty( $saved_address ) ) {
1518 continue;
1519 }
1520
1521 // Exit loop immediately if address exist.
1522 if ( $status = $this->is_address_match( $current_address, $saved_address ) ) {
1523 break;
1524 }
1525 }
1526 break;
1527 }
1528
1529 return $status;
1530 }
1531
1532 /**
1533 * Compare address.
1534 *
1535 * @since 2.0
1536 * @access private
1537 *
1538 * @param array $address_1
1539 * @param array $address_2
1540 *
1541 * @return bool
1542 */
1543 private function is_address_match( $address_1, $address_2 ) {
1544 $result = array_diff_assoc( $address_1, $address_2 );
1545
1546 return empty( $result );
1547 }
1548
1549 /**
1550 * Split donor name into first name and last name
1551 *
1552 * @param int $id Donor ID
1553 *
1554 * @since 2.0
1555 * @return object
1556 */
1557 public function split_donor_name( $id ) {
1558 $first_name = $last_name = '';
1559 $donor = new Give_Donor( $id );
1560
1561 $split_donor_name = explode( ' ', $donor->name, 2 );
1562
1563 // Check for existence of first name after split of donor name.
1564 if ( is_array( $split_donor_name ) && ! empty( $split_donor_name[0] ) ) {
1565 $first_name = $split_donor_name[0];
1566 }
1567
1568 // Check for existence of last name after split of donor name.
1569 if ( is_array( $split_donor_name ) && ! empty( $split_donor_name[1] ) ) {
1570 $last_name = $split_donor_name[1];
1571 }
1572
1573 return (object) array( 'first_name' => $first_name, 'last_name' => $last_name );
1574 }
1575
1576 /**
1577 * Retrieves first name of donor with backward compatibility
1578 *
1579 * @since 2.0
1580 * @return string
1581 */
1582 public function get_first_name() {
1583 $first_name = $this->get_meta( '_give_donor_first_name' );
1584 if ( ! $first_name ) {
1585 $first_name = $this->split_donor_name( $this->id )->first_name;
1586 }
1587
1588 return $first_name;
1589 }
1590
1591 /**
1592 * Retrieves last name of donor with backward compatibility
1593 *
1594 * @since 2.0
1595 * @return string
1596 */
1597 public function get_last_name() {
1598 $first_name = $this->get_meta( '_give_donor_first_name' );
1599 $last_name = $this->get_meta( '_give_donor_last_name' );
1600
1601 // This condition will prevent unnecessary splitting of donor name to fetch last name.
1602 if ( ! $first_name && ! $last_name ) {
1603 $last_name = $this->split_donor_name( $this->id )->last_name;
1604 }
1605
1606 return ( $last_name ) ? $last_name : '';
1607 }
1608
1609 /**
1610 * Retrieves company name of donor
1611 *
1612 * @since 2.1
1613 *
1614 * @return string $company_name Donor Company Name
1615 */
1616 public function get_company_name() {
1617 $company_name = $this->get_meta( '_give_donor_company' );
1618
1619 return $company_name;
1620 }
1621
1622 /**
1623 * Retrieves last donation for the donor.
1624 *
1625 * @since 2.1
1626 *
1627 * @return string $company_name Donor Company Name
1628 */
1629 public function get_last_donation() {
1630
1631 $payments = array_unique( array_values( explode( ',', $this->payment_ids ) ) );
1632
1633 return end( $payments );
1634
1635 }
1636
1637 /**
1638 * Retrieves last donation for the donor.
1639 *
1640 * @since 2.1
1641 *
1642 * @param bool $formatted Whether to return with the date format or not.
1643 *
1644 * @return string The date of the last donation.
1645 */
1646 public function get_last_donation_date( $formatted = false ) {
1647 $completed_data = '';
1648
1649 // Return if donation id is invalid.
1650 if( ! ( $last_donation = absint( $this->get_last_donation() ) ) ) {
1651 return $completed_data;
1652 }
1653
1654 $completed_data = give_get_payment_completed_date( $last_donation );
1655
1656 if ( $formatted ) {
1657 return date_i18n( give_date_format(), strtotime( $completed_data ) );
1658 }
1659
1660 return $completed_data;
1661
1662 }
1663
1664 /**
1665 * Retrieves a donor's initials (first name and last name).
1666 *
1667 * @since 2.1
1668 *
1669 * @return string The donor's two initials (no middle).
1670 */
1671 public function get_donor_initals() {
1672 /**
1673 * Filter the donor name initials
1674 *
1675 * @since 2.1.0
1676 */
1677 return apply_filters(
1678 'get_donor_initals',
1679 give_get_name_initial( array(
1680 'firstname' => $this->get_first_name(),
1681 'lastname' => $this->get_last_name()
1682 ) )
1683 );
1684
1685 }
1686
1687 }
1688