0
votes

My problem is that all capabilities work as expected except non admin cannot create new widgets. The Add New button is there but the 'You do not have sufficient permissions' message is shown when clicked. The client has unchecked all standard capabilities like edit_posts (for some other reason before I showed up). So maybe that is the issue? Here is my relevant code:

public static function manage_plugin_cap($action = 'add_cap'){

$roles = get_editable_roles();
$caps = array('edit_widget','edit_widgets','read_widgets');
$admin_caps = array('edit_other_widgets','publish_widgets','read_private_widgets','delete_widgets');
foreach ($GLOBALS['wp_roles']->role_objects as $key => $role) {
    if (isset($roles[$key])) {      
        if ($key == 'administrator'){
            foreach ($admin_cap as $c){
                if ($action=='add_cap')
                    {$role->add_cap( $c, false );}
                else  {$role->{$action}( $c );}
            } 
        }
        foreach ($cap as $c){
            if ($action=='add_cap')
                {$role->add_cap( $c, false );}
            else  {$role->{$action}( $c );}
        }
    }
}
 }
 register_post_type( $this->prefix.'_'.$single, $args );
 $args = array(
            'labels'             => $labels,
            'description'        => __( 'Description.', $this->text_domain ),
            'public'             => true,
            'publicly_queryable' => true,
            'show_ui'            => true,
            'show_in_menu'       => 'edit.php?post_type={$single}',
            'query_var'          => true,
            'rewrite'            => array('slug' => $single,'with_front'=>true ),
            'capability_type'    => 'widget',
            'has_archive'        => $plural,
            'can_export'         => true,
            'hierarchical'       => false,
            'menu_position'      => null
 );

Does anyone see what I'm missing? I tried adding 'create_widgets' without success and 'publish_widgets' to all roles (even though I don't want them to be able to) and that didn't work either. Thanks!

Edit: I removed 'capability_type' from args. I don't think that is needed when I define add my own (maybe it is only needed when mapping from existing capabilities so wp knows what to name the new ones).

Update: I had a chance to revisit this to try and get it right. I have these elements in my register_post_type array:

'capability_type'    => 'widget',
'map_meta_cap'       => false, 

which does seem to work for everything except create_widgets. When I dump $GLOBALS['wp_post_types']['my_cpt'] I get

 public 'cap' => 
    object(stdClass)[434]
      public 'edit_post' => string 'edit_widget' (length=10)
      public 'read_post' => string 'read_widget' (length=10)
      public 'delete_post' => string 'delete_widget' (length=12)
      public 'edit_posts' => string 'edit_widgets' (length=11)
      public 'edit_others_posts' => string 'edit_others_widgets' (length=18)
      public 'publish_posts' => string 'publish_widgets' (length=14)
      public 'read_private_posts' => string 'read_private_widgets' (length=19)
      public 'create_posts' => string 'edit_widgets' (length=11)

So I'm not sure why it shows 'create_posts' as 'edit_widgets'?

2

2 Answers

2
votes

"You do not have sufficient permissions to access this page." message means user can't access admin page where posts are created - which is checked before other capabilities, like "edit_widgets". For instance, in your case user has "edit_widgets" capability and in theory he can create new "widget" posts, but he can't reach the admin page where posts are created. And here is why:

As far as I remember, when "show_in_menu" parameter for register_post_type is anything other than "true", default menu item like "Add {post_type}" is not created therefore users will need built-in "edit_posts" capability to access "post-new.php?post_type={post_type}" (where they create new posts).

Workarounds:

  1. Set "show_in_menu" to true: default menus will be created
  2. Grant "edit_posts" capability (obviously, it will allow users create posts which share "edit_posts" capability).
  3. Manually add submenu and set "edit_widgets" as required capability to access the page (if this menu page is nested under 2nd level menu item, it will not be visible - can be useful if you are grouping multiple post types under one menu parent)

    add_submenu_page({parent_menu_link}, 'Add Widget', 'Add Widget', 'edit_widgets', 'post-new.php?post_type={post_type}');

The key here is "edit_widgets" capability which will make "Add Widget" page accessible by anyone who has "edit_widgets" capability.

PS: you may also need to set "map_meta_cap" to true, see https://codex.wordpress.org/Function_Reference/register_post_type

0
votes

I think I figured this one out.I was mapping 'create_posts' incorrectly. As I mentioned in my question, default wp behavior is to map like this:

'create_posts' => 'edit_widgets'

when creating the role, I was mapping like this

'create_posts' => 'create_widgets',

So I went back to mapping like the default and it works.