Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WordPress - Custom Post type, Custom role, Custom Capability

I am stuck in a problem assigning custom capability with custom post type to a custom role.

The issue is i want to remove the Add New ( Not with a CSS hack or by unsetting menu item ) option of my custom post type. I have already come across answers that suggest many solutions but none of them works perfectly.

Closest to what i want is this :

register_post_type( 'custom_post_type_name', array(
  'capability_type' => 'post',
  'capabilities' => array(
    'create_posts' => 'do_not_allow', // false < WP 4.5, credit @Ewout
  ),
  'map_meta_cap' => true, // Set to `false`, if users are not allowed to edit/delete existing posts
));

This code removes the Add New link but it assigns the default post slug for capabilities.Notice line 2 of above code. If i change it to my custom post type slug, it stops working and i can't even go posts page.

One thing to keep in mind is that i am working with custom role, which has only read capability by default.

If i also assign the edit_posts capability then my objective is achieved, but then user can also access posts and comments, which i do not want.

Woocommerce is doing this. I dive into woocommerce code and add this line where it registers its products and orders.

'capabilities'        => array( 'create_posts' => 'do_not_allow' ),

And everything works as i want. I have explored woocommerce code all day but can't find how it is doing this. Can someone else help me out on this with another pair of eyes ? :)

Much appreciated. Thanks..

like image 968
shazyriver Avatar asked Sep 28 '17 14:09

shazyriver


2 Answers

You can restrict specific user role to custom post by below script :

Add custom Role

add_action('init','add_my_custom_role');
    function add_my_custom_role() {

     add_role('my_custom_role',
                'Custom Role',
                array(
                    'read' => true,
                    'edit_posts' => false,
                    'delete_posts' => false,
                    'publish_posts' => false,
                    'upload_files' => false,
                    'publish_posts' => false,
                    'create_posts' => false, 
                )
            );
       }

Register Custom post

add_action( 'init', 'my_custom_post_type');
function my_custom_post_type() {
     $args = array(
 'label'               => __( 'Custom post', 'custom-text-domain' ),
 'description'         => __( 'Custom post', 'custom-text-domain' ),
 'labels'              => $labels,
 'supports'            => array( 'title', 'comments', 'revisions', ),
 'hierarchical'        => false,
 'public'              => true,
 'show_ui'             => true,
 'rewrite'             => $rewrite,
                        'capability_type'     => array('custom_post','custom_post'),
                        'map_meta_cap'        => true, // Set to `false`, if users are not allowed to edit/delete existing posts 
 );
 register_post_type( 'custom_post', $args );
}

Allow user capabilities for post on the basis of roles

    add_action('admin_init','custom_post_add_role_caps',999);
        function custom_post_add_role_caps() {

     // Add the roles you'd like to administer the custom post types
     $roles = array('my_custom_role','editor');

     // Loop through each role and assign capabilities
     foreach($roles as $the_role) { 

          $role = get_role($the_role);

                  $role->add_cap( 'read' );
                  $role->add_cap( 'read_custom_post');
                  $role->add_cap( 'read_private_custom_post' );
                  $role->add_cap( 'edit_custom_post' );
                  $role->add_cap( 'edit_custom_post' );
                  $role->add_cap( 'edit_others_custom_post' );
                  $role->add_cap( 'edit_published_custom_post' );
                  $role->add_cap( 'publish_custom_post' );
                  $role->add_cap( 'delete_others_custom_post' );
                  $role->add_cap( 'delete_private_custom_post' );
                  $role->add_cap( 'delete_published_custom_post' );

     }
}

I hope this will help you, to get more help please visit

https://codex.wordpress.org/Function_Reference/register_post_type

and

https://codex.wordpress.org/Roles_and_Capabilities

like image 190
dineshkashera Avatar answered Oct 18 '22 02:10

dineshkashera


I already mention to you that give us little more details about the plan that you want to do?

Here is the solution that I think it would be helpful for you.

If you want to used map_meta_cap => true then you will need to change capability_type as well with your own type, see more https://codex.wordpress.org/Function_Reference/register_post_type#capability_type

But if you set your own capability_type value then you will need to add capability to users role those you want to add.

here is a complete example.

