How are Multiple Roles in Conditionals Handled?

Either S2 is not handling multiple roles correctly or there is an error in my logic.
On a single page I have these 2 content restriction conditionals:

[s2If !current_user_can(access_s2member_level1) AND is_user_logged_in()]...[/s2If]
and
[s2If current_user_is(s2member_level0) AND current_user_can](access_s2member_ccap_bfsupporter) AND !current_user_can(access_s2member_ccap_pi_institution)]...[/s2If]

When a user with both Subscriber and s2Member Level 1 roles visits the page, they see content in both sections. I’m guessing that s2 is treating Subscriber as s2member_level0
Thanks.

I’m interested to hear feedback from the devs, but here is a workaround:

If s2 is equating non-s2 roles with s2member_level0, then s2member_level0 can’t be used for membership check.

Rather than using current_user_is(s2member_level0) to check for current membership, use !current_user_can(access_s2member_level1). In our case, Level1 is the only s2 role we use, so we don’t have to check for other levels.

E.g s2member_level1 is always used for memberships and s2 will detect it if there are multiple roles.

s2Member does indeed behave that way.

IMO that’s a process error in a system where a user can have multiple roles.

No, you misunderstand. They are not multiple roles. They are two labels for a single role.

To clarify: Multiple roles is referring to Multiple WordPress Roles.

I used s2member_level0 to test if someone has membership. That doesn’t work because if someone has any s2 Level and Subscriber, it will still trigger. Would s2member_level0 would be used to test for anything besides membership?

Also, will s2 consider other non-s2 roles as s2member_level0 or only Subscriber?
Thanks.

I am aware of what multiple roles refers to. s2Member actually doesn’t recognize multiple roles. If a person has multiple roles (which is certainly possible with WP), s2Member will only “see” one of them.

The only purpose of s2member_level0 is to make it easier for those not aware of the default WP roles but accustomed to thinking in terms of s2Member roles. Only the default role of subscriber is used this way.

Can you tell me the most efficient way to test if the logged in user has any s2 levels assigned to their account?
Thanks.

You could just look at the users table in the WP admin.

But, if you want to do it programmatically, see https://njengah.com/get-current-user-role-in-wordpress/

If you want to check for users other than the current one, just use get_users to get an array of users and do a foreach to go through each one.

I meant using [s2If]…[/s2If] on a page.

The only option I see is to test for all possible membership levels.

BTW, are you one of the s2 devs?
Thanks.

Really? Look at example 3.

And, no, I’m not one of the devs. I used to use s2Member extensively. These days I use my own custom code but check in here regularly as this is essentially where I learned to code.

There is a flaw in your logic:

The ‘!’ means the opposite. Your first line translates as:
Current User canNOT Access s2member_level1 -AND- User Is Logged in

This leaves only those with subscriber (or level 0), which are treated as the same thing.

Second line translates as:
Current User is s2Member_level0 -AND- current user can access ccap_bfsupporter capability -AND- current user canNOT access ccap_bfsupporter capability.

This logic easily overlaps because those with the second line are a subset of the first.

In WordPress (unless something has drastically changed in the last couple years), you cannot have multiple ROLES. While roles can be customized, each user is given one role (i.e. Subscriber, Editor, Author, Administrator, etc.) S2Member adds some roles (Level 1, 2, etc.) that sit slightly above the Subscriber role.

However, users can have multiple capabilities that are independent of their role. Each role has a default set of capabilities that each includes (like edit_posts, manage_options, etc.). S2member is able to add custom capabilities to individual users – which it looks like you are using in your second example.

I’d try the following:
For visitors:
[s2If !is_user_logged_in()]...[/s2If]

For ALL Subscribers/Level 0 Logged_In Users
[s2If !current_user_can(access_s2member_level1) AND is_user_logged_in()]...[/s2If]

For ALL Level 1 AND Higher users
[s2If current_user_can(access_s2member_level1)]...[/s2If]

For users with Custom Capability - regardless of level
[s2If current_user_can(access_s2member_ccap_pi_institution)]]...[/s2If]

For users who have the first capability but NOT the second
[s2If current_user_can(access_s2member_ccap_bfsupporter) AND !current_user_can(access_s2member_ccap_pi_institution)]...[/s2If]

I suspect you can figure out how to get more creative if necessary. Just be careful of that exclamation point. It can be easy to miss! :slight_smile:

When I was working to figure out all the nuances of my membership site, I opted to have two membership levels along with all the custom capabilities. Level 1 was a basic membership that was above a free subscriber (and any ccap purchase promoted that user’s level). Level 2 was an all access package that was given all available ccap access.

