Skip to:
Content

BuddyPress.org

Ticket #7597: bp-members-functions.php

File bp-members-functions.php, 84.2 KB (added by antonioeatgoat, 9 years ago)
Line 
1<?php
2/**
3 * BuddyPress Member Functions.
4 *
5 * Functions specific to the members component.
6 *
7 * @package BuddyPress
8 * @subpackage MembersFunctions
9 * @since 1.5.0
10 */
11
12// Exit if accessed directly.
13defined( 'ABSPATH' ) || exit;
14
15/**
16 * Check for the existence of a Members directory page.
17 *
18 * @since 1.5.0
19 *
20 * @return bool True if found, otherwise false.
21 */
22function bp_members_has_directory() {
23 $bp = buddypress();
24
25 return (bool) !empty( $bp->pages->members->id );
26}
27
28/**
29 * Define the slug constants for the Members component.
30 *
31 * Handles the three slug constants used in the Members component -
32 * BP_MEMBERS_SLUG, BP_REGISTER_SLUG, and BP_ACTIVATION_SLUG. If these
33 * constants are not overridden in wp-config.php or bp-custom.php, they are
34 * defined here to match the slug of the corresponding WP pages.
35 *
36 * In general, fallback values are only used during initial BP page creation,
37 * when no slugs have been explicitly defined.
38 *
39 * @since 1.5.0
40 */
41function bp_core_define_slugs() {
42 $bp = buddypress();
43
44 // No custom members slug.
45 if ( !defined( 'BP_MEMBERS_SLUG' ) ) {
46 if ( !empty( $bp->pages->members ) ) {
47 define( 'BP_MEMBERS_SLUG', $bp->pages->members->slug );
48 } else {
49 define( 'BP_MEMBERS_SLUG', 'members' );
50 }
51 }
52
53 // No custom registration slug.
54 if ( !defined( 'BP_REGISTER_SLUG' ) ) {
55 if ( !empty( $bp->pages->register ) ) {
56 define( 'BP_REGISTER_SLUG', $bp->pages->register->slug );
57 } else {
58 define( 'BP_REGISTER_SLUG', 'register' );
59 }
60 }
61
62 // No custom activation slug.
63 if ( !defined( 'BP_ACTIVATION_SLUG' ) ) {
64 if ( !empty( $bp->pages->activate ) ) {
65 define( 'BP_ACTIVATION_SLUG', $bp->pages->activate->slug );
66 } else {
67 define( 'BP_ACTIVATION_SLUG', 'activate' );
68 }
69 }
70}
71add_action( 'bp_setup_globals', 'bp_core_define_slugs', 11 );
72
73/**
74 * Fetch an array of users based on the parameters passed.
75 *
76 * Since BuddyPress 1.7, bp_core_get_users() uses BP_User_Query. If you
77 * need backward compatibility with BP_Core_User::get_users(), filter the
78 * bp_use_legacy_user_query value, returning true.
79 *
80 * @since 1.2.0
81 *
82 * @param array|string $args {
83 * Array of arguments. All are optional. See {@link BP_User_Query} for
84 * a more complete description of arguments.
85 * @type string $type Sort order. Default: 'active'.
86 * @type int $user_id Limit results to friends of a user. Default: false.
87 * @type mixed $exclude IDs to exclude from results. Default: false.
88 * @type string $search_terms Limit to users matching search terms. Default: false.
89 * @type string $meta_key Limit to users with a meta_key. Default: false.
90 * @type string $meta_value Limit to users with a meta_value (with meta_key). Default: false.
91 * @type array|string $member_type Array or comma-separated string of member types.
92 * @type array|string $member_type__in Array or comma-separated string of member types.
93 * `$member_type` takes precedence over this parameter.
94 * @type array|string $member_type__not_in Array or comma-separated string of member types to be excluded.
95 * @type mixed $include Limit results by user IDs. Default: false.
96 * @type int $per_page Results per page. Default: 20.
97 * @type int $page Page of results. Default: 1.
98 * @type bool $populate_extras Fetch optional extras. Default: true.
99 * @type string|bool $count_total How to do total user count. Default: 'count_query'.
100 * }
101 * @return array
102 */
103function bp_core_get_users( $args = '' ) {
104
105 // Parse the user query arguments.
106 $r = bp_parse_args( $args, array(
107 'type' => 'active', // Active, newest, alphabetical, random or popular.
108 'user_id' => false, // Pass a user_id to limit to only friend connections for this user.
109 'exclude' => false, // Users to exclude from results.
110 'search_terms' => false, // Limit to users that match these search terms.
111 'meta_key' => false, // Limit to users who have this piece of usermeta.
112 'meta_value' => false, // With meta_key, limit to users where usermeta matches this value.
113 'member_type' => '',
114 'member_type__in' => '',
115 'member_type__not_in' => '',
116 'include' => false, // Pass comma separated list of user_ids to limit to only these users.
117 'per_page' => 20, // The number of results to return per page.
118 'page' => 1, // The page to return if limiting per page.
119 'populate_extras' => true, // Fetch the last active, where the user is a friend, total friend count, latest update.
120 'count_total' => 'count_query' // What kind of total user count to do, if any. 'count_query', 'sql_calc_found_rows', or false.
121 ), 'core_get_users' );
122
123 // For legacy users. Use of BP_Core_User::get_users() is deprecated.
124 if ( apply_filters( 'bp_use_legacy_user_query', false, __FUNCTION__, $r ) ) {
125 $retval = BP_Core_User::get_users(
126 $r['type'],
127 $r['per_page'],
128 $r['page'],
129 $r['user_id'],
130 $r['include'],
131 $r['search_terms'],
132 $r['populate_extras'],
133 $r['exclude'],
134 $r['meta_key'],
135 $r['meta_value']
136 );
137
138 // Default behavior as of BuddyPress 1.7.0.
139 } else {
140
141 // Get users like we were asked to do...
142 $users = new BP_User_Query( $r );
143
144 // ...but reformat the results to match bp_core_get_users() behavior.
145 $retval = array(
146 'users' => array_values( $users->results ),
147 'total' => $users->total_users
148 );
149 }
150
151 /**
152 * Filters the results of the user query.
153 *
154 * @since 1.2.0
155 *
156 * @param array $retval Array of users for the current query.
157 * @param array $r Array of parsed query arguments.
158 */
159 return apply_filters( 'bp_core_get_users', $retval, $r );
160}
161
162/**
163 * Return the domain for the passed user: e.g. http://example.com/members/andy/.
164 *
165 * @since 1.0.0
166 *
167 * @param int $user_id The ID of the user.
168 * @param string|bool $user_nicename Optional. user_nicename of the user.
169 * @param string|bool $user_login Optional. user_login of the user.
170 * @return string
171 */
172function bp_core_get_user_domain( $user_id = 0, $user_nicename = false, $user_login = false ) {
173
174 if ( empty( $user_id ) ) {
175 return;
176 }
177
178 $username = bp_core_get_username( $user_id, $user_nicename, $user_login );
179
180 if ( bp_is_username_compatibility_mode() ) {
181 $username = rawurlencode( $username );
182 }
183
184 $after_domain = bp_core_enable_root_profiles() ? $username : bp_get_members_root_slug() . '/' . $username;
185 $domain = trailingslashit( bp_get_root_domain() . '/' . $after_domain );
186
187 // Don't use this filter. Subject to removal in a future release.
188 // Use the 'bp_core_get_user_domain' filter instead.
189 $domain = apply_filters( 'bp_core_get_user_domain_pre_cache', $domain, $user_id, $user_nicename, $user_login );
190
191 /**
192 * Filters the domain for the passed user.
193 *
194 * @since 1.0.1
195 *
196 * @param string $domain Domain for the passed user.
197 * @param int $user_id ID of the passed user.
198 * @param string $user_nicename User nicename of the passed user.
199 * @param string $user_login User login of the passed user.
200 */
201 return apply_filters( 'bp_core_get_user_domain', $domain, $user_id, $user_nicename, $user_login );
202}
203
204/**
205 * Fetch everything in the wp_users table for a user, without any usermeta.
206 *
207 * @since 1.2.0
208 *
209 * @param int $user_id The ID of the user.
210 * @return array|bool Array of data on success, boolean false on failure.
211 */
212function bp_core_get_core_userdata( $user_id = 0 ) {
213 if ( empty( $user_id ) ) {
214 return false;
215 }
216
217 $userdata = wp_cache_get( 'bp_core_userdata_' . $user_id, 'bp' );
218
219 // No cache.
220 if ( false === $userdata ) {
221 $userdata = BP_Core_User::get_core_userdata( $user_id );
222
223 // Cache data; no-result is cached as integer 0.
224 wp_cache_set( 'bp_core_userdata_' . $user_id, false === $userdata ? 0 : $userdata, 'bp' );
225
226 // Cached no-result, so set return value as false as expected.
227 } elseif ( 0 === $userdata ) {
228 $userdata = false;
229 }
230
231 /**
232 * Filters the userdata for a passed user.
233 *
234 * @since 1.2.0
235 *
236 * @param array|bool $userdata Array of user data for a passed user on success, boolean false on failure.
237 */
238 return apply_filters( 'bp_core_get_core_userdata', $userdata );
239}
240
241/**
242 * Return the ID of a user, based on user_login.
243 *
244 * No longer used.
245 *
246 * @todo Deprecate.
247 *
248 * @param string $user_login user_login of the user being queried.
249 * @return int
250 */
251function bp_core_get_displayed_userid( $user_login ) {
252 return apply_filters( 'bp_core_get_displayed_userid', bp_core_get_userid( $user_login ) );
253}
254
255/**
256 * Return the user ID based on a user's user_login.
257 *
258 * @since 1.0.0
259 *
260 * @param string $username user_login to check.
261 * @return int|null The ID of the matched user on success, null on failure.
262 */
263function bp_core_get_userid( $username = '' ) {
264 if ( empty( $username ) ) {
265 return false;
266 }
267
268 $user = get_user_by( 'login', $username );
269
270 /**
271 * Filters the ID of a user, based on user_login.
272 *
273 * @since 1.0.1
274 *
275 * @param int|null $value ID of the user or null.
276 * @param string $username User login to check.
277 */
278 return apply_filters( 'bp_core_get_userid', ! empty( $user->ID ) ? $user->ID : NULL, $username );
279}
280
281/**
282 * Return the user ID based on a user's user_nicename.
283 *
284 * @since 1.2.3
285 *
286 * @param string $user_nicename user_nicename to check.
287 * @return int|null The ID of the matched user on success, null on failure.
288 */
289function bp_core_get_userid_from_nicename( $user_nicename = '' ) {
290 if ( empty( $user_nicename ) ) {
291 return false;
292 }
293
294 $user = get_user_by( 'slug', $user_nicename );
295
296 /**
297 * Filters the user ID based on user_nicename.
298 *
299 * @since 1.2.3
300 *
301 * @param int|null $value ID of the user or null.
302 * @param string $user_nicename User nicename to check.
303 */
304 return apply_filters( 'bp_core_get_userid_from_nicename', ! empty( $user->ID ) ? $user->ID : NULL, $user_nicename );
305}
306
307/**
308 * Return the username for a user based on their user id.
309 *
310 * This function is sensitive to the BP_ENABLE_USERNAME_COMPATIBILITY_MODE,
311 * so it will return the user_login or user_nicename as appropriate.
312 *
313 * @since 1.0.0
314 *
315 * @param int $user_id User ID to check.
316 * @param string|bool $user_nicename Optional. user_nicename of user being checked.
317 * @param string|bool $user_login Optional. user_login of user being checked.
318 * @return string|bool The username of the matched user, or false.
319 */
320function bp_core_get_username( $user_id = 0, $user_nicename = false, $user_login = false ) {
321 $bp = buddypress();
322
323 // Check cache for user nicename.
324 $username = wp_cache_get( 'bp_user_username_' . $user_id, 'bp' );
325 if ( false === $username ) {
326
327 // Cache not found so prepare to update it.
328 $update_cache = true;
329
330 // Nicename and login were not passed.
331 if ( empty( $user_nicename ) && empty( $user_login ) ) {
332
333 // User ID matches logged in user.
334 if ( bp_loggedin_user_id() == $user_id ) {
335 $userdata = &$bp->loggedin_user->userdata;
336
337 // User ID matches displayed in user.
338 } elseif ( bp_displayed_user_id() == $user_id ) {
339 $userdata = &$bp->displayed_user->userdata;
340
341 // No user ID match.
342 } else {
343 $userdata = false;
344 }
345
346 // No match so go dig.
347 if ( empty( $userdata ) ) {
348
349 // User not found so return false.
350 if ( !$userdata = bp_core_get_core_userdata( $user_id ) ) {
351 return false;
352 }
353 }
354
355 // Update the $user_id for later.
356 $user_id = $userdata->ID;
357
358 // Two possible options.
359 $user_nicename = $userdata->user_nicename;
360 $user_login = $userdata->user_login;
361 }
362
363 // Pull an audible and maybe use the login over the nicename.
364 $username = bp_is_username_compatibility_mode() ? $user_login : $user_nicename;
365
366 // Username found in cache so don't update it again.
367 } else {
368 $update_cache = false;
369 }
370
371 // Add this to cache.
372 if ( ( true === $update_cache ) && !empty( $username ) ) {
373 wp_cache_set( 'bp_user_username_' . $user_id, $username, 'bp' );
374
375 // @todo bust this cache if no $username found?
376 // } else {
377 // wp_cache_delete( 'bp_user_username_' . $user_id );
378 }
379
380 /**
381 * Filters the username based on originally provided user ID.
382 *
383 * @since 1.0.1
384 *
385 * @param string $username Username determined by user ID.
386 */
387 return apply_filters( 'bp_core_get_username', $username );
388}
389
390/**
391 * Return the user_nicename for a user based on their user_id.
392 *
393 * This should be used for linking to user profiles and anywhere else a
394 * sanitized and unique slug to a user is needed.
395 *
396 * @since 1.5.0
397 *
398 * @todo Refactor to use a WP core function, if possible.
399 *
400 * @param int $user_id User ID to check.
401 * @return string|bool The username of the matched user, or false.
402 */
403function bp_members_get_user_nicename( $user_id ) {
404 $bp = buddypress();
405
406 if ( !$user_nicename = wp_cache_get( 'bp_members_user_nicename_' . $user_id, 'bp' ) ) {
407 $update_cache = true;
408
409 // User ID matches logged in user.
410 if ( bp_loggedin_user_id() == $user_id ) {
411 $userdata = &$bp->loggedin_user->userdata;
412
413 // User ID matches displayed in user.
414 } elseif ( bp_displayed_user_id() == $user_id ) {
415 $userdata = &$bp->displayed_user->userdata;
416
417 // No user ID match.
418 } else {
419 $userdata = false;
420 }
421
422 // No match so go dig.
423 if ( empty( $userdata ) ) {
424
425 // User not found so return false.
426 if ( !$userdata = bp_core_get_core_userdata( $user_id ) ) {
427 return false;
428 }
429 }
430
431 // User nicename found.
432 $user_nicename = $userdata->user_nicename;
433
434 // Nicename found in cache so don't update it again.
435 } else {
436 $update_cache = false;
437 }
438
439 // Add this to cache.
440 if ( true == $update_cache && !empty( $user_nicename ) ) {
441 wp_cache_set( 'bp_members_user_nicename_' . $user_id, $user_nicename, 'bp' );
442 }
443
444 /**
445 * Filters the user_nicename based on originally provided user ID.
446 *
447 * @since 1.5.0
448 *
449 * @param string $username User nice name determined by user ID.
450 */
451 return apply_filters( 'bp_members_get_user_nicename', $user_nicename );
452}
453
454/**
455 * Return the email address for the user based on user ID.
456 *
457 * @since 1.0.0
458 *
459 * @param int $uid User ID to check.
460 * @return string The email for the matched user. Empty string if no user
461 * matched the $uid.
462 */
463function bp_core_get_user_email( $uid ) {
464
465 if ( !$email = wp_cache_get( 'bp_user_email_' . $uid, 'bp' ) ) {
466
467 // User exists.
468 $ud = bp_core_get_core_userdata( $uid );
469 if ( ! empty( $ud ) ) {
470 $email = $ud->user_email;
471
472 // User was deleted.
473 } else {
474 $email = '';
475 }
476
477 wp_cache_set( 'bp_user_email_' . $uid, $email, 'bp' );
478 }
479
480 /**
481 * Filters the user email for user based on user ID.
482 *
483 * @since 1.0.1
484 *
485 * @param string $email Email determined for the user.
486 */
487 return apply_filters( 'bp_core_get_user_email', $email );
488}
489
490/**
491 * Return a HTML formatted link for a user with the user's full name as the link text.
492 *
493 * Eg: <a href="http://andy.example.com/">Andy Peatling</a>
494 *
495 * Optional parameters will return just the name or just the URL.
496 *
497 * @since 1.0.0
498 *
499 * @param int $user_id User ID to check.
500 * @param bool $no_anchor Disable URL and HTML and just return full name.
501 * Default: false.
502 * @param bool $just_link Disable full name and HTML and just return the URL
503 * text. Default false.
504 * @return string|bool The link text based on passed parameters, or false on
505 * no match.
506 */
507function bp_core_get_userlink( $user_id, $no_anchor = false, $just_link = false ) {
508 $display_name = bp_core_get_user_displayname( $user_id );
509
510 if ( empty( $display_name ) ) {
511 return false;
512 }
513
514 if ( ! empty( $no_anchor ) ) {
515 return $display_name;
516 }
517
518 if ( !$url = bp_core_get_user_domain( $user_id ) ) {
519 return false;
520 }
521
522 if ( ! empty( $just_link ) ) {
523 return $url;
524 }
525
526 /**
527 * Filters the link text for the passed in user.
528 *
529 * @since 1.2.0
530 *
531 * @param string $value Link text based on passed parameters.
532 * @param int $user_id ID of the user to check.
533 */
534 return apply_filters( 'bp_core_get_userlink', '<a href="' . $url . '">' . $display_name . '</a>', $user_id );
535}
536
537/**
538 * Fetch the display name for a group of users.
539 *
540 * Uses the 'Name' field in xprofile if available. Falls back on WP
541 * display_name, and then user_nicename.
542 *
543 * @since 2.0.0
544 *
545 * @param array $user_ids Array of user IDs to get display names for.
546 * @return array
547 */
548function bp_core_get_user_displaynames( $user_ids ) {
549
550 // Sanitize.
551 $user_ids = wp_parse_id_list( $user_ids );
552
553 // Remove dupes and empties.
554 $user_ids = array_unique( array_filter( $user_ids ) );
555
556 if ( empty( $user_ids ) ) {
557 return array();
558 }
559
560 $uncached_ids = array();
561 foreach ( $user_ids as $user_id ) {
562 if ( false === wp_cache_get( 'bp_user_fullname_' . $user_id, 'bp' ) ) {
563 $uncached_ids[] = $user_id;
564 }
565 }
566
567 // Prime caches.
568 if ( ! empty( $uncached_ids ) ) {
569 if ( bp_is_active( 'xprofile' ) ) {
570 $fullname_data = BP_XProfile_ProfileData::get_value_byid( 1, $uncached_ids );
571
572 // Key by user_id.
573 $fullnames = array();
574 foreach ( $fullname_data as $fd ) {
575 if ( ! empty( $fd->value ) ) {
576 $fullnames[ intval( $fd->user_id ) ] = $fd->value;
577 }
578 }
579
580 // If xprofiledata is not found for any users, we'll look
581 // them up separately.
582 $no_xprofile_ids = array_diff( $uncached_ids, array_keys( $fullnames ) );
583 } else {
584 $fullnames = array();
585 $no_xprofile_ids = $user_ids;
586 }
587
588 if ( ! empty( $no_xprofile_ids ) ) {
589 // Use WP_User_Query because we don't need BP information.
590 $query = new WP_User_Query( array(
591 'include' => $no_xprofile_ids,
592 'fields' => array( 'ID', 'user_nicename', 'display_name', ),
593 'count_total' => false,
594 'blog_id' => 0,
595 ) );
596
597 foreach ( $query->results as $qr ) {
598 $fullnames[ $qr->ID ] = ! empty( $qr->display_name ) ? $qr->display_name : $qr->user_nicename;
599
600 // If xprofile is active, set this value as the
601 // xprofile display name as well.
602 if ( bp_is_active( 'xprofile' ) ) {
603 xprofile_set_field_data( 1, $qr->ID, $fullnames[ $qr->ID ] );
604 }
605 }
606 }
607
608 foreach ( $fullnames as $fuser_id => $fname ) {
609 wp_cache_set( 'bp_user_fullname_' . $fuser_id, $fname, 'bp' );
610 }
611 }
612
613 $retval = array();
614 foreach ( $user_ids as $user_id ) {
615 $retval[ $user_id ] = wp_cache_get( 'bp_user_fullname_' . $user_id, 'bp' );
616 }
617
618 return $retval;
619}
620
621/**
622 * Fetch the display name for a user.
623 *
624 * @since 1.0.1
625 *
626 * @param int|string|bool $user_id_or_username User ID or username.
627 * @return string|bool The display name for the user in question, or false if
628 * user not found.
629 */
630function bp_core_get_user_displayname( $user_id_or_username ) {
631 if ( empty( $user_id_or_username ) ) {
632 return false;
633 }
634
635 if ( ! is_numeric( $user_id_or_username ) ) {
636 $user_id = bp_core_get_userid( $user_id_or_username );
637 } else {
638 $user_id = $user_id_or_username;
639 }
640
641 if ( empty( $user_id ) ) {
642 return false;
643 }
644
645 $display_names = bp_core_get_user_displaynames( array( $user_id ) );
646
647 if ( ! isset( $display_names[ $user_id ] ) ) {
648 $fullname = false;
649 } else {
650 $fullname = $display_names[ $user_id ];
651 }
652
653 /**
654 * Filters the display name for the passed in user.
655 *
656 * @since 1.0.1
657 *
658 * @param string $fullname Display name for the user.
659 * @param int $user_id ID of the user to check.
660 */
661 return apply_filters( 'bp_core_get_user_displayname', $fullname, $user_id );
662}
663add_filter( 'bp_core_get_user_displayname', 'strip_tags', 1 );
664add_filter( 'bp_core_get_user_displayname', 'trim' );
665add_filter( 'bp_core_get_user_displayname', 'stripslashes' );
666add_filter( 'bp_core_get_user_displayname', 'esc_html' );
667
668/**
669 * Return the user link for the user based on user email address.
670 *
671 * @since 1.0.0
672 *
673 * @param string $email The email address for the user.
674 * @return string The link to the users home base. False on no match.
675 */
676function bp_core_get_userlink_by_email( $email ) {
677 $user = get_user_by( 'email', $email );
678
679 /**
680 * Filters the user link for the user based on user email address.
681 *
682 * @since 1.0.1
683 *
684 * @param string|bool $value URL for the user if found, otherwise false.
685 */
686 return apply_filters( 'bp_core_get_userlink_by_email', bp_core_get_userlink( $user->ID, false, false, true ) );
687}
688
689/**
690 * Return the user link for the user based on the supplied identifier.
691 *
692 * @since 1.0.0
693 *
694 * @param string $username If BP_ENABLE_USERNAME_COMPATIBILITY_MODE is set,
695 * this should be user_login, otherwise it should
696 * be user_nicename.
697 * @return string|bool The link to the user's domain, false on no match.
698 */
699function bp_core_get_userlink_by_username( $username ) {
700 if ( bp_is_username_compatibility_mode() ) {
701 $user_id = bp_core_get_userid( $username );
702 } else {
703 $user_id = bp_core_get_userid_from_nicename( $username );
704 }
705
706 /**
707 * Filters the user link for the user based on username.
708 *
709 * @since 1.0.1
710 *
711 * @param string|bool $value URL for the user if found, otherwise false.
712 */
713 return apply_filters( 'bp_core_get_userlink_by_username', bp_core_get_userlink( $user_id, false, false, true ) );
714}
715
716/**
717 * Return the total number of members for the installation.
718 *
719 * Note that this is a raw count of non-spam, activated users. It does not
720 * account for users who have logged activity (last_active). See
721 * {@link bp_core_get_active_member_count()}.
722 *
723 * @since 1.2.0
724 *
725 * @return int The total number of members.
726 */
727function bp_core_get_total_member_count() {
728 global $wpdb;
729
730 $count = wp_cache_get( 'bp_total_member_count', 'bp' );
731
732 if ( false === $count ) {
733 $status_sql = bp_core_get_status_sql();
734 $count = $wpdb->get_var( "SELECT COUNT(ID) FROM {$wpdb->users} WHERE {$status_sql}" );
735 wp_cache_set( 'bp_total_member_count', $count, 'bp' );
736 }
737
738 /**
739 * Filters the total number of members for the installation.
740 *
741 * @since 1.2.0
742 *
743 * @param int $count Total number of members.
744 */
745 return apply_filters( 'bp_core_get_total_member_count', $count );
746}
747
748/**
749 * Return the total number of members, limited to those members with last_activity.
750 *
751 * @since 1.6.0
752 *
753 * @return int The number of active members.
754 */
755function bp_core_get_active_member_count() {
756 global $wpdb;
757
758 $count = get_transient( 'bp_active_member_count' );
759 if ( false === $count ) {
760 $bp = buddypress();
761
762 // Avoid a costly join by splitting the lookup.
763 if ( is_multisite() ) {
764 $sql = "SELECT ID FROM {$wpdb->users} WHERE (user_status != 0 OR deleted != 0 OR user_status != 0)";
765 } else {
766 $sql = "SELECT ID FROM {$wpdb->users} WHERE user_status != 0";
767 }
768
769 $exclude_users = $wpdb->get_col( $sql );
770 $exclude_users_sql = !empty( $exclude_users ) ? "AND user_id NOT IN (" . implode( ',', wp_parse_id_list( $exclude_users ) ) . ")" : '';
771 $count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(user_id) FROM {$bp->members->table_name_last_activity} WHERE component = %s AND type = 'last_activity' {$exclude_users_sql}", $bp->members->id ) );
772
773 set_transient( 'bp_active_member_count', $count );
774 }
775
776 /**
777 * Filters the total number of members for the installation limited to those with last_activity.
778 *
779 * @since 1.6.0
780 *
781 * @param int $count Total number of active members.
782 */
783 return apply_filters( 'bp_core_get_active_member_count', $count );
784}
785
786/**
787 * Process a spammed or unspammed user.
788 *
789 * This function is called from three places:
790 *
791 * - in bp_settings_action_capabilities() (from the front-end)
792 * - by bp_core_mark_user_spam_admin() (from wp-admin)
793 * - bp_core_mark_user_ham_admin() (from wp-admin)
794 *
795 * @since 1.6.0
796 *
797 * @param int $user_id The ID of the user being spammed/hammed.
798 * @param string $status 'spam' if being marked as spam, 'ham' otherwise.
799 * @param bool $do_wp_cleanup True to force the cleanup of WordPress content
800 * and status, otherwise false. Generally, this should
801 * only be false if WordPress is expected to have
802 * performed this cleanup independently, as when hooked
803 * to 'make_spam_user'.
804 * @return bool True on success, false on failure.
805 */
806function bp_core_process_spammer_status( $user_id, $status, $do_wp_cleanup = true ) {
807 global $wpdb;
808
809 // Bail if no user ID.
810 if ( empty( $user_id ) ) {
811 return;
812 }
813
814 // Bail if user ID is super admin.
815 if ( is_super_admin( $user_id ) ) {
816 return;
817 }
818
819 // Get the functions file.
820 if ( is_multisite() ) {
821 require_once( ABSPATH . 'wp-admin/includes/ms.php' );
822 }
823
824 $is_spam = ( 'spam' == $status );
825
826 // Only you can prevent infinite loops.
827 remove_action( 'make_spam_user', 'bp_core_mark_user_spam_admin' );
828 remove_action( 'make_ham_user', 'bp_core_mark_user_ham_admin' );
829
830 // Force the cleanup of WordPress content and status for multisite configs.
831 if ( $do_wp_cleanup ) {
832
833 // Get the blogs for the user.
834 $blogs = get_blogs_of_user( $user_id, true );
835
836 foreach ( (array) array_values( $blogs ) as $details ) {
837
838 // Do not mark the main or current root blog as spam.
839 if ( 1 == $details->userblog_id || bp_get_root_blog_id() == $details->userblog_id ) {
840 continue;
841 }
842
843 // Update the blog status.
844 update_blog_status( $details->userblog_id, 'spam', $is_spam );
845 }
846
847 // Finally, mark this user as a spammer.
848 if ( is_multisite() ) {
849 update_user_status( $user_id, 'spam', $is_spam );
850 }
851 }
852
853 // Update the user status.
854 $wpdb->update( $wpdb->users, array( 'user_status' => $is_spam ), array( 'ID' => $user_id ) );
855
856 // Clean user cache.
857 clean_user_cache( $user_id );
858
859 if ( ! is_multisite() ) {
860 // Call multisite actions in single site mode for good measure.
861 if ( true === $is_spam ) {
862
863 /**
864 * Fires at end of processing spammer in Dashboard if not multisite and user is spam.
865 *
866 * @since 1.5.0
867 *
868 * @param int $value user ID.
869 */
870 do_action( 'make_spam_user', $user_id );
871 } else {
872
873 /**
874 * Fires at end of processing spammer in Dashboard if not multisite and user is not spam.
875 *
876 * @since 1.5.0
877 *
878 * @param int $value user ID.
879 */
880 do_action( 'make_ham_user', $user_id );
881 }
882 }
883
884 // Hide this user's activity.
885 if ( ( true === $is_spam ) && bp_is_active( 'activity' ) ) {
886 bp_activity_hide_user_activity( $user_id );
887 }
888
889 // We need a special hook for is_spam so that components can delete data at spam time.
890 if ( true === $is_spam ) {
891
892 /**
893 * Fires at the end of the process spammer process if the user is spam.
894 *
895 * @since 1.5.0
896 *
897 * @param int $value Displayed user ID.
898 */
899 do_action( 'bp_make_spam_user', $user_id );
900 } else {
901
902 /**
903 * Fires at the end of the process spammer process if the user is not spam.
904 *
905 * @since 1.5.0
906 *
907 * @param int $value Displayed user ID.
908 */
909 do_action( 'bp_make_ham_user', $user_id );
910 }
911
912 /**
913 * Fires at the end of the process for hanlding spammer status.
914 *
915 * @since 1.5.5
916 *
917 * @param int $user_id ID of the processed user.
918 * @param bool $is_spam The determined spam status of processed user.
919 */
920 do_action( 'bp_core_process_spammer_status', $user_id, $is_spam );
921
922 // Put things back how we found them.
923 add_action( 'make_spam_user', 'bp_core_mark_user_spam_admin' );
924 add_action( 'make_ham_user', 'bp_core_mark_user_ham_admin' );
925
926 return true;
927}
928/**
929 * Hook to WP's make_spam_user and run our custom BP spam functions.
930 *
931 * @since 1.6.0
932 *
933 * @param int $user_id The user ID passed from the make_spam_user hook.
934 */
935function bp_core_mark_user_spam_admin( $user_id ) {
936 bp_core_process_spammer_status( $user_id, 'spam', false );
937}
938add_action( 'make_spam_user', 'bp_core_mark_user_spam_admin' );
939
940/**
941 * Hook to WP's make_ham_user and run our custom BP spam functions.
942 *
943 * @since 1.6.0
944 *
945 * @param int $user_id The user ID passed from the make_ham_user hook.
946 */
947function bp_core_mark_user_ham_admin( $user_id ) {
948 bp_core_process_spammer_status( $user_id, 'ham', false );
949}
950add_action( 'make_ham_user', 'bp_core_mark_user_ham_admin' );
951
952/**
953 * Check whether a user has been marked as a spammer.
954 *
955 * @since 1.6.0
956 *
957 * @param int $user_id The ID for the user.
958 * @return bool True if spammer, otherwise false.
959 */
960function bp_is_user_spammer( $user_id = 0 ) {
961
962 // No user to check.
963 if ( empty( $user_id ) ) {
964 return false;
965 }
966
967 $bp = buddypress();
968
969 // Assume user is not spam.
970 $is_spammer = false;
971
972 // Setup our user.
973 $user = false;
974
975 // Get locally-cached data if available.
976 switch ( $user_id ) {
977 case bp_loggedin_user_id() :
978 $user = ! empty( $bp->loggedin_user->userdata ) ? $bp->loggedin_user->userdata : false;
979 break;
980
981 case bp_displayed_user_id() :
982 $user = ! empty( $bp->displayed_user->userdata ) ? $bp->displayed_user->userdata : false;
983 break;
984 }
985
986 // Manually get userdata if still empty.
987 if ( empty( $user ) ) {
988 $user = get_userdata( $user_id );
989 }
990
991 // No user found.
992 if ( empty( $user ) ) {
993 $is_spammer = false;
994
995 // User found.
996 } else {
997
998 // Check if spam.
999 if ( !empty( $user->spam ) ) {
1000 $is_spammer = true;
1001 }
1002
1003 if ( 1 == $user->user_status ) {
1004 $is_spammer = true;
1005 }
1006 }
1007
1008 /**
1009 * Filters whether a user is marked as a spammer.
1010 *
1011 * @since 1.6.0
1012 *
1013 * @param bool $is_spammer Whether or not user is marked as spammer.
1014 */
1015 return apply_filters( 'bp_is_user_spammer', (bool) $is_spammer );
1016}
1017
1018/**
1019 * Check whether a user has been marked as deleted.
1020 *
1021 * @since 1.6.0
1022 *
1023 * @param int $user_id The ID for the user.
1024 * @return bool True if deleted, otherwise false.
1025 */
1026function bp_is_user_deleted( $user_id = 0 ) {
1027
1028 // No user to check.
1029 if ( empty( $user_id ) ) {
1030 return false;
1031 }
1032
1033 $bp = buddypress();
1034
1035 // Assume user is not deleted.
1036 $is_deleted = false;
1037
1038 // Setup our user.
1039 $user = false;
1040
1041 // Get locally-cached data if available.
1042 switch ( $user_id ) {
1043 case bp_loggedin_user_id() :
1044 $user = ! empty( $bp->loggedin_user->userdata ) ? $bp->loggedin_user->userdata : false;
1045 break;
1046
1047 case bp_displayed_user_id() :
1048 $user = ! empty( $bp->displayed_user->userdata ) ? $bp->displayed_user->userdata : false;
1049 break;
1050 }
1051
1052 // Manually get userdata if still empty.
1053 if ( empty( $user ) ) {
1054 $user = get_userdata( $user_id );
1055 }
1056
1057 // No user found.
1058 if ( empty( $user ) ) {
1059 $is_deleted = true;
1060
1061 // User found.
1062 } else {
1063
1064 // Check if deleted.
1065 if ( !empty( $user->deleted ) ) {
1066 $is_deleted = true;
1067 }
1068
1069 if ( 2 == $user->user_status ) {
1070 $is_deleted = true;
1071 }
1072 }
1073
1074 /**
1075 * Filters whether a user is marked as deleted.
1076 *
1077 * @since 1.6.0
1078 *
1079 * @param bool $is_deleted Whether or not user is marked as deleted.
1080 */
1081 return apply_filters( 'bp_is_user_deleted', (bool) $is_deleted );
1082}
1083
1084/**
1085 * Check whether a user is "active", ie neither deleted nor spammer.
1086 *
1087 * @since 1.6.0
1088 *
1089 * @param int $user_id The user ID to check.
1090 * @return bool True if active, otherwise false.
1091 */
1092function bp_is_user_active( $user_id = 0 ) {
1093
1094 // Default to current user.
1095 if ( empty( $user_id ) && is_user_logged_in() ) {
1096 $user_id = bp_loggedin_user_id();
1097 }
1098
1099 // No user to check.
1100 if ( empty( $user_id ) ) {
1101 return false;
1102 }
1103
1104 // Check spam.
1105 if ( bp_is_user_spammer( $user_id ) ) {
1106 return false;
1107 }
1108
1109 // Check deleted.
1110 if ( bp_is_user_deleted( $user_id ) ) {
1111 return false;
1112 }
1113
1114 // Assume true if not spam or deleted.
1115 return true;
1116}
1117
1118/**
1119 * Check whether user is not active.
1120 *
1121 * @since 1.6.0
1122 *
1123 * @todo No need for the user fallback checks, since they're done in
1124 * bp_is_user_active().
1125 *
1126 * @param int $user_id The user ID to check.
1127 * @return bool True if inactive, otherwise false.
1128 */
1129function bp_is_user_inactive( $user_id = 0 ) {
1130
1131 // Default to current user.
1132 if ( empty( $user_id ) && is_user_logged_in() ) {
1133 $user_id = bp_loggedin_user_id();
1134 }
1135
1136 // No user to check.
1137 if ( empty( $user_id ) ) {
1138 return false;
1139 }
1140
1141 // Return the inverse of active.
1142 return !bp_is_user_active( $user_id );
1143}
1144
1145/**
1146 * Update a user's last activity.
1147 *
1148 * @since 1.9.0
1149 *
1150 * @param int $user_id ID of the user being updated.
1151 * @param string $time Time of last activity, in 'Y-m-d H:i:s' format.
1152 * @return bool True on success, false on failure.
1153 */
1154function bp_update_user_last_activity( $user_id = 0, $time = '' ) {
1155
1156 // Fall back on current user.
1157 if ( empty( $user_id ) ) {
1158 $user_id = bp_loggedin_user_id();
1159 }
1160
1161 // Bail if the user id is 0, as there's nothing to update.
1162 if ( empty( $user_id ) ) {
1163 return false;
1164 }
1165
1166 // Fall back on current time.
1167 if ( empty( $time ) ) {
1168 $time = bp_core_current_time();
1169 }
1170
1171 // As of BuddyPress 2.0, last_activity is no longer stored in usermeta.
1172 // However, we mirror it there for backward compatibility. Do not use!
1173 // Remove our warning and re-add.
1174 remove_filter( 'update_user_metadata', '_bp_update_user_meta_last_activity_warning', 10 );
1175 remove_filter( 'get_user_metadata', '_bp_get_user_meta_last_activity_warning', 10 );
1176 bp_update_user_meta( $user_id, 'last_activity', $time );
1177 add_filter( 'update_user_metadata', '_bp_update_user_meta_last_activity_warning', 10, 4 );
1178 add_filter( 'get_user_metadata', '_bp_get_user_meta_last_activity_warning', 10, 3 );
1179
1180 return BP_Core_User::update_last_activity( $user_id, $time );
1181}
1182
1183/**
1184 * Backward compatibility for 'last_activity' usermeta fetching.
1185 *
1186 * In BuddyPress 2.0, user last_activity data was moved out of usermeta. For
1187 * backward compatibility, we continue to mirror the data there. This function
1188 * serves two purposes: it warns plugin authors of the change, and it returns
1189 * the data from the proper location.
1190 *
1191 * @since 2.0.0
1192 *
1193 * @access private For internal use only.
1194 *
1195 * @param null $retval Null retval value.
1196 * @param int $object_id ID of the user.
1197 * @param string $meta_key Meta key being fetched.
1198 * @return string|null
1199 */
1200function _bp_get_user_meta_last_activity_warning( $retval, $object_id, $meta_key ) {
1201 static $warned = false;
1202
1203 if ( 'last_activity' === $meta_key ) {
1204 // Don't send the warning more than once per pageload.
1205 if ( false === $warned ) {
1206 _doing_it_wrong( 'get_user_meta( $user_id, \'last_activity\' )', __( 'User last_activity data is no longer stored in usermeta. Use bp_get_user_last_activity() instead.', 'buddypress' ), '2.0.0' );
1207 $warned = true;
1208 }
1209
1210 return bp_get_user_last_activity( $object_id );
1211 }
1212
1213 return $retval;
1214}
1215add_filter( 'get_user_metadata', '_bp_get_user_meta_last_activity_warning', 10, 3 );
1216
1217/**
1218 * Backward compatibility for 'last_activity' usermeta setting.
1219 *
1220 * In BuddyPress 2.0, user last_activity data was moved out of usermeta. For
1221 * backward compatibility, we continue to mirror the data there. This function
1222 * serves two purposes: it warns plugin authors of the change, and it updates
1223 * the data in the proper location.
1224 *
1225 * @since 2.0.0
1226 *
1227 * @access private For internal use only.
1228 *
1229 * @param int $meta_id ID of the just-set usermeta row.
1230 * @param int $object_id ID of the user.
1231 * @param string $meta_key Meta key being fetched.
1232 * @param string $meta_value Active time.
1233 */
1234function _bp_update_user_meta_last_activity_warning( $meta_id, $object_id, $meta_key, $meta_value ) {
1235 if ( 'last_activity' === $meta_key ) {
1236 _doing_it_wrong( 'update_user_meta( $user_id, \'last_activity\' )', __( 'User last_activity data is no longer stored in usermeta. Use bp_update_user_last_activity() instead.', 'buddypress' ), '2.0.0' );
1237 bp_update_user_last_activity( $object_id, $meta_value );
1238 }
1239}
1240add_filter( 'update_user_metadata', '_bp_update_user_meta_last_activity_warning', 10, 4 );
1241
1242/**
1243 * Get the last activity for a given user.
1244 *
1245 * @since 1.9.0
1246 *
1247 * @param int $user_id The ID of the user.
1248 * @return string Time of last activity, in 'Y-m-d H:i:s' format, or an empty
1249 * string if none is found.
1250 */
1251function bp_get_user_last_activity( $user_id = 0 ) {
1252 $activity = '';
1253
1254 $last_activity = BP_Core_User::get_last_activity( $user_id );
1255 if ( ! empty( $last_activity[ $user_id ] ) ) {
1256 $activity = $last_activity[ $user_id ]['date_recorded'];
1257 }
1258
1259 /**
1260 * Filters the last activity for a given user.
1261 *
1262 * @since 1.9.0
1263 *
1264 * @param string $activity Time of last activity, in 'Y-m-d H:i:s' format or
1265 * an empty string if none found.
1266 * @param int $user_id ID of the user being checked.
1267 */
1268 return apply_filters( 'bp_get_user_last_activity', $activity, $user_id );
1269}
1270
1271/**
1272 * Migrate last_activity data from the usermeta table to the activity table.
1273 *
1274 * Generally, this function is only run when BP is upgraded to 2.0. It can also
1275 * be called directly from the BuddyPress Tools panel.
1276 *
1277 * @since 2.0.0
1278 *
1279 * @return bool
1280 */
1281function bp_last_activity_migrate() {
1282 global $wpdb;
1283
1284 $bp = buddypress();
1285
1286 // Wipe out existing last_activity data in the activity table -
1287 // this helps to prevent duplicates when pulling from the usermeta
1288 // table.
1289 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->members->table_name_last_activity} WHERE component = %s AND type = 'last_activity'", $bp->members->id ) );
1290
1291 $sql = "INSERT INTO {$bp->members->table_name_last_activity} (`user_id`, `component`, `type`, `action`, `content`, `primary_link`, `item_id`, `date_recorded` ) (
1292 SELECT user_id, '{$bp->members->id}' as component, 'last_activity' as type, '' as action, '' as content, '' as primary_link, 0 as item_id, meta_value AS date_recorded
1293 FROM {$wpdb->usermeta}
1294 WHERE
1295 meta_key = 'last_activity'
1296 );";
1297
1298 return $wpdb->query( $sql );
1299}
1300
1301/**
1302 * Fetch every post that is authored by the given user for the current blog.
1303 *
1304 * No longer used in BuddyPress.
1305 *
1306 * @todo Deprecate.
1307 *
1308 * @param int $user_id ID of the user being queried.
1309 * @return array Post IDs.
1310 */
1311function bp_core_get_all_posts_for_user( $user_id = 0 ) {
1312 global $wpdb;
1313
1314 if ( empty( $user_id ) ) {
1315 $user_id = bp_displayed_user_id();
1316 }
1317
1318 return apply_filters( 'bp_core_get_all_posts_for_user', $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_author = %d AND post_status = 'publish' AND post_type = 'post'", $user_id ) ) );
1319}
1320
1321/**
1322 * Process account deletion requests.
1323 *
1324 * Primarily used for self-deletions, as requested through Settings.
1325 *
1326 * @since 1.0.0
1327 *
1328 * @param int $user_id Optional. ID of the user to be deleted. Default: the
1329 * logged-in user.
1330 * @return bool True on success, false on failure.
1331 */
1332function bp_core_delete_account( $user_id = 0 ) {
1333
1334 // Use logged in user ID if none is passed.
1335 if ( empty( $user_id ) ) {
1336 $user_id = bp_loggedin_user_id();
1337 }
1338
1339 // Site admins cannot be deleted.
1340 if ( is_super_admin( $user_id ) ) {
1341 return false;
1342 }
1343
1344 // Extra checks if user is not deleting themselves.
1345 if ( bp_loggedin_user_id() !== absint( $user_id ) ) {
1346
1347 // Bail if current user cannot delete any users.
1348 if ( ! bp_current_user_can( 'delete_users' ) ) {
1349 return false;
1350 }
1351
1352 // Bail if current user cannot delete this user.
1353 if ( ! current_user_can_for_blog( bp_get_root_blog_id(), 'delete_user', $user_id ) ) {
1354 return false;
1355 }
1356 }
1357
1358 /**
1359 * Fires before the processing of an account deletion.
1360 *
1361 * @since 1.6.0
1362 *
1363 * @param int $user_id ID of the user account being deleted.
1364 */
1365 do_action( 'bp_core_pre_delete_account', $user_id );
1366
1367 // Specifically handle multi-site environment.
1368 if ( is_multisite() ) {
1369 require_once( ABSPATH . '/wp-admin/includes/ms.php' );
1370 require_once( ABSPATH . '/wp-admin/includes/user.php' );
1371
1372 $retval = wpmu_delete_user( $user_id );
1373
1374 // Single site user deletion.
1375 } else {
1376 require_once( ABSPATH . '/wp-admin/includes/user.php' );
1377 $retval = wp_delete_user( $user_id );
1378 }
1379
1380 /**
1381 * Fires after the deletion of an account.
1382 *
1383 * @since 1.6.0
1384 *
1385 * @param int $user_id ID of the user account that was deleted.
1386 */
1387 do_action( 'bp_core_deleted_account', $user_id );
1388
1389 return $retval;
1390}
1391
1392/**
1393 * Delete a user's avatar when the user is deleted.
1394 *
1395 * @since 1.9.0
1396 *
1397 * @param int $user_id ID of the user who is about to be deleted.
1398 * @return bool True on success, false on failure.
1399 */
1400function bp_core_delete_avatar_on_user_delete( $user_id ) {
1401 return bp_core_delete_existing_avatar( array(
1402 'item_id' => $user_id,
1403 'object' => 'user',
1404 ) );
1405}
1406add_action( 'wpmu_delete_user', 'bp_core_delete_avatar_on_user_delete' );
1407add_action( 'delete_user', 'bp_core_delete_avatar_on_user_delete' );
1408
1409/**
1410 * Multibyte-safe ucfirst() support.
1411 *
1412 * Uses multibyte functions when available on the PHP build.
1413 *
1414 * @since 1.0.0
1415 *
1416 * @param string $str String to be upper-cased.
1417 * @return string
1418 */
1419function bp_core_ucfirst( $str ) {
1420 if ( function_exists( 'mb_strtoupper' ) && function_exists( 'mb_substr' ) ) {
1421 $fc = mb_strtoupper( mb_substr( $str, 0, 1 ) );
1422 return $fc.mb_substr( $str, 1 );
1423 } else {
1424 return ucfirst( $str );
1425 }
1426}
1427
1428/**
1429 * Prevent spammers from logging in.
1430 *
1431 * When a user logs in, check if they have been marked as a spammer. If yes
1432 * then simply redirect them to the home page and stop them from logging in.
1433 *
1434 * @since 1.1.2
1435 *
1436 * @param WP_User|WP_Error $user Either the WP_User object or the WP_Error
1437 * object, as passed to the 'authenticate' filter.
1438 * @return WP_User|WP_Error If the user is not a spammer, return the WP_User
1439 * object. Otherwise a new WP_Error object.
1440 */
1441function bp_core_boot_spammer( $user ) {
1442
1443 // Check to see if the $user has already failed logging in, if so return $user as-is.
1444 if ( is_wp_error( $user ) || empty( $user ) ) {
1445 return $user;
1446 }
1447
1448 // The user exists; now do a check to see if the user is a spammer
1449 // if the user is a spammer, stop them in their tracks!
1450 if ( is_a( $user, 'WP_User' ) && ( ( is_multisite() && (int) $user->spam ) || 1 == $user->user_status ) ) {
1451 return new WP_Error( 'invalid_username', __( '<strong>ERROR</strong>: Your account has been marked as a spammer.', 'buddypress' ) );
1452 }
1453
1454 // User is good to go!
1455 return $user;
1456}
1457add_filter( 'authenticate', 'bp_core_boot_spammer', 30 );
1458
1459/**
1460 * Delete last_activity data for the user when the user is deleted.
1461 *
1462 * @since 1.0.0
1463 *
1464 * @param int $user_id The user ID for the user to delete usermeta for.
1465 */
1466function bp_core_remove_data( $user_id ) {
1467
1468 // Remove last_activity data.
1469 BP_Core_User::delete_last_activity( $user_id );
1470
1471 // Flush the cache to remove the user from all cached objects.
1472 wp_cache_flush();
1473}
1474add_action( 'wpmu_delete_user', 'bp_core_remove_data' );
1475add_action( 'delete_user', 'bp_core_remove_data' );
1476add_action( 'bp_make_spam_user', 'bp_core_remove_data' );
1477
1478/**
1479 * Check whether the logged-in user can edit settings for the displayed user.
1480 *
1481 * @since 1.5.0
1482 *
1483 * @return bool True if editing is allowed, otherwise false.
1484 */
1485function bp_core_can_edit_settings() {
1486 $status = false;
1487
1488 if ( bp_is_my_profile() ) {
1489 $status = true;
1490 } elseif ( is_super_admin( bp_displayed_user_id() ) && ! is_super_admin() ) {
1491 $status = false;
1492 } elseif ( bp_current_user_can( 'bp_moderate' ) || current_user_can( 'edit_users' ) ) {
1493 $status = true;
1494 }
1495
1496 /**
1497 * Filters the status of whether the logged-in user can edit settings for the displayed user or not.
1498 *
1499 * @since 2.8.0
1500 *
1501 * @param bool True if editing is allowed, otherwise false.
1502 */
1503 return apply_filters( 'bp_core_can_edit_settings', $status );
1504}
1505
1506/** Sign-up *******************************************************************/
1507
1508/**
1509 * Flush illegal names by getting and setting 'illegal_names' site option.
1510 *
1511 * @since 1.2.5
1512 */
1513function bp_core_flush_illegal_names() {
1514 $illegal_names = get_site_option( 'illegal_names' );
1515 update_site_option( 'illegal_names', $illegal_names );
1516}
1517
1518/**
1519 * Add BuddyPress-specific items to the illegal_names array.
1520 *
1521 * @since 1.2.7
1522 *
1523 * @param array|string $value Illegal names as being saved defined in
1524 * Multisite settings.
1525 * @param array|string $oldvalue The old value of the option.
1526 * @return array Merged and unique array of illegal names.
1527 */
1528function bp_core_get_illegal_names( $value = '', $oldvalue = '' ) {
1529
1530 // Make sure $value is array.
1531 if ( empty( $value ) ) {
1532 $db_illegal_names = array();
1533 }
1534
1535 if ( is_array( $value ) ) {
1536 $db_illegal_names = $value;
1537 } elseif ( is_string( $value ) ) {
1538 $db_illegal_names = explode( ' ', $value );
1539 }
1540
1541 // Add the core components' slugs to the banned list even if their components aren't active.
1542 $bp_component_slugs = array(
1543 'groups',
1544 'members',
1545 'forums',
1546 'blogs',
1547 'activity',
1548 'profile',
1549 'friends',
1550 'search',
1551 'settings',
1552 'notifications',
1553 'register',
1554 'activate'
1555 );
1556
1557 // Core constants.
1558 $slug_constants = array(
1559 'BP_GROUPS_SLUG',
1560 'BP_MEMBERS_SLUG',
1561 'BP_FORUMS_SLUG',
1562 'BP_BLOGS_SLUG',
1563 'BP_ACTIVITY_SLUG',
1564 'BP_XPROFILE_SLUG',
1565 'BP_FRIENDS_SLUG',
1566 'BP_SEARCH_SLUG',
1567 'BP_SETTINGS_SLUG',
1568 'BP_NOTIFICATIONS_SLUG',
1569 'BP_REGISTER_SLUG',
1570 'BP_ACTIVATION_SLUG',
1571 );
1572 foreach( $slug_constants as $constant ) {
1573 if ( defined( $constant ) ) {
1574 $bp_component_slugs[] = constant( $constant );
1575 }
1576 }
1577
1578 /**
1579 * Filters the array of default illegal usernames.
1580 *
1581 * @since 1.2.2
1582 *
1583 * @param array $value Merged and unique array of illegal usernames.
1584 */
1585 $filtered_illegal_names = apply_filters( 'bp_core_illegal_usernames', array_merge( array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator' ), $bp_component_slugs ) );
1586
1587 // Merge the arrays together.
1588 $merged_names = array_merge( (array) $filtered_illegal_names, (array) $db_illegal_names );
1589
1590 // Remove duplicates.
1591 $illegal_names = array_unique( (array) $merged_names );
1592
1593 /**
1594 * Filters the array of default illegal names.
1595 *
1596 * @since 1.2.5
1597 *
1598 * @param array $value Merged and unique array of illegal names.
1599 */
1600 return apply_filters( 'bp_core_illegal_names', $illegal_names );
1601}
1602add_filter( 'pre_update_site_option_illegal_names', 'bp_core_get_illegal_names', 10, 2 );
1603
1604/**
1605 * Check that an email address is valid for use.
1606 *
1607 * Performs the following checks:
1608 * - Is the email address well-formed?
1609 * - Is the email address already used?
1610 * - If there's an email domain blacklist, is the current domain on it?
1611 * - If there's an email domain whitelest, is the current domain on it?
1612 *
1613 * @since 1.6.2
1614 *
1615 * @param string $user_email The email being checked.
1616 * @return bool|array True if the address passes all checks; otherwise an array
1617 * of error codes.
1618 */
1619function bp_core_validate_email_address( $user_email ) {
1620 $errors = array();
1621
1622 $user_email = sanitize_email( $user_email );
1623
1624 // Is the email well-formed?
1625 if ( ! is_email( $user_email ) ) {
1626 $errors['invalid'] = 1;
1627 }
1628
1629 // Is the email on the Banned Email Domains list?
1630 // Note: This check only works on Multisite.
1631 if ( function_exists( 'is_email_address_unsafe' ) && is_email_address_unsafe( $user_email ) ) {
1632 $errors['domain_banned'] = 1;
1633 }
1634
1635 // Is the email on the Limited Email Domains list?
1636 // Note: This check only works on Multisite.
1637 $limited_email_domains = get_site_option( 'limited_email_domains' );
1638 if ( is_array( $limited_email_domains ) && empty( $limited_email_domains ) == false ) {
1639 $emaildomain = substr( $user_email, 1 + strpos( $user_email, '@' ) );
1640 if ( ! in_array( $emaildomain, $limited_email_domains ) ) {
1641 $errors['domain_not_allowed'] = 1;
1642 }
1643 }
1644
1645 // Is the email alreday in use?
1646 if ( email_exists( $user_email ) ) {
1647 $errors['in_use'] = 1;
1648 }
1649
1650 $retval = ! empty( $errors ) ? $errors : true;
1651
1652 return $retval;
1653}
1654
1655/**
1656 * Add the appropriate errors to a WP_Error object, given results of a validation test.
1657 *
1658 * Functions like bp_core_validate_email_address() return a structured array
1659 * of error codes. bp_core_add_validation_error_messages() takes this array and
1660 * parses, adding the appropriate error messages to the WP_Error object.
1661 *
1662 * @since 1.7.0
1663 *
1664 * @see bp_core_validate_email_address()
1665 *
1666 * @param WP_Error $errors WP_Error object.
1667 * @param array $validation_results The return value of a validation function
1668 * like bp_core_validate_email_address().
1669 */
1670function bp_core_add_validation_error_messages( WP_Error $errors, $validation_results ) {
1671 if ( ! empty( $validation_results['invalid'] ) ) {
1672 $errors->add( 'user_email', __( 'Please check your email address.', 'buddypress' ) );
1673 }
1674
1675 if ( ! empty( $validation_results['domain_banned'] ) ) {
1676 $errors->add( 'user_email', __( 'Sorry, that email address is not allowed!', 'buddypress' ) );
1677 }
1678
1679 if ( ! empty( $validation_results['domain_not_allowed'] ) ) {
1680 $errors->add( 'user_email', __( 'Sorry, that email address is not allowed!', 'buddypress' ) );
1681 }
1682
1683 if ( ! empty( $validation_results['in_use'] ) ) {
1684 $errors->add( 'user_email', __( 'Sorry, that email address is already used!', 'buddypress' ) );
1685 }
1686}
1687
1688/**
1689 * Validate a user name and email address when creating a new user.
1690 *
1691 * @since 1.2.2
1692 *
1693 * @param string $user_name Username to validate.
1694 * @param string $user_email Email address to validate.
1695 * @return array Results of user validation including errors, if any.
1696 */
1697function bp_core_validate_user_signup( $user_name, $user_email ) {
1698
1699 // Make sure illegal names include BuddyPress slugs and values.
1700 bp_core_flush_illegal_names();
1701
1702 // WordPress Multisite has its own validation. Use it, so that we
1703 // properly mirror restrictions on username, etc.
1704 if ( function_exists( 'wpmu_validate_user_signup' ) ) {
1705 $result = wpmu_validate_user_signup( $user_name, $user_email );
1706
1707 // When not running Multisite, we perform our own validation. What
1708 // follows reproduces much of the logic of wpmu_validate_user_signup(),
1709 // minus the multisite-specific restrictions on user_login.
1710 } else {
1711 $errors = new WP_Error();
1712
1713 /**
1714 * Filters the username before being validated.
1715 *
1716 * @since 1.5.5
1717 *
1718 * @param string $user_name Username to validate.
1719 */
1720 $user_name = apply_filters( 'pre_user_login', $user_name );
1721
1722 // User name can't be empty.
1723 if ( empty( $user_name ) ) {
1724 $errors->add( 'user_name', __( 'Please enter a username', 'buddypress' ) );
1725 }
1726
1727 // User name can't be on the blacklist.
1728 $illegal_names = get_site_option( 'illegal_names' );
1729 if ( in_array( $user_name, (array) $illegal_names ) ) {
1730 $errors->add( 'user_name', __( 'That username is not allowed', 'buddypress' ) );
1731 }
1732
1733 // User name must pass WP's validity check.
1734 if ( ! validate_username( $user_name ) ) {
1735 $errors->add( 'user_name', __( 'Usernames can contain only letters, numbers, ., -, and @', 'buddypress' ) );
1736 }
1737
1738 // Minimum of 4 characters.
1739 if ( strlen( $user_name ) < 4 ) {
1740 $errors->add( 'user_name', __( 'Username must be at least 4 characters', 'buddypress' ) );
1741 }
1742
1743 // No underscores. @todo Why not?
1744 if ( false !== strpos( ' ' . $user_name, '_' ) ) {
1745 $errors->add( 'user_name', __( 'Sorry, usernames may not contain the character "_"!', 'buddypress' ) );
1746 }
1747
1748 // No usernames that are all numeric. @todo Why?
1749 $match = array();
1750 preg_match( '/[0-9]*/', $user_name, $match );
1751 if ( $match[0] == $user_name ) {
1752 $errors->add( 'user_name', __( 'Sorry, usernames must have letters too!', 'buddypress' ) );
1753 }
1754
1755 // Check into signups.
1756 $signups = BP_Signup::get( array(
1757 'user_login' => $user_name,
1758 ) );
1759
1760 $signup = isset( $signups['signups'] ) && ! empty( $signups['signups'][0] ) ? $signups['signups'][0] : false;
1761
1762 // Check if the username has been used already.
1763 if ( username_exists( $user_name ) || ! empty( $signup ) ) {
1764 $errors->add( 'user_name', __( 'Sorry, that username already exists!', 'buddypress' ) );
1765 }
1766
1767 // Validate the email address and process the validation results into
1768 // error messages.
1769 $validate_email = bp_core_validate_email_address( $user_email );
1770 bp_core_add_validation_error_messages( $errors, $validate_email );
1771
1772 // Assemble the return array.
1773 $result = array(
1774 'user_name' => $user_name,
1775 'user_email' => $user_email,
1776 'errors' => $errors,
1777 );
1778
1779 // Apply WPMU legacy filter.
1780 $result = apply_filters( 'wpmu_validate_user_signup', $result );
1781 }
1782
1783 /**
1784 * Filters the result of the user signup validation.
1785 *
1786 * @since 1.2.2
1787 *
1788 * @param array $result Results of user validation including errors, if any.
1789 */
1790 return apply_filters( 'bp_core_validate_user_signup', $result );
1791}
1792
1793/**
1794 * Validate blog URL and title provided at signup.
1795 *
1796 * @since 1.2.2
1797 *
1798 * @todo Why do we have this wrapper?
1799 *
1800 * @param string $blog_url Blog URL requested during registration.
1801 * @param string $blog_title Blog title requested during registration.
1802 * @return array
1803 */
1804function bp_core_validate_blog_signup( $blog_url, $blog_title ) {
1805 if ( ! is_multisite() || ! function_exists( 'wpmu_validate_blog_signup' ) ) {
1806 return false;
1807 }
1808
1809 /**
1810 * Filters the validated blog url and title provided at signup.
1811 *
1812 * @since 1.2.2
1813 *
1814 * @param array $value Array with the new site data and error messages.
1815 */
1816 return apply_filters( 'bp_core_validate_blog_signup', wpmu_validate_blog_signup( $blog_url, $blog_title ) );
1817}
1818
1819/**
1820 * Process data submitted at user registration and convert to a signup object.
1821 *
1822 * @since 1.2.0
1823 *
1824 * @todo There appears to be a bug in the return value on success.
1825 *
1826 * @param string $user_login Login name requested by the user.
1827 * @param string $user_password Password requested by the user.
1828 * @param string $user_email Email address entered by the user.
1829 * @param array $usermeta Miscellaneous metadata about the user (blog-specific
1830 * signup data, xprofile data, etc).
1831 * @return int|false True on success, WP_Error on failure.
1832 */
1833function bp_core_signup_user( $user_login, $user_password, $user_email, $usermeta ) {
1834 $bp = buddypress();
1835
1836 // We need to cast $user_id to pass to the filters.
1837 $user_id = false;
1838
1839 // Multisite installs have their own install procedure.
1840 if ( is_multisite() ) {
1841 wpmu_signup_user( $user_login, $user_email, $usermeta );
1842
1843 } else {
1844 // Format data.
1845 $user_login = preg_replace( '/\s+/', '', sanitize_user( $user_login, true ) );
1846 $user_email = sanitize_email( $user_email );
1847 $activation_key = wp_generate_password( 32, false );
1848
1849 /**
1850 * WordPress's default behavior is to create user accounts
1851 * immediately at registration time. BuddyPress uses a system
1852 * borrowed from WordPress Multisite, where signups are stored
1853 * separately and accounts are only created at the time of
1854 * activation. For backward compatibility with plugins that may
1855 * be anticipating WP's default behavior, BP silently creates
1856 * accounts for registrations (though it does not use them). If
1857 * you know that you are not running any plugins dependent on
1858 * these pending accounts, you may want to save a little DB
1859 * clutter by defining setting the BP_SIGNUPS_SKIP_USER_CREATION
1860 * to true in your wp-config.php file.
1861 */
1862 if ( ! defined( 'BP_SIGNUPS_SKIP_USER_CREATION' ) || ! BP_SIGNUPS_SKIP_USER_CREATION ) {
1863 $user_id = BP_Signup::add_backcompat( $user_login, $user_password, $user_email, $usermeta );
1864
1865 if ( is_wp_error( $user_id ) ) {
1866 return $user_id;
1867 }
1868
1869 bp_update_user_meta( $user_id, 'activation_key', $activation_key );
1870 }
1871
1872 $args = array(
1873 'user_login' => $user_login,
1874 'user_email' => $user_email,
1875 'activation_key' => $activation_key,
1876 'meta' => $usermeta,
1877 );
1878
1879 BP_Signup::add( $args );
1880
1881 /**
1882 * Filters if BuddyPress should send an activation key for a new signup.
1883 *
1884 * @since 1.2.3
1885 *
1886 * @param bool $value Whether or not to send the activation key.
1887 * @param int $user_id User ID to send activation key to.
1888 * @param string $user_email User email to send activation key to.
1889 * @param string $activation_key Activation key to be sent.
1890 * @param array $usermeta Miscellaneous metadata about the user (blog-specific
1891 * signup data, xprofile data, etc).
1892 */
1893 if ( apply_filters( 'bp_core_signup_send_activation_key', true, $user_id, $user_email, $activation_key, $usermeta ) ) {
1894 bp_core_signup_send_validation_email( $user_id, $user_email, $activation_key, $user_login );
1895 }
1896 }
1897
1898 $bp->signup->username = $user_login;
1899
1900 /**
1901 * Fires at the end of the process to sign up a user.
1902 *
1903 * @since 1.2.2
1904 *
1905 * @param bool|WP_Error $user_id True on success, WP_Error on failure.
1906 * @param string $user_login Login name requested by the user.
1907 * @param string $user_password Password requested by the user.
1908 * @param string $user_email Email address requested by the user.
1909 * @param array $usermeta Miscellaneous metadata about the user (blog-specific
1910 * signup data, xprofile data, etc).
1911 */
1912 do_action( 'bp_core_signup_user', $user_id, $user_login, $user_password, $user_email, $usermeta );
1913
1914 return $user_id;
1915}
1916
1917/**
1918 * Create a blog and user based on data supplied at user registration.
1919 *
1920 * @since 1.2.2
1921 *
1922 * @param string $blog_domain Domain requested by user.
1923 * @param string $blog_path Path requested by user.
1924 * @param string $blog_title Title as entered by user.
1925 * @param string $user_name user_login of requesting user.
1926 * @param string $user_email Email address of requesting user.
1927 * @param string $usermeta Miscellaneous metadata for the user.
1928 * @return bool
1929 */
1930function bp_core_signup_blog( $blog_domain, $blog_path, $blog_title, $user_name, $user_email, $usermeta ) {
1931 if ( ! is_multisite() || ! function_exists( 'wpmu_signup_blog' ) ) {
1932 return false;
1933 }
1934
1935 /**
1936 * Filters the result of wpmu_signup_blog().
1937 *
1938 * This filter provides no value and is retained for
1939 * backwards compatibility.
1940 *
1941 * @since 1.2.2
1942 *
1943 * @param void $value
1944 */
1945 return apply_filters( 'bp_core_signup_blog', wpmu_signup_blog( $blog_domain, $blog_path, $blog_title, $user_name, $user_email, $usermeta ) );
1946}
1947
1948/**
1949 * Activate a signup, as identified by an activation key.
1950 *
1951 * @since 1.2.2
1952 *
1953 * @param string $key Activation key.
1954 * @return int|bool User ID on success, false on failure.
1955 */
1956function bp_core_activate_signup( $key ) {
1957 global $wpdb;
1958
1959 $user = false;
1960
1961 // Multisite installs have their own activation routine.
1962 if ( is_multisite() ) {
1963 $user = wpmu_activate_signup( $key );
1964
1965 // If there were errors, add a message and redirect.
1966 if ( ! empty( $user->errors ) ) {
1967 return $user;
1968 }
1969
1970 $user_id = $user['user_id'];
1971
1972 } else {
1973 $signups = BP_Signup::get( array(
1974 'activation_key' => $key,
1975 ) );
1976
1977 if ( empty( $signups['signups'] ) ) {
1978 return new WP_Error( 'invalid_key', __( 'Invalid activation key.', 'buddypress' ) );
1979 }
1980
1981 $signup = $signups['signups'][0];
1982
1983 if ( $signup->active ) {
1984 if ( empty( $signup->domain ) ) {
1985 return new WP_Error( 'already_active', __( 'The user is already active.', 'buddypress' ), $signup );
1986 } else {
1987 return new WP_Error( 'already_active', __( 'The site is already active.', 'buddypress' ), $signup );
1988 }
1989 }
1990
1991 // Password is hashed again in wp_insert_user.
1992 $password = wp_generate_password( 12, false );
1993
1994 $user_id = username_exists( $signup->user_login );
1995
1996 // Create the user. This should only be necessary if BP_SIGNUPS_SKIP_USER_CREATION is true.
1997 if ( ! $user_id ) {
1998 $user_id = wp_create_user( $signup->user_login, $password, $signup->user_email );
1999
2000 // Otherwise, update the existing user's status.
2001 } elseif ( $key === bp_get_user_meta( $user_id, 'activation_key', true ) || $key === wp_hash( $user_id ) ) {
2002
2003 // Change the user's status so they become active.
2004 if ( ! $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->users} SET user_status = 0 WHERE ID = %d", $user_id ) ) ) {
2005 return new WP_Error( 'invalid_key', __( 'Invalid activation key.', 'buddypress' ) );
2006 }
2007
2008 bp_delete_user_meta( $user_id, 'activation_key' );
2009
2010 $member = get_userdata( $user_id );
2011 $member->set_role( get_option('default_role') );
2012
2013 $user_already_created = true;
2014
2015 } else {
2016 $user_already_exists = true;
2017 }
2018
2019 if ( ! $user_id ) {
2020 return new WP_Error( 'create_user', __( 'Could not create user', 'buddypress' ), $signup );
2021 }
2022
2023 // Fetch the signup so we have the data later on.
2024 $signups = BP_Signup::get( array(
2025 'activation_key' => $key,
2026 ) );
2027
2028 $signup = isset( $signups['signups'] ) && ! empty( $signups['signups'][0] ) ? $signups['signups'][0] : false;
2029
2030 // Activate the signup.
2031 BP_Signup::validate( $key );
2032
2033 if ( isset( $user_already_exists ) ) {
2034 return new WP_Error( 'user_already_exists', __( 'That username is already activated.', 'buddypress' ), $signup );
2035 }
2036
2037 // Set up data to pass to the legacy filter.
2038 $user = array(
2039 'user_id' => $user_id,
2040 'password' => $signup->meta['password'],
2041 'meta' => $signup->meta,
2042 );
2043
2044 // Notify the site admin of a new user registration.
2045 if ( apply_filters( 'bp_sent_notification_to_admin_on_user_registration', true) )
2046 wp_new_user_notification( $user_id );
2047
2048 if ( isset( $user_already_created ) ) {
2049
2050 /**
2051 * Fires if the user has already been created.
2052 *
2053 * @since 1.2.2
2054 *
2055 * @param int $user_id ID of the user being checked.
2056 * @param string $key Activation key.
2057 * @param array $user Array of user data.
2058 */
2059 do_action( 'bp_core_activated_user', $user_id, $key, $user );
2060 return $user_id;
2061 }
2062 }
2063
2064 // Set any profile data.
2065 if ( bp_is_active( 'xprofile' ) ) {
2066 if ( ! empty( $user['meta']['profile_field_ids'] ) ) {
2067 $profile_field_ids = explode( ',', $user['meta']['profile_field_ids'] );
2068
2069 foreach( (array) $profile_field_ids as $field_id ) {
2070 $current_field = isset( $user['meta']["field_{$field_id}"] ) ? $user['meta']["field_{$field_id}"] : false;
2071
2072 if ( !empty( $current_field ) ) {
2073 xprofile_set_field_data( $field_id, $user_id, $current_field );
2074 }
2075
2076 /*
2077 * Save the visibility level.
2078 *
2079 * Use the field's default visibility if not present, and 'public' if a
2080 * default visibility is not defined.
2081 */
2082 $key = "field_{$field_id}_visibility";
2083 if ( isset( $user['meta'][ $key ] ) ) {
2084 $visibility_level = $user['meta'][ $key ];
2085 } else {
2086 $vfield = xprofile_get_field( $field_id );
2087 $visibility_level = isset( $vfield->default_visibility ) ? $vfield->default_visibility : 'public';
2088 }
2089 xprofile_set_field_visibility_level( $field_id, $user_id, $visibility_level );
2090 }
2091 }
2092 }
2093
2094 // Replace the password automatically generated by WordPress by the one the user chose.
2095 if ( ! empty( $user['meta']['password'] ) ) {
2096 $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->users} SET user_pass = %s WHERE ID = %d", $user['meta']['password'], $user_id ) );
2097
2098 /**
2099 * Make sure to clean the user's cache as we've
2100 * directly edited the password without using
2101 * wp_update_user().
2102 *
2103 * If we can't use wp_update_user() that's because
2104 * we already hashed the password at the signup step.
2105 */
2106 $uc = wp_cache_get( $user_id, 'users' );
2107
2108 if ( ! empty( $uc->ID ) ) {
2109 clean_user_cache( $uc->ID );
2110 }
2111 }
2112
2113 /**
2114 * Fires at the end of the user activation process.
2115 *
2116 * @since 1.2.2
2117 *
2118 * @param int $user_id ID of the user being checked.
2119 * @param string $key Activation key.
2120 * @param array $user Array of user data.
2121 */
2122 do_action( 'bp_core_activated_user', $user_id, $key, $user );
2123
2124 return $user_id;
2125}
2126
2127/**
2128 * Migrate signups from pre-2.0 configuration to wp_signups.
2129 *
2130 * @since 2.0.1
2131 */
2132function bp_members_migrate_signups() {
2133 global $wpdb;
2134
2135 $status_2_ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->users} WHERE user_status = '2'" );
2136
2137 if ( ! empty( $status_2_ids ) ) {
2138 $signups = get_users( array(
2139 'fields' => array(
2140 'ID',
2141 'user_login',
2142 'user_pass',
2143 'user_registered',
2144 'user_email',
2145 'display_name',
2146 ),
2147 'include' => $status_2_ids,
2148 ) );
2149
2150 // Fetch activation keys separately, to avoid the all_with_meta
2151 // overhead.
2152 $status_2_ids_sql = implode( ',', $status_2_ids );
2153 $ak_data = $wpdb->get_results( "SELECT user_id, meta_value FROM {$wpdb->usermeta} WHERE meta_key = 'activation_key' AND user_id IN ({$status_2_ids_sql})" );
2154
2155 // Rekey.
2156 $activation_keys = array();
2157 foreach ( $ak_data as $ak_datum ) {
2158 $activation_keys[ intval( $ak_datum->user_id ) ] = $ak_datum->meta_value;
2159 }
2160
2161 unset( $status_2_ids_sql, $status_2_ids, $ak_data );
2162
2163 // Merge.
2164 foreach ( $signups as &$signup ) {
2165 if ( isset( $activation_keys[ $signup->ID ] ) ) {
2166 $signup->activation_key = $activation_keys[ $signup->ID ];
2167 }
2168 }
2169
2170 // Reset the signup var as we're using it to process the migration.
2171 unset( $signup );
2172
2173 } else {
2174 return;
2175 }
2176
2177 foreach ( $signups as $signup ) {
2178 $meta = array();
2179
2180 // Rebuild the activation key, if missing.
2181 if ( empty( $signup->activation_key ) ) {
2182 $signup->activation_key = wp_generate_password( 32, false );
2183 }
2184
2185 if ( bp_is_active( 'xprofile' ) ) {
2186 $meta['field_1'] = $signup->display_name;
2187 }
2188
2189 $meta['password'] = $signup->user_pass;
2190
2191 $user_login = preg_replace( '/\s+/', '', sanitize_user( $signup->user_login, true ) );
2192 $user_email = sanitize_email( $signup->user_email );
2193
2194 BP_Signup::add( array(
2195 'user_login' => $user_login,
2196 'user_email' => $user_email,
2197 'registered' => $signup->user_registered,
2198 'activation_key' => $signup->activation_key,
2199 'meta' => $meta
2200 ) );
2201
2202 // Deleting these options will remove signups from users count.
2203 delete_user_option( $signup->ID, 'capabilities' );
2204 delete_user_option( $signup->ID, 'user_level' );
2205 }
2206}
2207
2208/**
2209 * Map a user's WP display name to the XProfile fullname field, if necessary.
2210 *
2211 * This only happens when a user is registered in wp-admin by an administrator;
2212 * during normal registration, XProfile data is provided directly by the user.
2213 *
2214 * @since 1.2.0
2215 *
2216 * @param int $user_id ID of the user.
2217 * @return bool
2218 */
2219function bp_core_map_user_registration( $user_id ) {
2220
2221 // Only map data when the site admin is adding users, not on registration.
2222 if ( ! is_admin() ) {
2223 return false;
2224 }
2225
2226 // Add the user's fullname to Xprofile.
2227 if ( bp_is_active( 'xprofile' ) ) {
2228 $firstname = bp_get_user_meta( $user_id, 'first_name', true );
2229 $lastname = ' ' . bp_get_user_meta( $user_id, 'last_name', true );
2230 $name = $firstname . $lastname;
2231
2232 if ( empty( $name ) || ' ' == $name ) {
2233 $name = bp_get_user_meta( $user_id, 'nickname', true );
2234 }
2235
2236 xprofile_set_field_data( 1, $user_id, $name );
2237 }
2238}
2239add_action( 'user_register', 'bp_core_map_user_registration' );
2240
2241/**
2242 * Get the avatar storage directory for use during registration.
2243 *
2244 * @since 1.1.0
2245 *
2246 * @return string|bool Directory path on success, false on failure.
2247 */
2248function bp_core_signup_avatar_upload_dir() {
2249 $bp = buddypress();
2250
2251 if ( empty( $bp->signup->avatar_dir ) ) {
2252 return false;
2253 }
2254
2255 $directory = 'avatars/signups';
2256 $path = bp_core_avatar_upload_path() . '/' . $directory . '/' . $bp->signup->avatar_dir;
2257 $newbdir = $path;
2258 $newurl = bp_core_avatar_url() . '/' . $directory . '/' . $bp->signup->avatar_dir;
2259 $newburl = $newurl;
2260 $newsubdir = '/' . $directory . '/' . $bp->signup->avatar_dir;
2261
2262 /**
2263 * Filters the avatar storage directory for use during registration.
2264 *
2265 * @since 1.1.1
2266 *
2267 * @param array $value Array of path and URL values for created storage directory.
2268 */
2269 return apply_filters( 'bp_core_signup_avatar_upload_dir', array(
2270 'path' => $path,
2271 'url' => $newurl,
2272 'subdir' => $newsubdir,
2273 'basedir' => $newbdir,
2274 'baseurl' => $newburl,
2275 'error' => false
2276 ) );
2277}
2278
2279/**
2280 * Send activation email to a newly registered user.
2281 *
2282 * @since 1.2.2
2283 * @since 2.5.0 Add the $user_login parameter.
2284 *
2285 * @param int|bool $user_id ID of the new user, false if BP_SIGNUPS_SKIP_USER_CREATION is true.
2286 * @param string $user_email Email address of the new user.
2287 * @param string $key Activation key.
2288 * @param string $user_login Optional. The user login name.
2289 */
2290function bp_core_signup_send_validation_email( $user_id, $user_email, $key, $user_login = '' ) {
2291 $args = array(
2292 'tokens' => array(
2293 'activate.url' => esc_url( trailingslashit( bp_get_activation_page() ) . "{$key}/" ),
2294 'key' => $key,
2295 'user.email' => $user_email,
2296 'user.id' => $user_id,
2297 ),
2298 );
2299
2300 if ( $user_id ) {
2301 $to = $user_id;
2302 } else {
2303 $to = array( array( $user_email => $user_login ) );
2304 }
2305
2306 bp_send_email( 'core-user-registration', $to, $args );
2307}
2308
2309/**
2310 * Display a "resend email" link when an unregistered user attempts to log in.
2311 *
2312 * @since 1.2.2
2313 *
2314 * @param WP_User|WP_Error|null $user Either the WP_User or the WP_Error object.
2315 * @param string $username The inputted, attempted username.
2316 * @param string $password The inputted, attempted password.
2317 * @return WP_User|WP_Error
2318 */
2319function bp_core_signup_disable_inactive( $user = null, $username = '', $password ='' ) {
2320 // Login form not used.
2321 if ( empty( $username ) && empty( $password ) ) {
2322 return $user;
2323 }
2324
2325 // An existing WP_User with a user_status of 2 is either a legacy
2326 // signup, or is a user created for backward compatibility. See
2327 // {@link bp_core_signup_user()} for more details.
2328 if ( is_a( $user, 'WP_User' ) && 2 == $user->user_status ) {
2329 $user_login = $user->user_login;
2330
2331 // If no WP_User is found corresponding to the username, this
2332 // is a potential signup.
2333 } elseif ( is_wp_error( $user ) && 'invalid_username' == $user->get_error_code() ) {
2334 $user_login = $username;
2335
2336 // This is an activated user, so bail.
2337 } else {
2338 return $user;
2339 }
2340
2341 // Look for the unactivated signup corresponding to the login name.
2342 $signup = BP_Signup::get( array( 'user_login' => sanitize_user( $user_login ) ) );
2343
2344 // No signup or more than one, something is wrong. Let's bail.
2345 if ( empty( $signup['signups'][0] ) || $signup['total'] > 1 ) {
2346 return $user;
2347 }
2348
2349 // Unactivated user account found!
2350 // Set up the feedback message.
2351 $signup_id = $signup['signups'][0]->signup_id;
2352
2353 $resend_url_params = array(
2354 'action' => 'bp-resend-activation',
2355 'id' => $signup_id,
2356 );
2357
2358 $resend_url = wp_nonce_url(
2359 add_query_arg( $resend_url_params, wp_login_url() ),
2360 'bp-resend-activation'
2361 );
2362
2363 $resend_string = '<br /><br />' . sprintf( __( 'If you have not received an email yet, <a href="%s">click here to resend it</a>.', 'buddypress' ), esc_url( $resend_url ) );
2364
2365 return new WP_Error( 'bp_account_not_activated', __( '<strong>ERROR</strong>: Your account has not been activated. Check your email for the activation link.', 'buddypress' ) . $resend_string );
2366}
2367add_filter( 'authenticate', 'bp_core_signup_disable_inactive', 30, 3 );
2368
2369/**
2370 * On the login screen, resends the activation email for a user.
2371 *
2372 * @since 2.0.0
2373 *
2374 * @see bp_core_signup_disable_inactive()
2375 */
2376function bp_members_login_resend_activation_email() {
2377 global $error;
2378
2379 if ( empty( $_GET['id'] ) || empty( $_GET['_wpnonce'] ) ) {
2380 return;
2381 }
2382
2383 // Verify nonce.
2384 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'bp-resend-activation' ) ) {
2385 die( 'Security check' );
2386 }
2387
2388 $signup_id = (int) $_GET['id'];
2389
2390 // Resend the activation email.
2391 // also updates the 'last sent' and '# of emails sent' values.
2392 $resend = BP_Signup::resend( array( $signup_id ) );
2393
2394 // Add feedback message.
2395 if ( ! empty( $resend['errors'] ) ) {
2396 $error = __( '<strong>ERROR</strong>: Your account has already been activated.', 'buddypress' );
2397 } else {
2398 $error = __( 'Activation email resent! Please check your inbox or spam folder.', 'buddypress' );
2399 }
2400}
2401add_action( 'login_form_bp-resend-activation', 'bp_members_login_resend_activation_email' );
2402
2403/**
2404 * Redirect away from wp-signup.php if BP registration templates are present.
2405 *
2406 * @since 1.1.0
2407 */
2408function bp_core_wpsignup_redirect() {
2409
2410 // Bail in admin or if custom signup page is broken.
2411 if ( is_admin() || ! bp_has_custom_signup_page() ) {
2412 return;
2413 }
2414
2415 $action = !empty( $_GET['action'] ) ? $_GET['action'] : '';
2416
2417 // Not at the WP core signup page and action is not register.
2418 if ( ! empty( $_SERVER['SCRIPT_NAME'] ) && false === strpos( 'wp-signup.php', $_SERVER['SCRIPT_NAME'] ) && ( 'register' != $action ) ) {
2419 return;
2420 }
2421
2422 bp_core_redirect( bp_get_signup_page() );
2423}
2424add_action( 'bp_init', 'bp_core_wpsignup_redirect' );
2425
2426/**
2427 * Stop a logged-in user who is marked as a spammer.
2428 *
2429 * When an admin marks a live user as a spammer, that user can still surf
2430 * around and cause havoc on the site until that person is logged out.
2431 *
2432 * This code checks to see if a logged-in user is marked as a spammer. If so,
2433 * we redirect the user back to wp-login.php with the 'reauth' parameter.
2434 *
2435 * This clears the logged-in spammer's cookies and will ask the spammer to
2436 * reauthenticate.
2437 *
2438 * Note: A spammer cannot log back in - {@see bp_core_boot_spammer()}.
2439 *
2440 * Runs on 'bp_init' at priority 5 so the members component globals are setup
2441 * before we do our spammer checks.
2442 *
2443 * This is important as the $bp->loggedin_user object is setup at priority 4.
2444 *
2445 * @since 1.8.0
2446 */
2447function bp_stop_live_spammer() {
2448 // If we're on the login page, stop now to prevent redirect loop.
2449 $is_login = false;
2450 if ( isset( $GLOBALS['pagenow'] ) && ( false !== strpos( $GLOBALS['pagenow'], 'wp-login.php' ) ) ) {
2451 $is_login = true;
2452 } elseif ( isset( $_SERVER['SCRIPT_NAME'] ) && false !== strpos( $_SERVER['SCRIPT_NAME'], 'wp-login.php' ) ) {
2453 $is_login = true;
2454 }
2455
2456 if ( $is_login ) {
2457 return;
2458 }
2459
2460 // User isn't logged in, so stop!
2461 if ( ! is_user_logged_in() ) {
2462 return;
2463 }
2464
2465 // If spammer, redirect to wp-login.php and reauthorize.
2466 if ( bp_is_user_spammer( bp_loggedin_user_id() ) ) {
2467 // Setup login args.
2468 $args = array(
2469 // Custom action used to throw an error message.
2470 'action' => 'bp-spam',
2471
2472 // Reauthorize user to login.
2473 'reauth' => 1
2474 );
2475
2476 /**
2477 * Filters the url used for redirection for a logged in user marked as spam.
2478 *
2479 * @since 1.8.0
2480 *
2481 * @param string $value URL to redirect user to.
2482 */
2483 $login_url = apply_filters( 'bp_live_spammer_redirect', add_query_arg( $args, wp_login_url() ) );
2484
2485 // Redirect user to login page.
2486 wp_redirect( $login_url );
2487 die();
2488 }
2489}
2490add_action( 'bp_init', 'bp_stop_live_spammer', 5 );
2491
2492/**
2493 * Show a custom error message when a logged-in user is marked as a spammer.
2494 *
2495 * @since 1.8.0
2496 */
2497function bp_live_spammer_login_error() {
2498 global $error;
2499
2500 $error = __( '<strong>ERROR</strong>: Your account has been marked as a spammer.', 'buddypress' );
2501
2502 // Shake shake shake!
2503 add_action( 'login_head', 'wp_shake_js', 12 );
2504}
2505add_action( 'login_form_bp-spam', 'bp_live_spammer_login_error' );
2506
2507/**
2508 * Get the displayed user Object
2509 *
2510 * @since 2.6.0
2511 *
2512 * @return object The displayed user object, null otherwise.
2513 */
2514function bp_get_displayed_user() {
2515 $bp = buddypress();
2516
2517 $displayed_user = null;
2518 if ( ! empty( $bp->displayed_user->id ) ) {
2519 $displayed_user = $bp->displayed_user;
2520 }
2521
2522 /**
2523 * Filters the displayed_user object corresponding to the displayed member.
2524 *
2525 * @since 2.6.0
2526 *
2527 * @param object $displayed_user The displayed_user object.
2528 */
2529 return apply_filters( 'bp_get_displayed_user', $displayed_user );
2530}
2531
2532/** Member Types *************************************************************/
2533
2534/**
2535 * Output the slug of the member type taxonomy.
2536 *
2537 * @since 2.7.0
2538 */
2539function bp_member_type_tax_name() {
2540 echo bp_get_member_type_tax_name();
2541}
2542
2543 /**
2544 * Return the slug of the member type taxonomy.
2545 *
2546 * @since 2.7.0
2547 *
2548 * @return string The unique member taxonomy slug.
2549 */
2550 function bp_get_member_type_tax_name() {
2551 /**
2552 * Filters the slug of the member type taxonomy.
2553 *
2554 * @since 2.7.0
2555 *
2556 * @param string $value Member type taxonomy slug.
2557 */
2558 return apply_filters( 'bp_get_member_type_tax_name', 'bp_member_type' );
2559 }
2560
2561/**
2562 * Register a member type.
2563 *
2564 * @since 2.2.0
2565 *
2566 * @param string $member_type Unique string identifier for the member type.
2567 * @param array $args {
2568 * Array of arguments describing the member type.
2569 *
2570 * @type array $labels {
2571 * Array of labels to use in various parts of the interface.
2572 *
2573 * @type string $name Default name. Should typically be plural.
2574 * @type string $singular_name Singular name.
2575 * }
2576 * @type bool|string $has_directory Whether the member type should have its own type-specific directory.
2577 * Pass `true` to use the `$member_type` string as the type's slug.
2578 * Pass a string to customize the slug. Pass `false` to disable.
2579 * Default: true.
2580 * }
2581 * @return object|WP_Error Member type object on success, WP_Error object on failure.
2582 */
2583function bp_register_member_type( $member_type, $args = array() ) {
2584 $bp = buddypress();
2585
2586 if ( isset( $bp->members->types[ $member_type ] ) ) {
2587 return new WP_Error( 'bp_member_type_exists', __( 'Member type already exists.', 'buddypress' ), $member_type );
2588 }
2589
2590 $r = bp_parse_args( $args, array(
2591 'labels' => array(),
2592 'has_directory' => true,
2593 ), 'register_member_type' );
2594
2595 $member_type = sanitize_key( $member_type );
2596
2597 /**
2598 * Filters the list of illegal member type names.
2599 *
2600 * - 'any' is a special pseudo-type, representing items unassociated with any member type.
2601 * - 'null' is a special pseudo-type, representing users without any type.
2602 * - '_none' is used internally to denote an item that should not apply to any member types.
2603 *
2604 * @since 2.4.0
2605 *
2606 * @param array $illegal_names Array of illegal names.
2607 */
2608 $illegal_names = apply_filters( 'bp_member_type_illegal_names', array( 'any', 'null', '_none' ) );
2609 if ( in_array( $member_type, $illegal_names, true ) ) {
2610 return new WP_Error( 'bp_member_type_illegal_name', __( 'You may not register a member type with this name.', 'buddypress' ), $member_type );
2611 }
2612
2613 // Store the post type name as data in the object (not just as the array key).
2614 $r['name'] = $member_type;
2615
2616 // Make sure the relevant labels have been filled in.
2617 $default_name = isset( $r['labels']['name'] ) ? $r['labels']['name'] : ucfirst( $r['name'] );
2618 $r['labels'] = array_merge( array(
2619 'name' => $default_name,
2620 'singular_name' => $default_name,
2621 ), $r['labels'] );
2622
2623 // Directory slug.
2624 if ( $r['has_directory'] ) {
2625 // A string value is intepreted as the directory slug. Otherwise fall back on member type.
2626 if ( is_string( $r['has_directory'] ) ) {
2627 $directory_slug = $r['has_directory'];
2628 } else {
2629 $directory_slug = $member_type;
2630 }
2631
2632 // Sanitize for use in URLs.
2633 $r['directory_slug'] = sanitize_title( $directory_slug );
2634 $r['has_directory'] = true;
2635 } else {
2636 $r['directory_slug'] = '';
2637 $r['has_directory'] = false;
2638 }
2639
2640 $bp->members->types[ $member_type ] = $type = (object) $r;
2641
2642 /**
2643 * Fires after a member type is registered.
2644 *
2645 * @since 2.2.0
2646 *
2647 * @param string $member_type Member type identifier.
2648 * @param object $type Member type object.
2649 */
2650 do_action( 'bp_registered_member_type', $member_type, $type );
2651
2652 return $type;
2653}
2654
2655/**
2656 * Retrieve a member type object by name.
2657 *
2658 * @since 2.2.0
2659 *
2660 * @param string $member_type The name of the member type.
2661 * @return object A member type object.
2662 */
2663function bp_get_member_type_object( $member_type ) {
2664 $types = bp_get_member_types( array(), 'objects' );
2665
2666 if ( empty( $types[ $member_type ] ) ) {
2667 return null;
2668 }
2669
2670 return $types[ $member_type ];
2671}
2672
2673/**
2674 * Get a list of all registered member type objects.
2675 *
2676 * @since 2.2.0
2677 *
2678 * @see bp_register_member_type() for accepted arguments.
2679 *
2680 * @param array|string $args Optional. An array of key => value arguments to match against
2681 * the member type objects. Default empty array.
2682 * @param string $output Optional. The type of output to return. Accepts 'names'
2683 * or 'objects'. Default 'names'.
2684 * @param string $operator Optional. The logical operation to perform. 'or' means only one
2685 * element from the array needs to match; 'and' means all elements
2686 * must match. Accepts 'or' or 'and'. Default 'and'.
2687 * @return array A list of member type names or objects.
2688 */
2689function bp_get_member_types( $args = array(), $output = 'names', $operator = 'and' ) {
2690 $types = buddypress()->members->types;
2691
2692 $types = wp_filter_object_list( $types, $args, $operator );
2693
2694 /**
2695 * Filters the array of member type objects.
2696 *
2697 * This filter is run before the $output filter has been applied, so that
2698 * filtering functions have access to the entire member type objects.
2699 *
2700 * @since 2.2.0
2701 *
2702 * @param array $types Member type objects, keyed by name.
2703 * @param array $args Array of key=>value arguments for filtering.
2704 * @param string $operator 'or' to match any of $args, 'and' to require all.
2705 */
2706 $types = apply_filters( 'bp_get_member_types', $types, $args, $operator );
2707
2708 if ( 'names' === $output ) {
2709 $types = wp_list_pluck( $types, 'name' );
2710 }
2711
2712 return $types;
2713}
2714
2715/**
2716 * Set type for a member.
2717 *
2718 * @since 2.2.0
2719 *
2720 * @param int $user_id ID of the user.
2721 * @param string $member_type Member type.
2722 * @param bool $append Optional. True to append this to existing types for user,
2723 * false to replace. Default: false.
2724 * @return false|array $retval See {@see bp_set_object_terms()}.
2725 */
2726function bp_set_member_type( $user_id, $member_type, $append = false ) {
2727 // Pass an empty $member_type to remove a user's type.
2728 if ( ! empty( $member_type ) && ! bp_get_member_type_object( $member_type ) ) {
2729 return false;
2730 }
2731
2732 $retval = bp_set_object_terms( $user_id, $member_type, bp_get_member_type_tax_name(), $append );
2733
2734 // Bust the cache if the type has been updated.
2735 if ( ! is_wp_error( $retval ) ) {
2736 wp_cache_delete( $user_id, 'bp_member_member_type' );
2737
2738 /**
2739 * Fires just after a user's member type has been changed.
2740 *
2741 * @since 2.2.0
2742 *
2743 * @param int $user_id ID of the user whose member type has been updated.
2744 * @param string $member_type Member type.
2745 * @param bool $append Whether the type is being appended to existing types.
2746 */
2747 do_action( 'bp_set_member_type', $user_id, $member_type, $append );
2748 }
2749
2750 return $retval;
2751}
2752
2753/**
2754 * Remove type for a member.
2755 *
2756 * @since 2.3.0
2757 *
2758 * @param int $user_id ID of the user.
2759 * @param string $member_type Member Type.
2760 * @return bool|WP_Error
2761 */
2762function bp_remove_member_type( $user_id, $member_type ) {
2763 // Bail if no valid member type was passed.
2764 if ( empty( $member_type ) || ! bp_get_member_type_object( $member_type ) ) {
2765 return false;
2766 }
2767
2768 $deleted = bp_remove_object_terms( $user_id, $member_type, bp_get_member_type_tax_name() );
2769
2770 // Bust the cache if the type has been removed.
2771 if ( ! is_wp_error( $deleted ) ) {
2772 wp_cache_delete( $user_id, 'bp_member_member_type' );
2773
2774 /**
2775 * Fires just after a user's member type has been removed.
2776 *
2777 * @since 2.3.0
2778 *
2779 * @param int $user_id ID of the user whose member type has been updated.
2780 * @param string $member_type Member type.
2781 */
2782 do_action( 'bp_remove_member_type', $user_id, $member_type );
2783 }
2784
2785 return $deleted;
2786}
2787
2788/**
2789 * Get type for a member.
2790 *
2791 * @since 2.2.0
2792 *
2793 * @param int $user_id ID of the user.
2794 * @param bool $single Optional. Whether to return a single type string. If multiple types are found
2795 * for the user, the oldest one will be returned. Default: true.
2796 * @return string|array|bool On success, returns a single member type (if $single is true) or an array of member
2797 * types (if $single is false). Returns false on failure.
2798 */
2799function bp_get_member_type( $user_id, $single = true ) {
2800 $types = wp_cache_get( $user_id, 'bp_member_member_type' );
2801
2802 if ( false === $types ) {
2803 $raw_types = bp_get_object_terms( $user_id, bp_get_member_type_tax_name() );
2804
2805 if ( ! is_wp_error( $raw_types ) ) {
2806 $types = array();
2807
2808 // Only include currently registered group types.
2809 foreach ( $raw_types as $mtype ) {
2810 if ( bp_get_member_type_object( $mtype->name ) ) {
2811 $types[] = $mtype->name;
2812 }
2813 }
2814
2815 wp_cache_set( $user_id, $types, 'bp_member_member_type' );
2816 }
2817 }
2818
2819 $type = false;
2820 if ( ! empty( $types ) ) {
2821 if ( $single ) {
2822 $type = array_pop( $types );
2823 } else {
2824 $type = $types;
2825 }
2826 }
2827
2828 /**
2829 * Filters a user's member type(s).
2830 *
2831 * @since 2.2.0
2832 *
2833 * @param string $type Member type.
2834 * @param int $user_id ID of the user.
2835 * @param bool $single Whether to return a single type string, or an array.
2836 */
2837 return apply_filters( 'bp_get_member_type', $type, $user_id, $single );
2838}
2839
2840/**
2841 * Check whether the given user has a certain member type.
2842 *
2843 * @since 2.3.0
2844 *
2845 * @param int $user_id $user_id ID of the user.
2846 * @param string $member_type Member Type.
2847 * @return bool Whether the user has the given member type.
2848 */
2849function bp_has_member_type( $user_id, $member_type ) {
2850 // Bail if no valid member type was passed.
2851 if ( empty( $member_type ) || ! bp_get_member_type_object( $member_type ) ) {
2852 return false;
2853 }
2854
2855 // Get all user's member types.
2856 $types = bp_get_member_type( $user_id, false );
2857
2858 if ( ! is_array( $types ) ) {
2859 return false;
2860 }
2861
2862 return in_array( $member_type, $types );
2863}
2864
2865/**
2866 * Delete a user's member type when the user when the user is deleted.
2867 *
2868 * @since 2.2.0
2869 *
2870 * @param int $user_id ID of the user.
2871 * @return false|array $value See {@see bp_set_member_type()}.
2872 */
2873function bp_remove_member_type_on_user_delete( $user_id ) {
2874 return bp_set_member_type( $user_id, '' );
2875}
2876add_action( 'wpmu_delete_user', 'bp_remove_member_type_on_user_delete' );
2877add_action( 'delete_user', 'bp_remove_member_type_on_user_delete' );
2878
2879/**
2880 * Get the "current" member type, if one is provided, in member directories.
2881 *
2882 * @since 2.3.0
2883 *
2884 * @return string
2885 */
2886function bp_get_current_member_type() {
2887
2888 /**
2889 * Filters the "current" member type, if one is provided, in member directories.
2890 *
2891 * @since 2.3.0
2892 *
2893 * @param string $value "Current" member type.
2894 */
2895 return apply_filters( 'bp_get_current_member_type', buddypress()->current_member_type );
2896}