User role permissions based on taxonomies

I was wondering if it’s possible to set up user roles in a way that means that users in certain groups can ONLY edit posts that have a specific taxonomy assigned to them e.g:

Properties (Post Type)
    Taxonomy One
    Taxonomy Two
    Taxonomy Three

User Roles
    Group One - Can only edit properties with 'Taxonomy One' assigned.
    Group Two - Can only edit properties with 'Taxonomy Two' assigned.
    Group Three - Can only edit properties with 'Taxonomy Three' assigned.

I’m using the Members plugin for role management at the moment, and I’m using custom post types/taxonomies.

From what I’ve seen so far it doesn’t look as though you can restrict access to POSTS based on TAXONOMIES.

UPDATE

I’ve now got permissions working for post types using the following code:

register_post_type( 'properties',
    array(
        'labels' => array(
            'name' => __( 'Properties' ),
            'singular_name' => __( 'Property' )
        ),
        'public' => true,
        'capability_type' => 'property',
        'map_meta_cap' => true,
        'capabilities' => array(
            'publish_posts' => 'publish_properties', // This allows a user to publish a property.
            'edit_posts' => 'edit_properties', // Allows editing of the user’s own properties but does not grant publishing permission.
            'edit_others_posts' => 'edit_others_properties', // Allows the user to edit everyone else’s properties but not publish.
            'delete_posts' => 'delete_properties', // Grants the ability to delete properties written by that user but not others’ properties.
            'delete_others_posts' => 'delete_others_properties', // Capability to edit properties written by other users.
            'read_private_posts' => 'read_private_properties', // Allows users to read private properties.
            'edit_post' => 'edit_property', // Meta capability assigned by WordPress. Do not give to any role.
            'delete_post' => 'delete_property', // Meta capability assigned by WordPress. Do not give to any role.
            'read_post' => 'read_property', // Meta capability assigned by WordPress. Do not give to any role.
        )
    )
);

A ‘Properties’ section has now appeared when editing roles in the ‘Members’ plugin which lets me restrict/allow access. Just need to figure out if this is do-able for each taxonomy now 🙂

2 Answers
2

You might be able to use the filter user_has_cap which is used when checking for a particular capability (found in /wp-includes/class-wp-user.php in has_cap):

    /**
     * Dynamically filter a user's capabilities.
     *
     * @since 2.0.0
     * @since 3.7.0 Added the user object.
     *
     * @param array   $allcaps An array of all the user's capabilities.
     * @param array   $caps    Actual capabilities for meta capability.
     * @param array   $args    Optional parameters passed to has_cap(), typically object ID.
     * @param WP_User $user    The user object.
     */
    $capabilities = apply_filters( 'user_has_cap', $this->allcaps, $caps, $args, $this );

So it would be something like:

add_filter('user_has_cap','check_post_taxonomy',10,4);
function check_post_taxonomy($allcaps,$caps,$args,$user) {
    global $post; if (!isset($post)) {return $allcaps;}

    $group = get_user_meta($user->ID,'special_edit_group',true);
    $taxonomy = 'taxonomy_'.$group; // maybe set to a, b or c?
    $terms = get_the_terms($post->ID,$taxonomy);

    // if there are no terms, remove the user capability(s) for this check
    // you may have to experiment to remove all the ones you want to
    if (!$terms) {
        unset($allcaps['edit_properties']);
    }

    return $allcaps;
}

I have done it this way because I realized the logic of the question is not quite right. If a post type has taxonomy A, B and C assigned to it, even if you set these capability filters for the role groups as you say, all three role groups would be able to edit anything in this post type anyway. In other words, there is no case where taxonomy A, B or C is “not” actually assigned.

Instead, I think you are really meaning “check whether this particular post has any terms assigned to it in taxonomy A”… and if so along group A to edit it, and so on. (Note: I have no idea if the above code will actually work for this case, it might need some more work. For example, currently this is checking for a user meta key for the group rather than an actual role/group.)

Leave a Comment