Pro Sites - BuddyPress - Restrict Access to Features

I am using Pro Sites and BuddyPress. How can I limit access to the features on BuddyPress (forums, groups, messaging, etc.) based upon the Pro level?

Thanks,
Chris

    aristath

    Hello there @Chris, I hope you're well today!

    This will have to be custom-coded in your template files or a custom plugin that you will create.
    You can detect the pro-sites level of the current site with this snippet:

    <?php
    global $wpdb;
    $blog_id = $wpdb->blogid;
    $sql = "SELECT level FROM {$wpdb->base_prefix}pro_sites WHERE blog_ID = '$blog_id'";
    $level = $wpdb->get_var($sql);
    ?>
    <?php if ($level == 1){ ?>
    	Level 1 content here
    <?php } ?>
    <?php if ($level == 2) { ?>
    	Level 2 content here
    <?php } ?>
    <?php if ($level == 3) { ?>
    	Level 3 content here
    <?php } ?>

    hope tht helps!

    Cheers,
    Ari.

    Chris

    Hi Ari,

    Thanks for this code. Would a simpler solution be to use Pro Sites w/ Membership? I see a lot of posts about these two, but I haven't seen one that explains how to accomplish what I need - nor any step-by-step guides to integrate these to plugins. Some responses in the forums make it sound like features of Pro Sites can be used with Membership, but I don't see the possibility if they don't integrate. I'll state my needs below, along with a few questions.

    Goal:
    To offer membership levels that a) protected content (pages, forums, and groups) and b) offer paid blogging.

    Must Have:
    1. One payment gateway / one account per user.
    2. Protected content on main site.
    3. Everything is automated, no manual intervention by super admin.
    4. When the membership expires, the protected content and the subdomain site's backend become restricted until payment is made.

    Question 1: Can either Membership or Pro Sites individually handle all of these 'Must Have' requirements? If not, which would handle most with only minimal coding?

    Nice To Have:
    A 'free' membership level - free blog w/ limited disk space, ads served by super admin, and limited access to protected content. When the user pays for a higher level, they have access to more content, ads are removed, and plugins, themes, quotas are increased.

    Question 2: Considering the 'Must Have's above, which of these 'Nice to Have's can be accomplished, and which should I consider dropping to make this project happen with limited coding?

    Additional Questions
    3. Am I better off using both Membership and Pro Sites together to accomplish the items above? Or, am I better off using one plugin with some custom coding?
    4. If this can be accomplished with both Membership and Pro Sites, what steps should I take to integrate them to achieve the above?
    5. Is there an order in which they should be installed? I already have Pro Sites + BuddyPress + bbPress installed.

    Thanks,
    Chris

    aristath

    Hello there @Chris, I hope you're well today!

    Pro-Sites can handle almost everything on your list except the conten protection
    My advise would be to use Pro-Sites with some custom coding.

    I just wrote this function that you will need:

    <?php
    
    function ari_prosites_maxlevel( $user ) {
    
    	//is there a user to check?
    	global $user, $wpdb;
    
    	if ( $user ) {
    		$user_id = $user->ID;
    	}
    
    	$blog_id = $wpdb->blogid;
    
    	// No need t proceed if no user
    	if ( ! isset( $user_id ) ) {
    		return;
    	}
    
    	// Get the email of the current user
    	$user_email = $user->user_email;
    
    	// Get the blogs of this user
    	$user_blogs = get_blogs_of_user( $user_id );
    
    	foreach ( $user_blogs as $user_blog ) {
    
    		// user_site_ids is an array because the user can have multiple sites
    		$user_site_ids = array();
    
    		// Get the ID of the blog
    		$blog_id = $user_blog->userblog_id;
    		// Switch to the blog
    		switch_to_blog( $blog_id );
    		// Retrieve the e-mail of the blog administrator
    		$admin_email = get_option( 'admin_email' );
    
    		// Check if the current user is the admin of that blog
    		if ( $admin_email == $user_email ) {
    			// Add this site to the $user_site_ids array
    			$user_site_ids[] = $blog_id;
    		}
    		restore_current_blog();
    
        }
    
        if ( ! empty( $user_site_ids ) ) {
    
        	foreach ( $user_site_ids as $user_site_id ) {
    
        		$sql = "SELECT level FROM {$wpdb->base_prefix}pro_sites WHERE blog_ID = '$user_site_id'";
        		$level = $wpdb->get_var( $sql );
    
        		if ( ! isset( $max_level ) ) {
        			// There is no other level defined, so set this one as max
        			$max_level = $level;
        		} else {
        			// If the current level is greater than the already defined $max_level
        			// change $max_level to $level and proceed.
        			$max_level = ( $level > $max_level ) ? $level : $max_level;
        		}
    
            }
    
        }
    
        return ( isset( $max_level ) ) ? $max_level : false;
    
    }

    You can put that in a php file in your mu-plugins folder so it will be available to all sites.
    This does the following:
    gets all the sites of the current member, checks on which sites the user is an admin, and then returns the maximum pro-sites level of these site.

    So if you then need to use thet number somewhere you can simpl call this function like this

    <?php 
    
    $current_user = wp_get_current_user();
    $max_level = ari_prosites_maxlevel( $current_user );

    You can use that to further allow or limit access to your content using native WordPress functions.

    I hope that helps!

    Cheers,
    Ari.

    Chris

    Hi Ari,

    Unfortunately, I am still having a problem. I am not sure how the plugin handles expirations. It seems that after an account has expired, the level doesn't change ... or at least it doesn't change immediately. Is there a grace period built into the plugin? I will break down my actions below:

    Step 1 - I have been manually changing the expiration. The account I'm testing initially started with a trial period. I entered the db and changed the timestamp to expire in one minute. It expired, but the restriction didn't work as expected. The user still had access to the restricted content. Is that b/c it's only looking at the 'level' (which didn't change)?

    Step 2 - After experimenting with the timestamp (further extending the expiration date to three days), the system seemed to clear out the account. This removed access (which is why I deduce there is a grace period). However, this refutes my logic about the level being the culprit b/c level didn't change and the account was restricted. Was this just a coincidence?

    Step 3 - I then increased the membership through the admin dashboard and extended it by one day. The user was not provided with access. As you can see, this doesn't work as expected. So, I can only assume I'm missing some important piece to how the plugin works.

    Am I correct in assuming that we should be looking at expiration, and not level? Or, is there some action that the plugin takes that I'm not taking into account?

    Please see the code below that I've cobbled together. I'm not a programmer, so I won't be surprised if there are errors with it. However, it may provide a starting point:

    function prosites_hide_buddypress_uri()
    {
    
    	$current_user = wp_get_current_user();
    	$max_level = ari_prosites_maxlevel( $current_user );
    	$uri = $_SERVER['REQUEST_URI'];
    	$not_allowed = array("/^\/members\/$/", "/tutorials\/*/", "/friends\/*/", "/^\/groups\/$/", "/\/groups\/create\//", "/\/site-tracking\/create\//", "/\/members\/[^\/]*\/groups\//", "/\/members\/[^\/]*\/forums\//", "/\/members\/[^\/]*\/settings\//");
    	foreach($not_allowed as $check)
    		{
    		if(preg_match($check, $uri) && $max_level < '1')
    		{
    			wp_redirect(home_url("/upgrade/"));
    			exit;
    		}
    	}
    
    }
    add_action("init", "prosites_hide_buddypress_uri");

     
    Update: In another thread, I was referred to the post below which suggests restriction based upon roles:

    https://premium.wpmudev.org/forums/topic/how-do-i-remove-something-on-all-pages-if-a-user-is-logged-in#post-739176

    My head is swimming. Should I limit access to content by level, role, or expiration? Since you know the plugin, and you know what I'm trying to accomplish, please let me know which you suggest.

    Thanks,
    Chris

    Michelle Shull

    Hi Chris!

    Wow, Ari really went the extra mile for you, that's quite a nice addition to ProSItes he coded up.

    Per this thread: https://premium.wpmudev.org/forums/topic/pro-sites-expiration-grace-period, there may be a grace period built into the current version of Pro Sites, but I'm having trouble confirming it.

    Ultimately, what you decide to target to limit access to content is going to depend on what you want to accomplish, and how you'll be able to tick off the most boxes on your must haves. I think you'll find there are both benefits and drawbacks to each method.

    I think earlier you mentioned including Membership to help you fine tune how you want to control your site access, is that something you're still planning on doing?

    Thanks!

    Chris

    Hi Michelle,

    Yes, Ari definitely provided excellent support. Per his recommendation above, I will use Pro Sites with some custom coding. I would like to keep this as simple as possible - one plugin only.

    Regarding the thread on Grace Periods, I have checked the changelog and don't see anything about it there. Additionally, there isn't an option regarding it in the Settings menu. Given that the feature request for grace periods was suggested four months ago, it's probably unlikely that it's already in the plugin.

    Outstanding Question: Regarding my question about the best metric to use when filtering (level, role, or expiration), it would be great if the plugin developer could provide his/her input:

    1. Best metric to use
    2. Modifications to the codes above would be very helpful
    3. Best way to test the plugin (i.e. I don't want to wait a month for accounts to expire to see what happens). So, a list of considerations and steps needed when manually expiring / upgrading accounts to see if the plugin is performing correctly, and desired content restrictions are in place.
    4. A Feature Request might include a shortcode for these capabilities.

    Thanks,
    Chris

    twmal

    Hi, @Ari

    I have the same issues with Chris , I have 2 level which is Silver and Gold in Prosites. I want Silver level showing the content like 1,3,5 and Gold level will showing content 2,3,6 . But I using WHMCS to handle registration and Payments. Is it that code you have wrote is suitable for my case ? If so should I combine 3 coding you had wrote to mu-plug-in or just using second and third one?

    I have a bit confuse with this code

    <?php

    $current_user = wp_get_current_user();
    $max_level = ari_prosites_maxlevel( $current_user );

    Can you explain further for me about this code ? you said "You can use that to further allow or limit access to your content using native WordPress functions"

    1) How to do that ? Just copy and paste ? If want to limit access for content

    2) Regarding this code do i need to create a new plug in for it ?

    Thanks

    Chris

    After discussing it with Ari in the live help session, it seems that there could be a bug in the software related to the levels. It didn't seem to change the level after expiration.

    So, after thinking it over, I have decided that I want to use the code above to restrict by expiration timestamp. This seems to be a more reliable method that will work whether or not the bug exists/fixed.

    I have made some changes to the code provided, however, I can't get it to work. That shouldn't be a surprise since I don't think I ever got the first code to work . Some simple instructions and help with the code (below) would be greatly appreciated.

    MU Plugin

    <?php
    
    function ari_prosites_maxexpiration( $user ) {
    
    	//is there a user to check?
    	global $user, $wpdb;
    
    	if ( $user ) {
    		$user_id = $user->ID;
    	}
    
    	$blog_id = $wpdb->blogid;
    
    	// No need t proceed if no user
    	if ( ! isset( $user_id ) ) {
    		return;
    	}
    
    	// Get the email of the current user
    	$user_email = $user->user_email;
    
    	// Get the blogs of this user
    	$user_blogs = get_blogs_of_user( $user_id );
    
    	foreach ( $user_blogs as $user_blog ) {
    
    		// user_site_ids is an array because the user can have multiple sites
    		$user_site_ids = array();
    
    		// Get the ID of the blog
    		$blog_id = $user_blog->userblog_id;
    		// Switch to the blog
    		switch_to_blog( $blog_id );
    		// Retrieve the e-mail of the blog administrator
    		$admin_email = get_option( 'admin_email' );
    
    		// Check if the current user is the admin of that blog
    		if ( $admin_email == $user_email ) {
    			// Add this site to the $user_site_ids array
    			$user_site_ids[] = $blog_id;
    		}
    		restore_current_blog();
    
        }
    
        if ( ! empty( $user_site_ids ) ) {
    
        	foreach ( $user_site_ids as $user_site_id ) {
    
        		$sql = "SELECT expire FROM {$wpdb->base_prefix}pro_sites WHERE blog_ID = '$user_site_id'";
        		$expiration = $wpdb->get_var( $sql );
    
        		if ( ! isset( $max_expire ) ) {
        			// There is no other expiration defined, so set this one as max
        			$max_expire = $expiration;
        		} else {
        			// If the current expiration is greater than the already defined $max_expire
        			// change $max_expire to $expiration and proceed.
        			$max_expire = ( $expiration > $max_expire ) ? $expiration : $max_expire;
        		}
    
            }
    
        }
    
        return ( isset( $max_expire ) ) ? $max_expire : false;
    
    }
    
    // HIDE BUDDYPRESS - RESTRICT URI's TO NON-PRO SITE MEMBERS
    
    function prosites_hide_buddypress_uri()
    {
    
    	$current_user = wp_get_current_user();
    	$max_expire = ari_prosites_maxexpiration( $current_user );
    	$uri = $_SERVER['REQUEST_URI'];
    	$not_allowed = array("/^\/members\/$/", "/tutorials\/*/", "/friends\/*/", "/^\/groups\/$/", "/\/groups\/create\//", "/\/site-tracking\/create\//", "/\/members\/[^\/]*\/groups\//", "/\/members\/[^\/]*\/forums\//", "/\/members\/[^\/]*\/settings\//");
    	foreach($not_allowed as $check)
    		{
    		if(preg_match($check, $uri) && ($max_expire < time()))
    		{
    			wp_redirect(home_url("/upgrade/"));
    			exit;
    		}
    	}
    
    }
    add_action("init", "prosites_hide_buddypress_uri");
    Aaron

    First off, the default caution that pro site status is not tied in any way to a user, only a site. So this is hacky at best. There is already included a module for BP. It uses the built in is_pro_user() function.

    If you want to extend any of the functionality, the best bet is to use that is_pro_user() function. However it doesn't account for levels or user roles. So if you need that, you would just have to copy that function and make the mods there to do a WHERE on level as well.

    As to the earlier issues, level is only accurate when it is a pro site (not expired). When expiration is met then the level field means "previous level", it's not changed to 0. Hence the proper way to get a blog's level is $psts->get_level() method.

    Joshua

    I just ran across this topic and I am very interested in this exact thing.

    I have a single site I'd like users to register free for, but not necessarily have their own site. The could have the option to have their own site and once they sign up for the site, they would have access to a restricted section of the main site.

    Just curious if the developers of membership and prosite plugins plan to integrate the two at any point?

    kaitlyn_beth_millet

    I also am wondering if a good option would be to use pro sites and also using user roles plugin which allows you to edit custom user roles and allow them access to certain parts of the site . For instance pro sites from WPMUDEV may be used with the custom user role plugin to show the user role for prob sites members and customize this completely just to make positively sure that certain users can only access certain areas. It has helped me in the past with another site I had.

    Tyler Postle

    Hey Kaitlyn,

    Thanks for chiming in here with your feedback as well

    As Aaron mentioned, since the Pro Site level is linked to the site and not the user, it would be a bit hacky to custom code an integration like that BUT if you planned on manually changing the users roles as they get pro sites levels for certain sites then that would be do-able right out of the box.

    Also, Membership has integration with adding custom user roles to access levels. When you go to setup your access level you can choose the "Advanced" section then select a user role to apply to a user that signs up for that subscription/level

    It would also show your custom user roles in this case too.

    Hope that helps!

    Cheers,
    Tyler

    twmal

    @Jose,

    I still haven't figure it out how to using Ari,s coding to determine the pro site level and switch to other template.
    <?php
    global $wpdb;
    $blog_id = $wpdb->blogid;
    $sql = "SELECT level FROM {$wpdb->base_prefix}pro_sites WHERE blog_ID = '$blog_id'";
    $level = $wpdb->get_var($sql);
    ?>
    <?php if ($level == 1){ ?>
    Level 1 content here
    <?php } ?>
    <?php if ($level == 2) { ?>
    Level 2 content here
    <?php } ?>
    <?php if ($level == 3) { ?>
    Level 3 content here
    <?php } ?>

    I have created a multisite and I using WPMU DEV's ProSites plug in to handle user levels. I have two levels which is Silver and Gold.

    I want my users when they create a site will automatically assign them a specific contents for instance like theme,pages and menu depending the ProSite levels .

    For example the Silver level's menu is about me, join us & contact us etc….. and the pages is 2,4,6.

    Gold level's menu is about feature, about company, join us and the pages is 1,3,5.

    P/s : The theme did not change it doesn't matter(I can using default theme plug in to achieved it ) but the important thing is the contents ( menu and the pages ) ,I want Silver level have the specific Silver level's contents and Gold level have the Gold level's contents. How to determine which level should have which contents.

    Any idea? can u give me some interaction for this?

    Thanks

    twmal

    Hi Aaron,

    Thanks your great instructions ! Thousand thanks for your help!

    <?php if (is_pro_site(false, 1)){ ?>

    switch_to_blog( 44 );
    $template_prefix = $wpdb->prefix;
    restore_current_blog();

    <?php } ?>

    Is it like this ? if Im using New Blog Template to create 2 templates ,so that i can replace the template id for different level (the prefix for the template blog (ID 44) )

    Cheers

    Chris

    Here's the code that is causing problems. It's been added into functions.php via Genesis (custom-functions.php). Can you see what's wrong with it?

    function prosites_hide_buddypress_uri() {
    
    	$userid = get_current_user_id();
    	$uri = $_SERVER['REQUEST_URI'];
    	$not_allowed = array("/^\/members\/$/", "/friends\/*/", "/^\/groups\/*/", "/^\/forums\/*/", "/\/groups\/create\//", "/\/site-tracking\/create\//", "/\/members\/[^\/]*\/groups\//", "/\/members\/[^\/]*\/forums\//", "/\/members\/[^\/]*\/settings\//");
    
    if (!is_pro_user($userid) ) {
    
    		foreach($not_allowed as $check)
    		{
    		if(preg_match($check, $uri))
    		{
    			wp_redirect(home_url("/upgrade/"));
    			exit;
    		}
    	}
    
    }else{
    
    }
    }
    
    add_action("init", "prosites_hide_buddypress_uri");