2

In my system, I'm making two new roles:

  • Third Party (TP) (lesser privileges)
  • Data Entry Operator (DEO) (powerful over Third Party - but not of its own group)

My CPT 'capabilities' parameter is revamped using 'map_meta_cap' => true like:

...
'capabilities' => array ( 'read' => 'read_cpt', 'edit_posts' => 'edit_cpt' ),
'map_meta_cap' => true
...

Scenario is: TP can add their contents freely, but can't publish. DEOs can add their contents freely too, and additionally DEOs can edit/modify TP's contents, and finally can publish 'em. But they (DEOs) can't touch each other's posts of their own role. Suppose, 'X as a DEO' added an article, 'Y as a DEO' can't touch on it. But X and Y can individually touch posts of 'Z as a TP'.

While adding new role, I'm doing:

$tp = add_role(
       'third_party',
       __('Third Party'),
       array(
           'read_cpt' => true,
           'edit_cpt' => true,
           //'edit_others_cpt => false //by default not assigned
       )
);

$deo = add_role(
       'data_entry_operator',
       __('Data Entry Operator'),
       array(
           'read_cpt' => true,
           'edit_cpt' => true,
           'edit_others_cpt => true
       )
);

You know, edit_others_cpt will access them editing TP's posts, but won't restrict them of editing posts of their own user role (DEO).

How can I let DEO 'edit_others_posts' of TP role only, not of DEO?

1 Answer 1

1

First add capabilities to the roles like this

add_action( 'after_setup_theme', 'add_caps_to_custom_roles' );
function add_caps_to_custom_roles() {
  $caps = array(
    'read_cpt',
    'edit_cpt',
    'edit_others_cpt',
  );
  $roles = array(
    get_role( 'third_party' ),
    get_role( 'data_entry_operator' ),
  );
  foreach ($roles as $role) {
    foreach ($caps as $cap) {
      $role->add_cap( $cap );
    }
  }
}

THEN

/**
 * Helper function getting roles that the user is allowed to create/edit/delete 'TP' post.
 *
 * @param   WP_User $user
 * @return  array
 */
function allowed_roles_to_edit_TP_post( $user ) {
    $allowed = array();

    if ( in_array( 'administrator', $user->roles ) ) { // Admin can edit all roles post
        $allowed = array_keys( $GLOBALS['wp_roles']->roles );
    } else ( in_array( 'data_entry_operator', $user->roles ) ) {                
        $allowed[] = 'third_party';
    }

    return $allowed;
}

/**
 * Remove roles that are not allowed for the current user role.
 */
function editable_roles( $roles ) {
    if ( $user = wp_get_current_user() ) {
        $allowed = allowed_roles_to_edit_TP_post( $user );

        foreach ( $roles as $role => $caps ) {
            if ( ! in_array( $role, $allowed ) )
                unset( $roles[ $role ] );
        }
    }

    return $roles;
}
add_filter( 'editable_roles', 'editable_roles' );

/**
 * Prevent users deleting/editing users with a role outside their allowance.
 */
function controll_map_meta_cap( $caps, $cap, $user_ID, $args ) {
    if ( ( $cap === 'read_cpt' || $cap === 'edit_cpt' || $cap === 'edit_others_cpt' ) && $args ) {
        $the_user = get_userdata( $user_ID ); // The user performing the task
        $user     = get_userdata( $args[0] ); // The user being edited/deleted

        if ( $the_user && $user ) {
            $allowed = allowed_roles_to_edit_TP_post( $the_user );

            if ( array_diff( $user->roles, $allowed ) ) {
                // Target user has roles outside of our limits
                $caps[] = 'not_allowed';
            }
        }
    }

    return $caps;
}
add_filter( 'map_meta_cap', 'controll_map_meta_cap', 10, 4 );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.