Not sure what your scenario is, but hope these thoughts help.

~Cam

Really? Look at example 3.

Hey, I’m not looking to be confrontational, but example 3 requires tests for all the memberships individually, which as I stated, is the only option I see.

What I’m trying to do, as simply as possible, is test for logged-in AND not possessing any membership level. As I stated in my own answer to the question, I know I can test for each individually.

There is a flaw in your logic:
The ‘!’ means the opposite.

The use of ! is correct:

s2If !current_user_can(access_s2member_level1) AND is_user_logged_in()]…[/s2If]

That test is for logged in users who are not S2Level1, which, in our case is anyone who has purchased something and is not a member.

This leaves only those with subscriber (or level 0), which are treated as the same thing.

That is not correct. It does not only leave subscriber, and that is the problem. In our case the other role is more likely to be customer (from WooCommerce). Additionally, you can have multiple roles in WordPress (look it up), s2 does not support it. See the attached pic for a user who has customer and s2Level1.

s2_multRoles

I stand corrected on the multiple “roles”. Though from the quick search I found online, using multiple roles is risky. One place I found even suggested that WordPress itself does not “officially” support it, even if it is technically possible with plugins.

In your original post, you did not say you were using other plugins that include user management. That is incredibly risky from a development standpoint!

However, to solve your problem, it may be worth looking into how WooCommerce treats “customers” different from subscribers, and if the “customer role” is added each time the script is run (rather than being saved in the DB as a specific role).

If “customer” users are being added each time the script is run, it’s possible that s2member’s role/cap functions have run before WooCommerce has added a users additional role.

I have zero experience with WooCommerce, so I cannot help you with anything along those lines.

When I was programming the permissions for my site, I found that capabilities were much more reliable when determining access. However, unless your WooCommerce customers have some extra capability, this might not help.

To debug, I might try adding another plugin like User Role Editor to see what is happening for each user, and to hopefully help you discover what might be happening in the background. If your “customer” users have a unique capability, that might help you distinguish them using s2member. By default, subscribers (according to WP) are users with almost no capabilities.

If you find the users have special capabilities, then you can use your s2If statements with current_user_can and the capability you want to test for.

Sorry I cannot be more help.
~Cam

Interesting points.

“Official Support”: WP is a kludgey blogging software that has ballooned to fill a huge need for affordable CMS/eCommerce. The Add-Ons have extended it in many innovative (read “unofficial” ways). Do they ‘officially support’ using roles or additional metadata to limit access to content?

I’ve been in CG/IT for over 30 years, so I’ve worked with a lot of applications – WP for the last 7. IMO the WP dev team has not been the least bit visionary when deciding new features - they treat it likes it is still a blogging platform. So ‘official support’ (embracing innovation from the WP community) is severely lagging in many important areas. Consider that Windows 95 had better file management.

That said, it’s extensibility has provided us with an affordable way to build a complex professional organization. We have a highly customized site and Woo is the engine. I don’t know if Woo uses the customer role for any of its queries, but that is a good question. We use Woo for all of our registration, so if we want to also assign s2Level and/or ccaps as part of a sale, we add the s2 role/ccaps ourselves – this is all customized into the Woo product page.

The biggest risk I see, and this is not limited to WP, is the customization – the site needs to be documented and understandable in the event a different developer needs to step in and work on it.

Agreed. It has been 5+ years since I was heavily developing in WordPress. When I was, I was integrating WP, BuddyPress, and s2member together (something that was supported in the documentation).

However, various updates to one of the three would invariably break parts of my site (most seriously the signup process), so I figured out a way to have all three plugins, but keep them less integrated and dependent on each other. A highly customized site is a risk for one or two updates breaking everything (as I’m sure you know). :slight_smile:

Another thought I had is to program a function into your WooCommerce checkout process (at the end when the user lands on the success/thank you page) that adds a s2member ccap automatically. You commented on adding it yourselves – do you mean manually?

After commenting earlier that I have zero experience in WooCommerce, I remembered that I did once do a set of customizing for a site that used a WooCommerce (I think) addon plugin. It was a real challenge figuring out the nuances of getting it to work, but it was doable. WooCommerce is a good plugin with lots of hooks available to customize, which is a plus.

Hopefully later this weekend I can look into it further and see if I can suggest some code that could help with a solution…

~Cam

Thanks for your offer, but I really don’t need any help at this time. I have the code handled and my question was simply to confirm that I was not missing something simple.

Using custom code, we are able to add s2Levels and ccaps both automatically at the time of registration or manually via csv upload.