The default taxonomy, category. By default, only those with the edit_posts capability can assign categories during post creation/editing.

I have a role with very limited capabilities. I want to let users in this role be able to assign categories during custom-post-type creation/editing, but I cannot give them the edit_posts capability and they should not be able to edit the taxonomy, only assign it.

How can I do this? Setting 'assign_terms' => 'read' is one option, but how can I set that value without having to re-register the taxonomy?

Or alternatively, how can I give my low-level role permission to assign the taxonomy?

  • The user have to can assign terms only to post published by himself/herself or even published by others?
    – gmazzap
    Jul 29, 2013 at 17:39
  • Sorry, the previous is a stupid question. You don't want they can edit nothing, just create, I'm wrong?
    – gmazzap
    Jul 29, 2013 at 17:44
  • That's right, the user should only be able o assign categories to the custom posts he has created. I'm going to try your code, one second.
    – sker
    Jul 29, 2013 at 22:01

3 Answers 3


This should works

add_action( 'init', 'register_category_again', 1 );

function register_category_again() {
  $user = wp_get_current_user();
  if ( $user->roles[0] != 'your_custom_role' ) return;
  global $wp_taxonomies;
  unset( $wp_taxonomies['category'] );
  global $wp_rewrite;
  $rewrite = array(
    'hierarchical' => true,
    'slug' => get_option('category_base') ? get_option('category_base') : 'category',
    'with_front' => ! get_option('category_base') || $wp_rewrite->using_index_permalinks(),
    'ep_mask' => EP_CATEGORIES,
  register_taxonomy( 'category', 'post', array(
    'hierarchical' => true,
    'query_var' => 'category_name',
    'rewrite' => $rewrite,
    'public' => true,
    'capabilities' => array(
      'manage_terms'=> 'manage_categories',
      'edit_terms'=> 'manage_categories',
      'delete_terms'=> 'manage_categories',
      'assign_terms' => 'read'
    'show_ui' => true,
    'show_admin_column' => true,
    '_builtin' => true,
  ) );
  • Incredible, works like a charm. I would have never been able to do it without your help. I thought the answer was going to be a one-liner, but it turned out to be more complex than I expected. Thanks a lot.
    – sker
    Jul 29, 2013 at 22:10
  • You are welcome. Unset standard category is one line (maybe two) problem is register it again exactly how WP do, to avoid bugs. However, for the scope I just copied out the WP code. ;)
    – gmazzap
    Jul 29, 2013 at 22:21

I just found this question and although it might work, I was not satisfied with the solution. There had to be a better way to do this, without registering the taxonomy again. And there is a better solution, I am now using in my CPT plugin.

public function wpse_108219_set_taxonomy_caps( $taxonomy, $object_type, $args ) {
    global $wp_taxonomies;

    if ( 'category' == $taxonomy && 'cpt_item' == $object_type ) {
        $wp_taxonomies[ $taxonomy ]->cap->assign_terms = 'edit_cpt_items';


add_filter( 'registered_taxonomy', 'wpse_108219_set_taxonomy_caps' ), 10, 3 );

In this example, I set the assign_terms capability for the custom post type cpt_item to the custom capability edit_cpt_items which enables any user with this capability to assign categories to the CPT.

I hope this cleaner solution also works for you.


You could also filter core's category args before the taxonomy is registered:

 * Set the capabilities for the category taxonomy before it's registered.
 * @param array  $args        Array of arguments for registering a taxonomy.
 * @param array  $object_type Array of names of object types for the taxonomy.
 * @param string $taxonomy    Taxonomy key.
function wpse_108219_register_taxonomy_args( $args, $taxonomy, $object_type ) {

    if ( 'category' === $taxonomy ) {

        $args['capabilities'] = array(
            'manage_terms' => 'manage_categories',
            'edit_terms'   => 'manage_categories',
            'delete_terms' => 'manage_categories',
            'assign_terms' => 'read',


    return $args;

add_filter( 'register_taxonomy_args', 'wpse_108219_register_taxonomy_args', 10, 3 );

Your Answer

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

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