Filter list of rules based on a capability

Untested, but should be easily extendable(or something you can take ideas from).

function roles_have_cap( $roles = false, $cap ) {
    global $wp_roles;

    if( !isset( $wp_roles ) || !isset( $cap ) )
        return false;

    if( !$roles )
        $roles = array_keys( $wp_roles->roles );

    if( !is_array( $roles ) )
        $roles = array( $roles );

    $hascap = array();
    foreach( $roles as $role ) {
        if( !isset( $wp_roles->roles[$role]['capabilities'][$cap] ) || ( 1 != $wp_roles->roles[$role]['capabilities'][$cap] ) )
            continue;

        $hascap[] = $role;
    }

    if( empty( $hascap ) )
        return false;

    return $hascap;
}
  • First argument takes either a singular role name(string) or an array of roles to check have a particular cap.
  • Second argument takes a singular capability to check for(string).

Example usage:

$role_can_edit_pages = roles_have_cap( 'administrator', 'edit_pages' ); 
// Result
// array( 0 => administrator )

If the function returned false you’d know the role(s) does not have the cap, ie..

if( !$role_can_edit_pages )
// Role cannot not edit pages

Else, the result is an array of roles that do have the cap(whether you passed in a single role or several).

You could trim it down and just have a return value if that’s preferred, but you mentioned wanting a list of roles that have a cap, so i naturally assumed an array would be a logical choice..

Converting an array to a string is fairly easy, and you can even use your own seperator, simply call implode(), like so…(using the example variable from earlier)..

echo implode( ' | ', $role_can_edit_pages ); // | (pipe is the example seperator here)

You could also move the implode into the function to avoid having to do implodes when calling the function, and do note, implode will work correctly on a single item array to(ie. you’ll get a string with no seperator).

I hope that’s helpful in anycase… 🙂

EDIT:
Function will now look at all the roles if the first arg($roles) is set to false.