Extending BuddyPress profile field visibility
BuddyPress profile field visibility allows users on a BuddyPress based social site to change the visibility of individual profile field data. It controls who can see a profile filed data of the user.
Default Visibility Levels:-
By default, BuddyPress provides four visibility levels:-
- Everyone:- Anyone can see the data.
- Only Me:- Only the user and the site admin can see the data
- All Members:- Anyone logged into the site can see the data
- My Friends:- This visibility level is only available if the Friends component is enabled. A user can mark the filed only visible t his/her friends.
Today, In this tutorial, we will learn how to add new profile field visibility level as well as how to remove existing visibility levels.
It is a long tutorial, If you are looking for the code, you can directly head to github and download it from the below link.
https://github.com/buddydev/extended-xprofile-field-visibility-levels
If you are here, I promise you are going to learn a lot. I will illustrate the tutorial with the help of an example that creates a new privacy level "My Group Members". A field marked as My Group Members will be only visible to users who have at least 1 common group with this user.
BuddyPress provides a hook 'bp_xprofile_get_visibility_levels' that allows us to add new privacy level. Any function that is hooked to this filter can add a new visibility level or remove any existing level.
Here is an example syntax.
1 | add_filter( 'bp_xprofile_get_visibility_levels', 'buddydev_customize_profile_visibility' ); |
In the above code, we have hooked 'buddydev_customize_profile_visibility' to the filter. Now, let us see an implementation of the 'buddydev_customize_profile_visibility' function.
1 2 3 4 5 6 7 8 9 | function buddydev_customize_profile_visibility( $allowed_visibilities ) { //add new visibility //remove some visibility //return the modified visibility levels return $allowed_visibilities; } |
A sample implementation will look like the above. The hooked function gets all the existing visibility levels as a multi dimensional associative array as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /** * By default, $allowed_visibilities is an associative array of visibility level key and values like this * */ array( 'public' => array( 'id' => 'public', 'label' => _x( 'Everyone', 'Visibility level setting', 'buddypress' ) ), 'adminsonly' => array( 'id' => 'adminsonly', 'label' => _x( 'Only Me', 'Visibility level setting', 'buddypress' ) ), 'loggedin' => array( 'id' => 'loggedin', 'label' => _x( 'All Members', 'Visibility level setting', 'buddypress' ) ), 'friends' => array( 'id' => 'friends', 'label' => _x( 'My Friends', 'Visibility level setting', 'buddypress' ) ) ); |
As you can see, the keys public, adminsonly, loggedin, friends are used to identify each of the existing visibility level.
Removing Existing Visibility Level:-
In case you want to remove an existing visibility level, you can use
1 | unset( $allowed_visibilities[IDENTIFIER KEY OF THE VISIBILITY LEVEL] ); |
Where the Identifier key can be one of the following:-
- public
- adminsonly
- loggedin
- friends
Let us see a real example, to unset the My Friends visibility level, we can use the following code inside our function.
1 | unset( $allowed_visibilities['friends'] ); |
Once you do that you will see that the My Friends visibility is gone as shown in the screenshot below.
Adding a New Visibility Level:-
Building upon our previous example, we already know that a new privacy level can be added with a new key and It's levels. Let us add My Group Members to the visibility lebel.
1 2 3 4 5 6 7 8 | if( bp_is_active( 'groups' ) ) { $allowed_visibilities['groups'] = array( 'id' => 'groups', 'label' => _x( 'My Group Members', 'Visibility level setting', 'bp-extended-profile-visibility' ) ); } |
In the above code, we are testing if the groups component is enabled and if yes, we add the new privacy level. I hope that the example makes it clear what we are doing. After putting this code, you can check that the new Visibility level is added as shown in the screenshot below.
And here is the complete implementation of the hooked function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | /** * Filter visibility level and add/remove the visibility levels */ add_filter( 'bp_xprofile_get_visibility_levels', 'buddydev_customize_profile_visibility' ); function buddydev_customize_profile_visibility( $allowed_visibilities ) { /** * By default, $allowed_visibilities is an associative array of visibility level key and values like this * */ /* array( 'public' => array( 'id' => 'public', 'label' => _x( 'Everyone', 'Visibility level setting', 'buddypress' ) ), 'adminsonly' => array( 'id' => 'adminsonly', 'label' => _x( 'Only Me', 'Visibility level setting', 'buddypress' ) ), 'loggedin' => array( 'id' => 'loggedin', 'label' => _x( 'All Members', 'Visibility level setting', 'buddypress' ) ), 'friends' => array( 'id' => 'friends', 'label' => _x( 'My Friends', 'Visibility level setting', 'buddypress' ) ) ); */ //as you can see the keys, that's public|adminsonly|loggedin|friends //if you want to remove an existing privacy level, //just unset the key //no more friends privacy //unset( $allowed_visibilities['friends'] ); //add a custom visibility //let us add a groups only if( bp_is_active( 'groups' ) ) { $allowed_visibilities['groups'] = array( 'id' => 'groups', 'label' => _x( 'My Group Members', 'Visibility level setting', 'bp-extended-profile-visibility' ) ); } return $allowed_visibilities; } |
But wait, that's not all. Till now, we have told BuddyPress that please add this new privacy level but we have not specified how the visibility will actually contol the data. In other words, we need to tell BuddyPress when to hide a field with our new visibility and when to show it.
BuddyPress provides another hook for the purpose. We will use 'bp_xprofile_get_hidden_field_types_for_user' to tell BuddyPress when to hide our field data. Please don't get fooled by the name of the hook, It is not about profile field types, It is about profile field visibility and a better name should have been 'bp_xprofile_get_hidden_field_visibility_levels_for_user'. But that is not our job, so let us use 'bp_xprofile_get_hidden_field_types_for_user' and hook a function to tell BuddyPress when the fields with 'groups' visibility be hidden.
Here is what we want to accomplish:-
- If the profile data is fetched for the logged in user, we should not restrict as he/she is the owner of the profile
- If the logged in user is super admin, do not hide
- If the logged in user is having a common group with the user whose profile data is being fetched, then do not hide it
- In all other cases, just hide it.
Here is a code to do that for groups privacy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | add_filter( 'bp_xprofile_get_hidden_field_types_for_user', 'buddydev_get_hidden_visibility_types_for_user', 10, 3 ); function buddydev_get_hidden_visibility_types_for_user( $hidden_levels, $displayed_user_id, $current_user_id ) { //if it is not my data and super admin is not viewing and there are no common groups, then hide if( ( $displayed_user_id != $current_user_id ) && ! buddydev_user_has_common_group( $displayed_user_id, $current_user_id ) && ! is_super_admin() ) { $hidden_levels[] = 'groups'; //profile field with this privacy level will be hidden for the user } return $hidden_levels; } |
That does it. As you might have noticed, I have used a function 'buddydev_user_has_common_group' which does not exist yet. Well, BuddyPress does not provide a built in way to find common groups of two users, so we will write our own to find this. I have broken the code into two functions, so if you want, you can use a part of it to fetch common groups between any user.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | /** * Check if there are any common groups between these two users * * @param int $user_id * @param int $other_id * @return boolean true if ye, else false */ function buddydev_user_has_common_group( $user_id, $other_id ) { $common_groups = buddydev_get_common_groups( $user_id, $other_id ); if( ! empty( $common_groups ) ) return true; return false; } /** * Get all the common groups between these two users * * @global type $wpdb * @param int $user_id * @param int $other_id * @return mixed array of group ids */ function buddydev_get_common_groups( $user_id, $other_id ) { global $wpdb; //members table $table = buddypress()->groups->table_name_members; $query_user_groups = $wpdb->prepare( "SELECT group_id FROM {$table} WHERE user_id = %d AND is_confirmed = %d ", $user_id, 1 ); $query_other_user_groups = $wpdb->prepare( "SELECT group_id FROM {$table} WHERE user_id = %d AND is_confirmed = %d ", $other_id, 1 ); //should we put a LIMIT clause too, I am not putting as someone may find this function useful for other purposes $commpon_groups = $wpdb->get_col( "{$query_user_groups} AND group_id IN ({$query_other_user_groups})" ); return $commpon_groups; } |
Everything is setup and you can have some fun testing it. Yo can put the above code in your bp-custom.php
Here is the list of interesting things you can do with the knowledge you earned today.
- A visibility level for Sent Pending Friendship Request:- Allow users to make some fields visibility only to the members whom they have sent request( Like Friends + Users whom the profile user sent requst)
- Followers only visibility
- Following Only visibility
- Gender based visibility ( I have a lot to talk about this in our upcoming posts).
- and what ever you can think.
If you want me to add any specific visibility to the sample plugin, Please let me know your suggestions. I am looking forward to your thoughts, suggestions and criticism all in the comments below.
Happy social networking 🙂
Hello,
I just wanted to say thanks for this code. I was specifically interested in the 'common groups' part that you added. Very nice. I tested it on my dev site and it works great. Now I'll look to add to our live site.
Thanks.
Thank you Mitch 🙂
I am glad that it helped.
Hello,
Thank you for this inspiring piece of code. We need to hide various x-profile fields for a 2 user roles. Could you tell me if this is possible with this code. We tried but failed up to now
Hi Michael,
can you please link me to the code(pastebin/github). Yes, It will allow you to work with roles . I have even done the same for one of my clients for specific member types.
Hello! I would love to see how to establish a privacy level to work with user "Types" or roles. Any help great appreciated!
Any luck with this "privacy level to work with user “Types” or roles"
Hi Brajesh,
I'm a real Dummy at PHP programming. To be honest i'm more of a code copymaster 😉
So I tried some copying and pasting of code.
And after a couple of days and headaches something came out that really seems to work.
But since it's for a real website (and i'm the Dummy) I was wondering if you could take a look at https://github.com/IChess1/WPI/tree/master.
I've put your code there with my added code in it.
What do you think?
Hi Michael,
your code is perfectly fine 🙂
Worked beautifully, thank you!!
Thank you for the comment and confirming 🙂
Any update on Gender based visibility ( I have a lot to talk about this in our upcoming posts).
Some of my visitors want to hide some of their fields from males, is it possible.?
This is great! I'm a novice at this, and this was hoping you could help me understand how to customize this to add a visibility specification for a certain buddypress group. Thanks!
Hi Marshal,
Please post in our forums and we will help.
Thank you.
Is there a plugin that does this? This functionality is quite important to me.
Hi Michael,
Thank you for asking.
The above code is available in the form of a plugin(It is an example plugin) from here
https://github.com/buddydev/extended-xprofile-field-visibility-levels
If you are looking for something else, please do post in our forums.
Thank you.