PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.6.9
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.6.9
1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 1.7.0.9 1.8.0 All 210 releases
charitable / includes / users / class-charitable-user.php

class-charitable-user.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.6.9, at includes/users/class-charitable-user.php

1,042 lines 26.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Contains the class that models users in Charitable.
4 *
5 * There are several different user roles in Charitable, and one user
6 * may be more than one. People who make donations get the "donor" role;
7 * people who create campaigns (via Charitable Ambassadors) get
8 * the "campaign_creator" role; people who create fundraisers for campaigns
9 * get the "fundraiser" role.
10 *
11 * @version 1.0.0
12 * @package Charitable/Classes/Charitable_User
13 * @author Eric Daams
14 * @copyright Copyright (c) 2019, Studio 164a
15 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
16 */
17
18 // Exit if accessed directly.
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit;
21 }
22
23 if ( ! class_exists( 'Charitable_User' ) ) :
24
25 /**
26 * Charitable_User
27 *
28 * @since 1.0.0
29 *
30 * @property string $nickname
31 * @property string $description
32 * @property string $user_description
33 * @property string $first_name
34 * @property string $user_firstname
35 * @property string $last_name
36 * @property string $user_lastname
37 * @property string $user_login
38 * @property string $user_pass
39 * @property string $user_nicename
40 * @property string $user_email
41 * @property string $user_url
42 * @property string $user_registered
43 * @property string $user_activation_key
44 * @property string $user_status
45 * @property int $user_level
46 * @property string $display_name
47 * @property string $spam
48 * @property string $deleted
49 * @property string $locale
50 */
51 class Charitable_User extends WP_User {
52
53 /**
54 * The donor ID.
55 *
56 * NOTE: This is not the same as the user ID.
57 *
58 * @var int
59 * @since 1.0.0
60 */
61 protected $donor_id;
62
63 /**
64 * A mapping of user keys.
65 *
66 * @var string[]
67 * @since 1.4.0
68 */
69 protected $mapped_keys;
70
71 /**
72 * Core keys.
73 *
74 * @var string[]
75 * @since 1.4.0
76 */
77 protected $core_keys;
78
79 /**
80 * Create class object.
81 *
82 * @since 1.0.0
83 *
84 * @param int|string|stdClass|WP_User $id User's ID, a WP_User object, or a user object from the DB.
85 * @param string $name Optional. User's username.
86 * @param int $blog_id Optional Blog ID, defaults to current blog.
87 * @return void
88 */
89 public function __construct( $id = 0, $name = '', $blog_id = '' ) {
90 parent::__construct( $id, $name, $blog_id );
91 }
92
93 /**
94 * Create object using a donor ID.
95 *
96 * @since 1.0.0
97 *
98 * @param int $donor_id The donor ID.
99 * @return Charitable_user
100 */
101 public static function init_with_donor( $donor_id ) {
102 $user_id = charitable_get_table( 'donors' )->get_user_id( $donor_id );
103 $user = charitable_get_user( $user_id );
104 $user->set_donor_id( $donor_id );
105 return $user;
106 }
107
108 /**
109 * Magic getter method. Looks for the specified key in the mapped keys before using WP_User's __get method.
110 *
111 * @since 1.0.0
112 *
113 * @param string $key The key to retrieve.
114 * @return mixed
115 */
116 public function __get( $key ) {
117 return parent::__get( $this->map_key( $key ) );
118 }
119
120 /**
121 * Display the donor name when printing the object.
122 *
123 * @since 1.0.0
124 *
125 * @return string
126 */
127 public function __toString() {
128 return $this->get_name();
129 }
130
131 /**
132 * Determine whether a property or meta key is set
133 *
134 * Consults the users and usermeta tables.
135 *
136 * @since 1.5.0
137 *
138 * @param string $key Property.
139 * @return boolean
140 */
141 public function has_prop( $key ) {
142 return parent::has_prop( $this->map_key( $key ) );
143 }
144
145 /**
146 * Returns whether the user is logged in.
147 *
148 * @since 1.0.0
149 *
150 * @return boolean
151 */
152 public function is_logged_in() {
153 return 0 !== $this->ID;
154 }
155
156 /**
157 * Set the donor ID of this user.
158 *
159 * @since 1.0.0
160 *
161 * @param int $donor_id The Donor ID.
162 * @return void
163 */
164 public function set_donor_id( $donor_id ) {
165 $this->donor_id = $donor_id;
166 }
167
168 /**
169 * Return the donor ID of this user.
170 *
171 * @since 1.0.0
172 *
173 * @return int|false $donor_id
174 */
175 public function get_donor_id() {
176 if ( isset( $this->donor_id ) || ! is_null( $this->get_donor() ) ) {
177 return $this->donor_id;
178 }
179
180 return false;
181 }
182
183 /**
184 * Return the donor record.
185 *
186 * @since 1.0.0
187 *
188 * @return Object|null Object if a donor record could be matched. null if user is logged out or no donor record found.
189 */
190 public function get_donor() {
191 if ( ! $this->is_logged_in() && ! isset( $this->donor_id ) ) {
192 return null;
193 }
194
195 if ( isset( $this->donor_id ) ) {
196
197 $donor = wp_cache_get( $this->donor_id, 'donors' );
198
199 if ( is_object( $donor ) ) {
200 return $donor;
201 }
202
203 $donor = charitable_get_table( 'donors' )->get( $this->donor_id );
204
205 } else {
206
207 $donor = charitable_get_table( 'donors' )->get_by( 'email', $this->get( 'user_email' ) );
208
209 if ( ! is_object( $donor ) ) {
210 return null;
211 }
212
213 $this->donor_id = $donor->donor_id;
214
215 }//end if
216
217 wp_cache_add( $this->donor_id, $donor, 'donors' );
218
219 return $donor;
220 }
221
222 /**
223 * Returns whether the user has ever made a donation.
224 *
225 * @since 1.0.0
226 *
227 * @return boolean
228 */
229 public function is_donor() {
230 return ! is_null( $this->get_donor() );
231 }
232
233 /**
234 * Returns whether the user has verified their email address.
235 *
236 * @since 1.5.0
237 *
238 * @return int If verified, return 1. Otherwise return 0.
239 */
240 public function is_verified() {
241 return absint( get_user_meta( $this->ID, '_charitable_user_verified', true ) );
242 }
243
244 /**
245 * Mark a user as verified.
246 *
247 * @since 1.5.0
248 *
249 * @param boolean $verified Whether the user is verified.
250 * @return int|boolean Meta ID if the key didn't exist, true on successful update, false on failure.
251 */
252 public function mark_as_verified( $verified ) {
253 $verified = update_user_meta( $this->ID, '_charitable_user_verified', $verified );
254
255 if ( ! $verified ) {
256 return $verified;
257 }
258
259 /* Check for an existing donor account. */
260 $donor_id = $this->get_donor_id();
261
262 if ( $donor_id ) {
263 $donor = new Charitable_Donor( $donor_id );
264 $donor->set_user_id( $this->ID );
265 }
266
267 return $verified;
268 }
269
270 /**
271 * Returns the email address of the donor.
272 *
273 * @since 1.0.0
274 *
275 * @return string
276 */
277 public function get_email() {
278 if ( $this->get_donor() ) {
279 $email = $this->get_donor()->email;
280 } else {
281 $email = $this->get( 'user_email' );
282 }
283
284 /**
285 * Filter the user email address.
286 *
287 * @since 1.0.0
288 *
289 * @param string $email The email address.
290 * @param Charitable_User $user This instance of `Charitable_User`.
291 */
292 return apply_filters( 'charitable_user_email', $email, $this );
293 }
294
295 /**
296 * Returns the display name of the user.
297 *
298 * @since 1.0.0
299 *
300 * @return string
301 */
302 public function get_name() {
303 if ( $this->is_donor() ) {
304 $name = rtrim( sprintf( '%s %s', $this->get_donor()->first_name, $this->get_donor()->last_name ) );
305 } else {
306 $name = $this->display_name;
307 }
308
309 if ( ! $name ) {
310 $name = '';
311 }
312
313 return apply_filters( 'charitable_user_name', $name, $this );
314 }
315
316 /**
317 * Returns the first name of the user.
318 *
319 * @since 1.1.0
320 *
321 * @return string
322 */
323 public function get_first_name() {
324 if ( $this->is_donor() && $this->get_donor()->first_name ) {
325 $name = $this->get_donor()->first_name;
326 } else {
327 $name = $this->first_name;
328 }
329
330 return apply_filters( 'charitable_user_first_name', $name, $this );
331 }
332
333 /**
334 * Returns the last name of the user.
335 *
336 * @since 1.1.0
337 *
338 * @return string
339 */
340 public function get_last_name() {
341 if ( $this->is_donor() && $this->get_donor()->last_name ) {
342 $name = $this->get_donor()->last_name;
343 } else {
344 $name = $this->last_name;
345 }
346 return apply_filters( 'charitable_user_last_name', $name, $this );
347 }
348
349 /**
350 * Returns the user's location.
351 *
352 * @since 1.0.0
353 *
354 * @return string
355 */
356 public function get_location() {
357 $city = $this->get( 'donor_city' );
358 $state = $this->get( 'donor_state' );
359 $country = $this->get( 'donor_country' );
360 $location = '';
361
362 if ( strlen( $city ) || strlen( $state ) ) {
363 $region = strlen( $city ) ? $city : $state;
364
365 if ( strlen( $country ) ) {
366 $location = sprintf( '%s, %s', $region, $country );
367 } else {
368 $location = $region;
369 }
370 } elseif ( strlen( $country ) ) {
371 $location = $country;
372 }
373
374 return apply_filters( 'charitable_user_location', $location, $this );
375 }
376
377 /**
378 * Return an array of fields used for the address.
379 *
380 * @since 1.0.0
381 *
382 * @return array
383 */
384 public function get_address_fields() {
385 return apply_filters( 'charitable_user_address_fields', array(
386 'donor_address',
387 'donor_address_2',
388 'donor_city',
389 'donor_state',
390 'donor_postcode',
391 'donor_country',
392 ) );
393 }
394
395 /**
396 * Returns printable address of donor.
397 *
398 * @since 1.0.0
399 *
400 * @param int $donation_id Optional. If set, will return the address provided for the specific donation. Otherwise, returns the current address for the user.
401 * @return string
402 */
403 public function get_address( $donation_id = '' ) {
404 $address_fields = false;
405
406 if ( $donation_id ) {
407
408 $address_fields = get_post_meta( $donation_id, 'donor', true );
409
410 }
411
412 /* If the address fields were not set by the check above, get them from the user meta. */
413 if ( ! is_array( $address_fields ) ) {
414
415 $address_fields = array(
416 'first_name' => $this->get( 'first_name' ),
417 'last_name' => $this->get( 'last_name' ),
418 'company' => $this->get( 'donor_company' ),
419 'address' => $this->get( 'donor_address' ),
420 'address_2' => $this->get( 'donor_address_2' ),
421 'city' => $this->get( 'donor_city' ),
422 'state' => $this->get( 'donor_state' ),
423 'postcode' => $this->get( 'donor_postcode' ),
424 'country' => $this->get( 'donor_country' ),
425 );
426
427 }
428
429 $address_fields = apply_filters( 'charitable_user_address_fields', $address_fields, $this, $donation_id );
430
431 return charitable_get_location_helper()->get_formatted_address( $address_fields );
432 }
433
434 /**
435 * Return all donations made by donor.
436 *
437 * @since 1.0.0
438 *
439 * @param boolean $distinct_donations If true, will only count unique donations.
440 * @return object[]
441 */
442 public function get_donations( $distinct_donations = false ) {
443 return charitable_get_table( 'campaign_donations' )->get_donations_by_donor( $this->get_donor_id(), $distinct_donations );
444 }
445
446 /**
447 * Return the number of donations made by the donor.
448 *
449 * @since 1.0.0
450 *
451 * @param boolean $distinct_donations If true, will only count unique donations.
452 * @return int
453 */
454 public function count_donations( $distinct_donations = false ) {
455 return charitable_get_table( 'campaign_donations' )->count_donations_by_donor( $this->get_donor_id(), $distinct_donations );
456 }
457
458 /**
459 * Return the number of campaigns that the donor has supported.
460 *
461 * @since 1.0.0
462 *
463 * @return int
464 */
465 public function count_campaigns_supported() {
466 return charitable_get_table( 'campaign_donations' )->count_campaigns_supported_by_donor( $this->get_donor_id() );
467 }
468
469 /**
470 * Return the total amount donated by the donor.
471 *
472 * @since 1.0.0
473 *
474 * @param int $campaign_id Optional. If set, returns total donated to this particular campaign.
475 * @return float
476 */
477 public function get_total_donated( $campaign_id = false ) {
478 $amount = wp_cache_get( $this->get_donor_id(), 'charitable_donor_total_donation_amount_' . $campaign_id );
479
480 if ( false === $amount ) {
481
482 $args = apply_filters( 'charitable_user_total_donated_query_args', array(
483 'output' => 'raw',
484 'donor_id' => $this->get_donor_id(),
485 'distinct_donors' => true,
486 'fields' => 'amount',
487 'campaign' => (int) $campaign_id,
488 ), $this );
489
490 $query = new Charitable_Donor_Query( $args );
491
492 $amount = $query->current()->amount;
493
494 wp_cache_set( $this->get_donor_id(), $amount, 'charitable_donor_total_donation_amount_' . $campaign_id );
495 }
496
497 return (float) $amount;
498 }
499
500 /**
501 * Returns the user's avatar as a fully formatted <img> tag.
502 *
503 * By default, this will return the gravatar, but it can
504 * be extended to add support for locally hosted avatars.
505 *
506 * @since 1.0.0
507 *
508 * @param int $size The length and width of the avatar.
509 * @return string
510 */
511 public function get_avatar( $size = 100 ) {
512 /**If you use this filter, return an attachment ID. */
513 $avatar_attachment_id = apply_filters( 'charitable_user_avatar', false, $this );
514
515 /* If we don't have an attachment ID, display the gravatar. */
516 if ( ! $avatar_attachment_id ) {
517 return get_avatar( $this->ID, $size );
518 }
519
520 $img_size = apply_filters( 'charitable_user_avatar_media_size', array( $size, $size ), $size );
521
522 $attachment_src = wp_get_attachment_image_src( $avatar_attachment_id, $img_size );
523
524 /* No image for the given attachment ID? Fall back to the gravatar. */
525 if ( ! $attachment_src ) {
526 return get_avatar( $this->ID, $size );
527 }
528
529 return apply_filters( 'charitable_user_avatar_custom', sprintf( '<img src="%s" alt="%s" class="avatar photo" width="%s" height="%s" />',
530 $attachment_src[0],
531 esc_attr( $this->display_name ),
532 $attachment_src[1],
533 $attachment_src[2]
534 ), $avatar_attachment_id, $size, $this );
535 }
536
537 /**
538 * Return the src of the avatar.
539 *
540 * @since 1.0.0
541 *
542 * @param int $size The length and the width of the avatar.
543 * @return string
544 */
545 public function get_avatar_src( $size = 100 ) {
546 /* If this returns something, we don't need to deal with the gravatar. */
547 $avatar = apply_filters( 'charitable_user_avatar_src', false, $this, $size );
548
549 if ( false === $avatar ) {
550
551 /* The gravatars are returned as fully formatted img tags, so we need to pull out the src. */
552 $gravatar = get_avatar( $this->ID, $size );
553
554 preg_match( "@src='([^']+)'@" , $gravatar, $matches );
555
556 $avatar = array_pop( $matches );
557 }
558
559 return $avatar;
560 }
561
562 /**
563 * Return the campaigns created by the user.
564 *
565 * @since 1.0.0
566 *
567 * @param array $args Optional. Any arguments accepted by WP_Query.
568 * @return WP_Query
569 */
570 public function get_campaigns( $args = array() ) {
571 $defaults = array(
572 'author' => $this->ID,
573 );
574
575 $args = wp_parse_args( $args, $defaults );
576
577 return Charitable_Campaigns::query( $args );
578 }
579
580 /**
581 * Checks whether the user has any current campaigns (i.e. non-expired).
582 *
583 * @since 1.0.0
584 *
585 * @param array $args Query arguments.
586 * @return WP_Query
587 */
588 public function get_current_campaigns( $args = array() ) {
589 $defaults = array(
590 'author' => $this->ID,
591 'meta_query' => array(
592 'relation' => 'OR',
593 array(
594 'key' => '_campaign_end_date',
595 'value' => date( 'Y-m-d H:i:s' ),
596 'compare' => '>=',
597 'type' => 'datetime',
598 ),
599 array(
600 'key' => '_campaign_end_date',
601 'value' => '0',
602 )
603 ),
604 );
605
606 $args = wp_parse_args( $args, $defaults );
607
608 return Charitable_Campaigns::query( $args );
609 }
610
611 /**
612 * Returns all current campaigns by the user.
613 *
614 * @since 1.0.0
615 *
616 * @return WP_Query
617 */
618 public function has_current_campaigns() {
619 return $this->get_current_campaigns()->found_posts;
620 }
621
622 /**
623 * Returns the user's donation and campaign creation activity.
624 *
625 * @see WP_Query
626 * @since 1.0.0
627 *
628 * @param array $args Optional. Any arguments accepted by WP_Query.
629 * @return WP_Query
630 */
631 public function get_activity( $args = array() ) {
632 $defaults = array(
633 'author' => $this->ID,
634 'post_status' => array( 'charitable-completed', 'charitable-preapproved', 'publish' ),
635 'post_type' => array( 'donation', 'campaign' ),
636 'order' => 'DESC',
637 'orderby' => 'date',
638 );
639
640 $args = wp_parse_args( $args, $defaults );
641
642 $args = apply_filters( 'charitable_user_activity_args', $args, $this );
643
644 return new WP_Query( $args );
645 }
646
647 /**
648 * Add a new donor. This may also create a user account for them.
649 *
650 * @since 1.0.0
651 *
652 * @param array $submitted Values submitted by the user.
653 * @return int $donor_id Donor ID.
654 */
655 public function add_donor( $submitted = array() ) {
656 $email = false;
657
658 if ( isset( $submitted['email'] ) ) {
659 $email = $submitted['email'];
660 }
661
662 if ( ! $email && $this->is_logged_in() ) {
663 $email = $this->user_email;
664 }
665
666 /**
667 * Filter whether donors can be added without an email address.
668 *
669 * Prior to Charitable 1.6, this was never permitted. As of Charitable 1.6, donors
670 * without an email address can be added by default, primarily to support manual
671 * donations without an email address. Use this filter to disable that ability.
672 *
673 * NOTE: By default, the public donation form still requires an email address, so this
674 * primarily affects programmatically created donors, or donors created via manual
675 * donations in the admin.
676 *
677 * @see https://github.com/Charitable/Charitable/issues/535
678 *
679 * @since 1.6.0
680 *
681 * @param boolean $permitted Whether donors can be added without an email address.
682 */
683 if ( ! $email && ! charitable_permit_donor_without_email() ) {
684 charitable_get_deprecated()->doing_it_wrong(
685 __METHOD__,
686 __( 'Unable to add donor. Email not set for logged out user.', 'charitable' ),
687 '1.0.0'
688 );
689
690 return 0;
691 }
692
693 /**
694 * Filter the donor values.
695 *
696 * @since 1.0.0
697 *
698 * @param array $donor_values The donor values.
699 * @param Charitable_User $user This instance of `Charitable_User`.
700 * @param array $submitted Submitted values.
701 */
702 $donor_values = apply_filters( 'charitable_donor_values', array(
703 'user_id' => $this->ID,
704 'email' => $email,
705 'first_name' => array_key_exists( 'first_name', $submitted ) ? $submitted['first_name'] : $this->first_name,
706 'last_name' => array_key_exists( 'last_name', $submitted ) ? $submitted['last_name'] : $this->last_name,
707 ), $this, $submitted );
708
709 $donor_id = charitable_get_table( 'donors' )->insert( $donor_values );
710
711 /**
712 * If the user is logged in, add the "Donor" role to their account.
713 */
714 if ( $this->is_logged_in() ) {
715 $this->add_role( 'donor' );
716 }
717
718 do_action( 'charitable_after_insert_donor', $donor_id, $this );
719
720 return $donor_id;
721 }
722
723 /**
724 * Insert a new donor with submitted values.
725 *
726 * @since 1.4.0
727 *
728 * @param array $submitted The submitted values.
729 * @param array $keys The keys of fields that are to be updated.
730 * @return int
731 */
732 public static function create_profile( $submitted = array(), $keys = array() ) {
733 $user = new Charitable_User();
734 $user_id = $user->update_profile( $submitted, $keys );
735 return new Charitable_User( $user_id );
736 }
737
738 /**
739 * Update the user's details with submitted values.
740 *
741 * @since 1.0.0
742 *
743 * @param array $submitted The submitted values.
744 * @param array $keys The keys of fields that are to be updated.
745 * @return int
746 */
747 public function update_profile( $submitted = array(), $keys = array() ) {
748 if ( empty( $submitted ) ) {
749 $submitted = $_POST;
750 }
751
752 if ( empty( $keys ) ) {
753 $keys = array_keys( $submitted );
754 }
755
756 $user_id = $this->update_core_user( $submitted );
757
758 /* If there were problems with creating the user, stop here. */
759 if ( ! $user_id ) {
760 return $user_id;
761 }
762
763 /* Create or update the user's donor record. */
764 $this->update_donor_record( $submitted, $keys );
765
766 $this->update_user_meta( $submitted, $keys );
767
768 return $user_id;
769 }
770
771 /**
772 * Create or update a donor record for the current user.
773 *
774 * @since 1.6.2
775 *
776 * @param array $submitted The submitted values.
777 * @param array $keys The keys of fields that are to be updated.
778 * @return int The donor ID, or 0 if none was created or edited.
779 */
780 public function update_donor_record( $submitted, $keys ) {
781 $donor_fields = array_intersect( $keys, charitable_get_donor_keys() );
782
783 if ( array_key_exists( 'user_email', $submitted ) ) {
784 $donor_fields[] = 'email';
785 $submitted['email'] = $submitted['user_email'];
786 }
787
788 if ( empty( $donor_fields ) ) {
789 return 0;
790 }
791
792 $donor_data = array(
793 'user_id' => $this->ID,
794 );
795
796 foreach ( $donor_fields as $field ) {
797 if ( array_key_exists( $field, $submitted ) ) {
798 $value = $submitted[ $field ];
799 } elseif ( 'contact_consent' == $field ) {
800 $value = 0;
801 } else {
802 $value = '';
803 }
804
805 $donor_data[ $field ] = $value;
806 }
807
808 if ( array_key_exists( 'donor_id', $donor_data ) ) {
809 $donor_id = $donor_data['donor_id'];
810 } else {
811 $donor_id = $this->get_donor_id();
812 }
813
814 /* Clear out the cache */
815 wp_cache_delete( $donor_id, 'donors' );
816
817 if ( $donor_id ) {
818 charitable_get_table( 'donors' )->update( $donor_id, $donor_data );
819
820 return $donor_id;
821 }
822
823 return charitable_get_table( 'donors' )->insert( $donor_data );
824 }
825
826 /**
827 * Save core fields of the user (i.e. the wp_users data)
828 *
829 * @uses wp_insert_user
830 *
831 * @since 1.0.0
832 *
833 * @param array $submitted Values submitted by the user.
834 * @return int User ID
835 */
836 public function update_core_user( $submitted ) {
837 $core_fields = array_intersect( array_keys( $submitted ), $this->get_core_keys() );
838
839 if ( empty( $core_fields ) ) {
840 return 0;
841 }
842
843 $values = array();
844
845 /* If we're updating an active user, set the ID */
846 if ( 0 !== $this->ID ) {
847 $values['ID'] = $this->ID;
848 }
849
850 foreach ( $core_fields as $field ) {
851 $values[ $field ] = $submitted[ $field ];
852 }
853
854 /* Set the user's display name based on their name. */
855 $display_name = $this->sanitize_display_name( $values );
856
857 if ( $display_name ) {
858 $values['display_name'] = $display_name;
859 }
860
861 /* Insert the user */
862 if ( 0 == $this->ID ) {
863
864 if ( ! isset( $values['user_pass'] ) || strlen( $values['user_pass'] ) == 0 ) {
865 charitable_get_notices()->add_error( '<strong>ERROR:</strong> Password field is required.' );
866 return false;
867 }
868
869 if ( ! isset( $values['user_login'] ) ) {
870 $values['user_login'] = $values['user_email'];
871 }
872
873 /**
874 * `wp_insert_user` calls `sanitize_user` internally - make the
875 * same call here so `$values['user_login']` matches what is
876 * eventually saved to the database
877 */
878 $values['user_login'] = sanitize_user( $values['user_login'], true );
879
880 $user_id = wp_insert_user( $values );
881
882 if ( is_wp_error( $user_id ) ) {
883 charitable_get_notices()->add_errors_from_wp_error( $user_id );
884 return false;
885 }
886
887 $this->init( self::get_data_by( 'id', $user_id ) );
888
889 $signon = Charitable_User::signon( $values['user_login'], $values['user_pass'] );
890
891 if ( is_wp_error( $signon ) ) {
892 charitable_get_notices()->add_errors_from_wp_error( $signon );
893 return false;
894 }
895
896 do_action( 'charitable_after_insert_user', $user_id, $values );
897
898 } else {
899
900 $values['ID'] = $this->ID;
901
902 $user_id = wp_update_user( $values );
903
904 }//end if
905
906 /* If there was an error when inserting or updating the user, lodge the error. */
907 if ( is_wp_error( $user_id ) ) {
908
909 charitable_get_notices()->add_errors_from_wp_error( $user_id );
910 return false;
911
912 }
913
914 do_action( 'charitable_after_save_user', $user_id, $values );
915
916 return $user_id;
917 }
918
919 /**
920 * Save the user's meta fields.
921 *
922 * @since 1.0.0
923 *
924 * @param array $submitted The submitted values.
925 * @param array $keys The keys of fields that are to be updated.
926 * @return int Number of fields updated.
927 */
928 public function update_user_meta( $submitted, $keys ) {
929 /* Exclude the core keys */
930 $meta_fields = array_diff( $keys, $this->get_core_keys() );
931 $updated = 0;
932
933 foreach ( $meta_fields as $field ) {
934
935 if ( isset( $submitted[ $field ] ) ) {
936 $meta_key = $this->map_key( $field );
937 $meta_value = sanitize_meta( $meta_key, $submitted[ $field ], 'user' );
938
939 update_user_meta( $this->ID, $meta_key, $meta_value );
940
941 $updated++;
942 }
943 }
944
945 return $updated;
946 }
947
948 /**
949 * Log a user is with their username and password.
950 *
951 * @since 1.0.0
952 *
953 * @param string $username The user's username.
954 * @param string $password User password.
955 * @return WP_User|WP_Error|false WP_User on login, WP_Error on failure. False if feature is disabled.
956 */
957 public static function signon( $username, $password ) {
958 if ( ! apply_filters( 'charitable_auto_login_after_registration', true, $username ) ) {
959 return false;
960 }
961
962 if ( is_user_logged_in() ) {
963 return false;
964 }
965
966 $creds = array(
967 'user_login' => $username,
968 'user_password' => $password,
969 'remember' => true,
970 );
971
972 return wp_signon( $creds, false );
973 }
974
975 /**
976 * Return a display name for the user.
977 *
978 * @since 1.5.2
979 *
980 * @param array $values Submitted values.
981 * @return string|false String if we received a display_name
982 * or had a first name or last name.
983 */
984 public function sanitize_display_name( $values ) {
985 if ( array_key_exists( 'display_name', $values ) ) {
986 return $values['display_name'];
987 }
988
989 $first_name = array_key_exists( 'first_name', $values ) ? $values['first_name'] : $this->first_name;
990 $last_name = array_key_exists( 'last_name', $values ) ? $values['last_name'] : $this->last_name;
991 $display = trim( sprintf( '%s %s', $first_name, $last_name ) );
992
993 return strlen( $display ) ? $display : false;
994 }
995
996 /**
997 * Return the array of mapped keys, where the key is mapped to a meta_key in the user meta table.
998 *
999 * @since 1.0.0
1000 *
1001 * @return array
1002 */
1003 public function get_mapped_keys() {
1004 if ( ! isset( $this->mapped_keys ) ) {
1005 $this->mapped_keys = charitable_get_user_mapped_keys();
1006 }
1007
1008 return $this->mapped_keys;
1009 }
1010
1011 /**
1012 * Given a key, returns the mapped key or itself if it is not mapped.
1013 *
1014 * @since 1.5.0
1015 *
1016 * @param string $key The key to map.
1017 * @return string
1018 */
1019 public function map_key( $key ) {
1020 $mapped_keys = $this->get_mapped_keys();
1021
1022 return array_key_exists( $key, $mapped_keys ) ? $mapped_keys[ $key ] : $key;
1023 }
1024
1025 /**
1026 * Return the array of core keys.
1027 *
1028 * @since 1.0.0
1029 *
1030 * @return array
1031 */
1032 public function get_core_keys() {
1033 if ( ! isset( $this->core_keys ) ) {
1034 $this->core_keys = charitable_get_user_core_keys();
1035 }
1036
1037 return $this->core_keys;
1038 }
1039 }
1040
1041 endif;
1042