0

I am trying to make a custom post type editable by a group of people (i.e. The users department) instead of only the author. I don't want to let them edit posts created by people of other groups(department). To solve this issue, I am using map_meta_cap filter to map the custom capabilities. Which is actually working fine. If I check it like: user_can( $user_id_of_who_is_editing, 'edit_post', $post_id ) It returns true for users of same department.

Now, if the non-owner user, who belongs to the same department, this error shows up:

You are not allowed to edit this post.

If wordpress does not check current_user_can( 'edit_post', $post_id ), how does it check and how can I bypass it?

Map metacap filter:

add_filter( 'map_meta_cap', function( $caps, $cap, $user_id, $args ) {
    global $dept_based_cap_post_types;

    if( isset( $args[0] ) ){
        $post = get_post( $args[0] );
        if( isset( $post->post_type ) && in_array( $post->post_type, $dept_based_cap_post_types ) ){
            $edit   = "edit_$post->post_type";
            $delete = "delete_$post->post_type";
            $read   = "read_$post->post_type";

            $post_belongs_to_users_department = lu_post_under_users_dept( $user_id, $post->ID );
        }
        else {
            return $caps;
        }
    }
    else {
        return $caps;
    }

    /* If editing, deleting, or reading a post, get the post and post type object. */
    if ( $edit == $cap || $delete == $cap || $read == $cap ) {
        $post_type = get_post_type_object( $post->post_type );

        /* Set an empty array for the caps. */
        $caps = array();
    }

    /* If editing a post, assign the required capability. */
    if ( $edit == $cap ) {
        if ( $post_belongs_to_users_department || ( $user_id == $post->post_author && 'draft' == $post->post_status ) )
            $caps[] = $post_type->cap->edit_posts;
        else
            $caps[] = $post_type->cap->edit_others_posts;
    }

    /* If deleting a post, assign the required capability. */
    elseif ( $delete == $cap ) {
        if ( $post_belongs_to_users_department || ( $user_id == $post->post_author && 'draft' == $post->post_status ) )
            $caps[] = $post_type->cap->delete_posts;
        else
            $caps[] = $post_type->cap->delete_others_posts;
    }

    /* If reading a private post, assign the required capability. */
    elseif ( $read == $cap ) {

        if ( 'private' != $post->post_status )
            $caps[] = 'read';
        elseif ( $post_belongs_to_users_department || ( $user_id == $post->post_author && 'draft' == $post->post_status ) )
            $caps[] = 'read';
        else
            $caps[] = $post_type->cap->read_private_posts;
    }

    return $caps;
}, 10, 4 );

Code for custom post type registration:

$capabilities = array(
    'edit_post'           => 'edit_registration',
    'read_post'           => 'read_registration',
    'delete_post'         => 'delete_registration',
    'delete_posts'        => 'delete_registrations',
    'delete_others_posts' => 'delete_others_registrations',
    'edit_posts'          => 'edit_registrations',
    'edit_others_posts'   => 'edit_others_registrations',
    'publish_posts'       => 'publish_registrations',
    'read_private_posts'  => 'read_private_registrations'
);

$args = array(
    'labels'             => $labels,
    'public'             => false,
    'publicly_queryable' => false,
    'show_ui'            => current_user_can( 'edit_programs' ) ? 'edit.php?post_type=program' : true,
    'query_var'          => false,
    'capabilities'       => $capabilities,
    'has_archive'        => false,
    'hierarchical'       => false,
    'menu_icon'          => 'dashicons-clipboard',
    'supports'           => array( null ) // Array must contain a value to remove the default fields
);

register_post_type( 'registration', $args );
1

It appears that wordpress does not check the edit_post capability while saving. Instead it checks for the author. So I used a hack to override the author id. So, wordpress thinks you are changing the author and works by first changing the author to your own id. You can add this code below in your functions.php to fix this issue.

function your_function() {
    echo '
    <script>
    // Hack to let authorised people of the department manupulate the registration.
    jQuery(document).ready(function($){
        $(\'<input id="post_author_override" type="hidden" name="post_author_override" />\')
            .val( $("#user-id").val() )
            .prependTo("form");
    });
    </script>';
}
add_action( 'wp_footer', 'your_function' );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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