How disable a plugin only for users who don’t have some specific roles

Let’s imagine we want to unload the plugin Sample Plugin only for users who are neither administrators nor editors.

First of all, we need to create a so-called mu-plugin in the folder wp-content/mu-plugins. No matter the title, it’s important that it’s located in wp-content/mu-plugins. If you don’t see the folder mu-plugins, add a new folder in wp-content and name it mu-plugins.

Let’s create for example the file wp-content/mu-plugins/plugin-by-user-role.php.

Here is the code:

add_filter( 'option_active_plugins', 'jose_disabled_plugins_for_logged_users',40,1 );

function jose_disabled_plugins_for_logged_users( $plugins ) {
    if(
        ( wp_doing_ajax() )
        || ( defined( 'WP_CLI' ) && WP_CLI ) || ( defined( 'WP_SANDBOX_SCRAPING' ) && true === WP_SANDBOX_SCRAPING )
    ){
        return $plugins;
    }
    if( isset( $_COOKIE['wordpress_test_cookie'] ) && false !== strpos( implode( '',array_keys( $_COOKIE ) ),'wordpress_logged_in' ) ){
        $user = jose_get_current_user();
        if( $user ){
            $roles = get_user_meta( $user->ID,'wp_capabilities' );
            $skip_for_roles = array( 'administrator','editor' );
            $disabled_plugins = array( 'sample-plugin/sample-plugin.php' );
            foreach( $skip_for_roles as $skip_role ){
                foreach( $roles as $roleA ){
                    if( in_array( $skip_role,array_keys( $roleA ) ) ){
                        return $plugins;
                    }
                }
            }
            $plugins = array_diff( $plugins,$disabled_plugins );
            if( $plugins && is_array( $plugins ) ){
               $plugins = array_unique( $plugins );
            }
          }
       }
    }
    return $plugins;
}


function jose_get_current_user() {
    if( function_exists( 'wp_get_current_user' ) ) return wp_get_current_user(); //If the core function is availablle we use it and return
    if( !defined( 'LOGGED_IN_COOKIE' ) || !isset( $_COOKIE[LOGGED_IN_COOKIE] ) ) return false;
$cookie = $_COOKIE[LOGGED_IN_COOKIE];
    if ( empty( $cookie ) ) {
        if ( empty( $_COOKIE[ LOGGED_IN_COOKIE] ) ) {
            return false;
       }
    }
    $cookie_elements = explode( '|', $cookie );
    if ( count( $cookie_elements ) !== 4 ) {
        return false;
    }
    if( isset( $cookie_elements[0] ) && $cookie_elements[0] && '' !== $cookie_elements[0] ){
        global $wpdb;
        $user = $wpdb->get_row(
        $wpdb->prepare(
"SELECT * FROM $wpdb->users WHERE user_login = %s LIMIT 1",
sanitize_user( $cookie_elements[0] ) ) );
        if(
            $user
            && is_object( $user )
            && isset( $user->user_login )
            && sanitize_user( $user->user_login ) === $user->user_login
            && isset( $user->user_email )
            && $user->user_email === sanitize_email( $user->user_email )
            && isset( $user->ID )
            && ''.absint( $user->ID ) === ''.$user->ID
        ){
           return $user;
        }
    }
    return false;
}

We will use the filter hook “option_active_plugins” to filter the active plugins depending on our conditions.

First, let’s return all the plugins if it’s an ajax action or a WP CLI command because we don’t want to mess up anything.

Then we check if the user is logged in by simpling reading the related cookies. If that cookie is not set we return all the plugins without adding any database query.

We the custom function jose_get_current_user() to get the current user because in a mu-plugin the inbuild. core function wp_get_current_user is still not defined. You can read How to get the current user also when the core function is not available for more details.

Once we have the user, we can get the associated roles with the user meta “wp_capabilities”. I know it looks strange that is named “wp_capabilities”, but the user meta includes an array of roles, and each role has its associated capabilities.

We define the roles that we want to skip, in our example “administrator” and “editor”, and the plugins that we want to disable n the variable $disabled_plugins. In this example sample-plugin/sample-plugin.php.

Then inside the inner, loop if the user role is one of the roles to be skipped, the function will return all the plugins that enter the filter.
If not so, the function will remove the plugins defined in $disabled_plugins.

It’s important that you define correctly the plugins that you want to remove. You need to write the plugin folder name followed by “/” followed by the name of the main plugin file.

For example, for WooCommerce you will have woocommerce/woocommerce.php.
If a plugin has the main file named sample-plugin.php and it’s included in plugins/sample-plugin, then you need to write sample-plugin/sample-plugin.php.

If you prefer an easier life, of course, you can reach the same results with Freesoul Deactivate Plugins PRO.