if ( !class_exists( 'WPSE64458_CPT_Register' ) ) {
  class WPSE64458_CPT_Register {

    function __construct() {
      add_action( 'init', array( $this, 'wpse64458_register_post_types' ), 5 );
      add_action( 'admin_init', array( $this, 'wpse64458_add_caps' ), 5 );
      add_filter( 'register_post_type_args', array( $this, 'wpse64458_modify_cpt_registry' ) , 10, 2 );

    }

    /**
     * Register core post types.
     */
    public function wpse64458_register_post_types() {

      if ( ! is_blog_installed() || post_type_exists( 'member' ) ) {
        return;
      }

      register_post_type( 'member',
        apply_filters( 'wpse64458_callb_post_type_member',
          array(
            'labels'              => array(
              'name'                  => __( 'Members', 'domaintext' ),
              'singular_name'         => __( 'Member', 'domaintext' ),
              'all_items'             => __( 'All Members', 'domaintext' ),
              'menu_name'             => _x( 'Members', 'Admin menu name', 'domaintext' ),
              'add_new'               => __( 'Add New', 'domaintext' ),
              'add_new_item'          => __( 'Add new member', 'domaintext' ),
              'edit'                  => __( 'Edit', 'domaintext' ),
              'edit_item'             => __( 'Edit member', 'domaintext' ),
              'new_item'              => __( 'New member', 'domaintext' ),
              'view'                  => __( 'View member', 'domaintext' ),
              'view_item'             => __( 'View member', 'domaintext' ),
              'search_items'          => __( 'Search members', 'domaintext' ),
              'not_found'             => __( 'No members found', 'domaintext' ),
              'not_found_in_trash'    => __( 'No members found in trash', 'domaintext' ),
              'parent'                => __( 'Parent member', 'domaintext' ),
              'featured_image'        => __( 'Member image', 'domaintext' ),
              'set_featured_image'    => __( 'Set member image', 'domaintext' ),
              'remove_featured_image' => __( 'Remove member image', 'domaintext' ),
              'use_featured_image'    => __( 'Use as member image', 'domaintext' ),
              'insert_into_item'      => __( 'Insert into member', 'domaintext' ),
              'uploaded_to_this_item' => __( 'Uploaded to this member', 'domaintext' ),
              'filter_items_list'     => __( 'Filter members', 'domaintext' ),
              'items_list_navigation' => __( 'Members navigation', 'domaintext' ),
              'items_list'            => __( 'Members list', 'domaintext' ),
            ),
            'public'              => true,
            'show_ui'             => true,
            'capability_type'     => 'member',
            'map_meta_cap'        => true,
            'menu_icon'          => 'dashicons-groups',
            'publicly_queryable'  => true,
            'exclude_from_search' => false,
            'hierarchical'        => false, // Hierarchical causes memory issues - WP loads all records!
            'rewrite'            => array( 'slug' => 'member' ),
            'query_var'           => true,
            'supports'            => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
            'has_archive'         => 'members',
            'show_in_nav_menus'   => true,
            'show_in_rest'        => true,
          )
        )
      );

    } // end of wpse64458_register_post_types


    /**
     * Get capabilities.
     *
     * @return array
     */
     private function wpse64458_set_caps() {
      $capabilities = array();

      $capability_types = array( 'member' );

      foreach ( $capability_types as $capability_type ) {

        $capabilities[ $capability_type ] = array(
          // Post type
          "edit_{$capability_type}",
          "read_{$capability_type}",
          "delete_{$capability_type}",
          "edit_{$capability_type}s",
          "edit_others_{$capability_type}s",
          "publish_{$capability_type}s",
          "read_private_{$capability_type}s",
          "delete_{$capability_type}s",
          "delete_private_{$capability_type}s",
          "delete_published_{$capability_type}s",
          "delete_others_{$capability_type}s",
          "edit_private_{$capability_type}s",
          "edit_published_{$capability_type}s",

          // Terms
          // "manage_{$capability_type}_terms",
          // "edit_{$capability_type}_terms",
          // "delete_{$capability_type}_terms",
          // "assign_{$capability_type}_terms",

        );
      }

      return $capabilities;
    }

    /*
      Add Capability
     */
    public function wpse64458_add_caps(){

      global $wp_roles;

      if ( ! class_exists( 'WP_Roles' ) ) {
        return;
      }

      if ( ! isset( $wp_roles ) ) {
        $wp_roles = new WP_Roles();
      }

      $capabilities = $this->wpse64458_set_caps();

      foreach ( $capabilities as $cap_group ) {
        foreach ( $cap_group as $cap ) {
          $wp_roles->add_cap( 'editor', $cap );
          $wp_roles->add_cap( 'administrator', $cap );
        }
      }
    }

    public function wpse64458_modify_cpt_registry( $args, $post_type ){

      // Do not filter any other post type
      if ( 'member' !== $post_type ) {

        // Give other post_types their original arguments
        return $args;

      }

      if( current_user_can('editor') ) {
        $args['capabilities']['create_posts'] = false;
      }

      // Give the custom-css-js post type it's arguments
      return $args;

    }


  }
}

then inherite the class with new WPSE64458_CPT_Register();

With this example I disable editor role to add new member post functionality. modify whatever you like, or you can do this others as well. but you previously mention that you already tried to follow WooCommerce, actually they also do this way,

Hope it make sense to you.

HappyCodding!

like image 3
mlimon Avatar answered Oct 18 '22 03:10

mlimon