What if you want to show hidden information only to “administrators” or “shop managers?” What about displaying a custom “My Account” tab just for logged-in customers?
Running functions based on user roles by using conditional logic is a common part of WooCommerce customization.
What if you want to show hidden information only to “administrators” or “shop managers?” What about displaying a custom “My Account” tab just for logged-in customers?
Well, wc_current_user_has_role
allows us to check just that: what role group does the logged-in user belong to.
WordPress has six pre-defined roles: Super Admin, Administrator, Editor, Author, Contributor, and Subscriber. WooCommerce adds another two: Shop Manager and Customer. Other plugins may add more. You can theoretically create any number of user roles. Each role is allowed to perform a defined set of tasks called capabilities.
As usual, we’ll study the WooCommerce core function code for wc_current_user_has_role
, see where and why it’s used, and finally, we’ll cover a quick case study. Enjoy!
Function code
The wc_current_user_has_role
function can be found under \woocommerce\includes\wc-user-functions.php
:
/**
* Checks if the current user has a role.
*
* @param string $role The role.
* @return bool
*/
function wc_current_user_has_role( $role ) {
return wc_user_has_role( wp_get_current_user(), $role );
}
The function just returns the result of the wc_user_has_role
function for the logged-in user. This additional function can be found in the same file as wc_current_user_has_role
:
/**
* Checks if a user has a role.
*
* @param int|\WP_User $user The user.
* @param string $role The role.
* @return bool
*/
function wc_user_has_role( $user, $role ) {
if ( ! is_object( $user ) ) {
$user = get_userdata( $user );
}
if ( ! $user || ! $user->exists() ) {
return false;
}
return in_array( $role, $user->roles, true );
}
In a nutshell, wc_user_has_role
checks if a $user
object exists, and if it does, it checks the $role
passed to it against the current list of user roles to see if there’s a match. That’s it.
Function usage
Want to know if the current user is an Administrator? Simple!
if ( wc_current_user_has_role( 'administrator' ) ) {
// do something
}
The same applies to the other roles. The slugs you can use in the wc_current_user_has_role
function are:
'administrator'
'editor'
'author'
'contributor'
'subscriber'
'shop_manager'
'customer'
If you want to know if the current user is in a specific role group — for example, a WooCommerce Shop Manager — you would check this way:
if ( wc_current_user_has_role( 'shop_manager' ) ) {
// do something
}
Now, for a bit of context. If we do a file search for wc_current_user_has_role
inside the WooCommerce plugin code, we’re able to understand where and when it’s used. There are four main results, all inside \woocommerce\includes\wc-user-functions.php
:
/**
* Modify the list of editable roles to prevent non-admin adding admin users.
*
* @param array $roles Roles.
* @return array
*/
function wc_modify_editable_roles( $roles ) {
if ( is_multisite() && is_super_admin() ) {
return $roles;
}
if ( ! wc_current_user_has_role( 'administrator' ) ) {
unset( $roles['administrator'] );
if ( wc_current_user_has_role( 'shop_manager' ) ) {
$shop_manager_editable_roles = apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) );
return array_intersect_key( $roles, array_flip( $shop_manager_editable_roles ) );
}
}
return $roles;
}
add_filter( 'editable_roles', 'wc_modify_editable_roles' );
The wc_modify_editable_roles
function clearly defines who can “add/edit specific user roles.” Because WooCommerce adds users to the Shop Manager and Customer role groups, this function makes sure that if the current user is not an Administrator ( ! wc_current_user_has_role( 'administrator' )
) they can’t add Administrators. (This is for the new Customer and Shop Manager roles.) Also, if the logged-in user is a Shop Manager (wc_current_user_has_role( 'shop_manager' )
), they can add/edit customers!
Similarly, wc_current_user_has_role
is used a few lines below by wc_modify_map_meta_cap
:
/**
* Modify capabilities to prevent non-admin users editing admin users.
*
* $args[0] will be the user being edited in this case.
*
* @param array $caps Array of caps.
* @param string $cap Name of the cap we are checking.
* @param int $user_id ID of the user being checked against.
* @param array $args Arguments.
* @return array
*/
function wc_modify_map_meta_cap( $caps, $cap, $user_id, $args ) {
if ( is_multisite() && is_super_admin() ) {
return $caps;
}
switch ( $cap ) {
case 'edit_user':
case 'remove_user':
case 'promote_user':
case 'delete_user':
if ( ! isset( $args[0] ) || $args[0] === $user_id ) {
break;
} else {
if ( ! wc_current_user_has_role( 'administrator' ) ) {
if ( wc_user_has_role( $args[0], 'administrator' ) ) {
$caps[] = 'do_not_allow';
} elseif ( wc_current_user_has_role( 'shop_manager' ) ) {
// Shop managers can only edit customer info.
$userdata = get_userdata( $args[0] );
$shop_manager_editable_roles = apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) );
if ( property_exists( $userdata, 'roles' ) && ! empty( $userdata->roles ) && ! array_intersect( $userdata->roles, $shop_manager_editable_roles ) ) {
$caps[] = 'do_not_allow';
}
}
}
}
break;
}
return $caps;
}
add_filter( 'map_meta_cap', 'wc_modify_map_meta_cap', 10, 4 );
Once again, this function dictates what Shop Managers can and cannot do with regard to capabilities. This is a little more complex than the previous function so let’s see some case studies that illustrate how it can be used.
WooCommerce case studies
We often need to check the logged-in user role when our shop applies different rules:
- at checkout (payment gateways by role)
- at the product level (price by role)
- at the shop level (toggle categories by role)
- …and so on
Let’s start with the first example — how can we enable a payment gateway just for logged-in customers?
I already have a PayPal toggle snippet on Business Bloomer — however, I use current_user_can
and not wc_current_user_has_role
, so let’s write a new version. Let’s check for a “cheque” gateway:
/**
* @snippet Enable cheque for logged in customers only
* @how-to Get CustomizeWoo.com FREE
* @author Rodolfo Melogli
* @compatible WooCommerce 6
* @donate $9 https://businessbloomer.com/bloomer-armada/
*/
add_filter( 'woocommerce_available_payment_gateways', 'bbloomer_enable_cheque_customers' );
function bbloomer_enable_cheque_customers( $available_gateways ) {
if ( isset( $available_gateways['cheque'] ) && ! wc_current_user_has_role( 'customer' ) ) {
unset( $available_gateways['cheque'] );
}
return $available_gateways;
}
Yes, in order to “enable” a gateway just for customers, I “disable” (unset) it for all non-customers.
One more example?
Let’s apply a discount to logged-in subscribers.
WooCommerce Subscriptions uses the default Subscriber role when a WooCommerce Customer purchases a subscription. Their goes back to “Customer” when the subscription expires/is cancelled)
/**
* @snippet 20% discount logged in subscribers only
* @how-to Get CustomizeWoo.com FREE
* @author Rodolfo Melogli
* @compatible WooCommerce 6
* @donate $9 https://businessbloomer.com/bloomer-armada/
*/
add_action( 'woocommerce_before_calculate_totals', 'bbloomer_alter_price_cart_subscribers', 9999 );
function bbloomer_alter_price_cart_subscribers( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// IF SUBSCRIBER NOT LOGGED IN, DONT APPLY DISCOUNT
if ( ! wc_current_user_has_role( 'subscriber' ) ) return;
// LOOP THROUGH CART ITEMS & APPLY 20% DISCOUNT
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$price = $product->get_price();
$cart_item['data']->set_price( $price * 0.80 );
}
}
No screenshots this week as I’m getting ready for WCEU 2022 and am short on time — hope to see you there!
![Rodolpho Melogli](https://poststatus.com/wp-content/uploads/2022/06/WppgClGp_400x400-300x300.jpg)
Rodolfo Melogli is an author, WooCommerce expert, and WordCamp speaker, Rodolfo has worked as an independent WooCommerce freelancer since 2011. He teaches WooCommerce development at Business Bloomer.