I found one related issue to this moment. WC version 3.4.6 introduced the critical bug in includes/wc-user-functions.php.
Older version:
function wc_modify_editable_roles( $roles ) {
if ( ! current_user_can( 'administrator' ) ) {
unset( $roles['administrator'] );
}
return $roles;
}
add_filter( 'editable_roles', 'wc_modify_editable_roles' );
New version:
function wc_modify_editable_roles( $roles ) {
if ( ! current_user_can( 'administrator' ) ) {
unset( $roles['administrator'] );
}
if ( current_user_can( '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' );
current_user_can() always returns true for WP multisite superadmin. Thus this function hides from superadmin all roles except ‘customer’.
This issue requires urgent fix.
A lot of WooCommerce users use “User Role Editor” or similar plugins to work with custom roles. It’s not a friendly behavior to break their work using this logic:
“Shop manager” may select from available drop-down list just a single “Customer” role.
Thread Starter
Abland
(@abland)
Thank you, Vladimir (@shinephp)
Removing the shop_manager condition fixed the drop down issue. In the same file, includes/wc-user-functions.php just below the code you posted there is this code:
function wc_modify_map_meta_cap( $caps, $cap, $user_id, $args ) {
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 ( user_can( $args[0], 'administrator' ) && ! current_user_can( 'administrator' ) ) {
$caps[] = 'do_not_allow';
}
// Shop managers can only edit customer info.
if ( current_user_can( 'shop_manager' ) ) {
$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 );
Removing the shop_manager conditional allows Super Admin to edit users again also.
I agree – not a friendly behavior … hopefully they fix this quickly
Quick workaround for WordPress multisite superadmin and WooCommerce v. 3.4.6.
This code switches off WooCommerce’s available roles list changing code for WordPress multisite superadmin user only:
add_action( 'admin_init', 'fix_for_wc_436');
function fix_for_wc_436() {
if ( ! is_multisite() or ! is_super_admin() ) {
return;
}
remove_filter( 'editable_roles', 'wc_modify_editable_roles' );
remove_filter( 'map_meta_cap', 'wc_modify_map_meta_cap', 10 );
}
Setup it as a “Must Use” plugin or add to the theme’s functions.php file.
And, yes, WC developers offer a custom filter ‘woocommerce_shop_manager_editable_roles’, which allows to whitelist for ‘shop_manager’ additional roles, not a ‘customer’ only. Example is offered here.
Thread Starter
Abland
(@abland)
Thank you, Vladimir, (@shinephp)
That code snippet into the theme functions.php should do the trick quite nicely. I appreciate the time and interest you’ve put into this.
Thanks for the heads-up. We’ll patch this soon. You can follow at: https://github.com/woocommerce/woocommerce/issues/21546
Adding the snippet to Remove those filters worked for my network sites, but the main blog still only allows the Customer role to be viewed, and when adding a new user as a Customer I still get a permission error. I even deleted the conditionals so the filters are removed in all cases, but still the main blog is messed up.
Plugin Support
AW a11n
(@slash1andy)
Automattic Happiness Engineer
This is fixed in the latest WooCommerce version, 3.4.7, marking resolved.