WordPress.org

Make WordPress Core

Opened 14 months ago

Last modified 10 months ago

#51181 new feature request

Capabilities arg for register_taxonomy() inneffective on non-hierarchical taxonomies

Reported by: jerclarke Owned by:
Milestone: Awaiting Review Priority: normal
Severity: minor Version:
Component: Taxonomy Keywords:
Focuses: Cc:

Description

TL;DR: It's impossible to make a tag-type taxonomy where admins control who can create terms, and it's part of a much bigger problem with the hierarchical flag.

There's a problem in WP's taxonomy registration where "hierarchical" is overloaded, with the hierarchical flag of register_taxonomy() affecting MANY things that aren't about hierarchy. Of course it affects whether parentage is possible (flat v. hierarchical), but it also totally changes the interface and various assumptions about how the taxonomy will be used.

| register_taxonomy() handbook reference

Valid taxonomy types that the current system fails to enable:

  • Flat taxonomy where the metabox shows the full list of terms with checkboxes
  • Flat taxonomy with tags metabox where some users are blocked from creating new terms
  • Hierarchical taxonomy where the full list of terms isn't always shown

Technical goal of this ticket: Enable creation of taxonomies that use the "tags" interface, where users type in tags and choose them from the autocomplete (i.e. what WP calls "non-hierarchical") but where most users ("Authors") are unable to add new terms.

Broader conceptual goal: Decouple the taxonomy systems conflation of "hierarchical" with input methods for terms (text field v. checkboxes), and permissions control over term creation (anyone can add new tags no matter what).

Infinite (tags) v. Limited (categories) taxonomies (I want infinite)

Conceptually, I think there's an important distinction between categories and tags that has nothing to do with hierarchy: Infinite set v. limited set.

  • Categories are treated as a limited set. If you have more than a dozen the UI no longer works properly. (The site I run has hundreds of categories, so I'm aware both that it's possible to have an "infinite" set, and also that it's a terrible idea).
  • Tags are treated as infinite. The UI is weak in a lot of ways but it's strength is in not getting bogged down if there's a huge number of tags.

I think this aspect of tags v. categories is inherent to everything about them in WP, and that it's intentionally taken for granted by the developers that this aspect of tags v. categories comes along for the ride with the "hierarchical" distinction, despite having nothing to do with hierarchical or "flat".

Proposal: Address this interface question with a new register_taxonomy() argument

This ticket isn't about fixing this problem, but I would strongly encourage also dealing with this, and in a better way than the current option of using the meta_box_cb argument of register_taxonomy() to trick WP into showing the "opposite" metabox UI for a taxonomy, which brings with it bugs and the need for akward workarounds.

Instead, why not ensure that both metabox types support all the variations of taxonomy definitions (hierarchical and capabilities args of register_taxonomy()), then add a new flag that controls the interface, something like:

'ui_type'
(string) What type of metabox will show on the post editor: Use checkboxes for the "categories" type interface, or text_field for the "tags" type interface. Default is based on the hierarchical argument.

This change would dramatically free up developers to choose their hierarchical value based on whether their taxonomy is "flat" or not, rather than based on the coupling of hierarchical with the interface.

For the purposes of this ticket, the point is that I need an "infinite" taxonomy, so I have to use the "tags" interface and am thus trapped with hierarchical=>false.

I have a taxonomy of "Special Topics" for our journalistic organization that will grow indefinitely, and so the categories/hierarchical metabox is innapropriate. I need a solution that doesn't require users to scroll through every term, so the "autocomplete" interface for tags makes more sense.

Controlled (categories) v. Author-expandable (tags) taxonomies

The more problematic side-effect of the hierarchical flag in register_taxonomy() is the inability to stop authors from adding new terms on hierarchical=>false taxonomies. This issue is the key subject of this ticket. I think that unlike the "limited" v. "infinite" question above, the current behavior of WP in terms of the tags UI and permissions is an unintentional side-effect of the distinction between tags and categories.

It should be possible for any taxonomy to control whether authors can create new terms, but from what I can tell, it's impossible to limit creation of terms in hierarchical=>false taxonomies.

If someone can "assign" tags to a post, they automatically and irrevocably also have the ability to create new tags. What does this have to do with a taxonomy not being "hierarchical"?

In my "Special Topics" use case we need to use the tags interface for the "infinite set" reasons described above, but we also need to control the total set of terms for editorial reasons. Our editors will add new "Special Topics" based on group discussions, so authors should not be able to add them on their own. This keeps the length of the list under control, while also avoiding the inevitable typos that make most "tags" systems a nightmare of false positives.

It seems like in WP as it stands, this forces us into the position of using hierarchical=>true (categories) just to have control over creation of new terms, despite us not wanting the terms to have "hierarchical" parentage, nor wanting to use the "categories" metabox UI.

The capabilites option doesn't work properly on non-hierarchical taxonomies

Now down to the specific problem, which is a failure of the taxonomy creation API found in register_taxonomy(), who's capabilities argument should enable us to control who can create terms, but currently has no effect on the post edit screen when hierarchical=>false.

Here's an example capabilities array to get us started. By the expectations of the API, this should allow users who can edit_posts ("Author") to add terms to a post, but all other abilities, like creating, editing, and deleting terms, are reserved only for users who can manage_options ("Administrator"):

<?php
'capabilities' => array(
        'manage_terms' => 'manage_options', // View the management screen
        'edit_terms' => 'manage_options', // Create new terms
        'delete_terms' => 'manage_options', // Remove terms
        'assign_terms' => 'edit_posts', // Associate terms to posts
),

*Result of above: On a hierarchical=>false taxonomy, the "Author" user with only edit_posts is still able to add new terms while editing posts.*

capabilities['edit_terms'] should reliably control who can create new terms

By the description of the capabilities argument, it should be possible to set who can create new terms using the capabilities['edit_terms'] argument to an appropriate cap.

On a hierarchical=>true taxonomy, this is exactly the effect that the capabilities['edit_terms']argument has: If the current user can't edit_terms, then they don't see the Add new category link in the categories metabox.

This is additionally backed up by the management screens for hierarchical=>false taxonomies, which show up in the menu and can be visited as long as the current user has the capabilities['manage_terms'] capability, but will lack the "Add new term" sidebar on the left unless the user also has the capabilities['edit_terms'] capability.

So clearly edit_terms is supposed to encompass the creation of new terms, but for hierarchical=>false taxonomies, that applies to the management screen but not the post editor!

So why doesn't edit_terms=>manage_options stop users without the edit_terms capability from creating new tags in the post editor?

The short answer seems very obvious to me: The tags metabox simply doesn't support anything except the "if you can assign tags you can add them" workflow.

I haven't dug into the relevant PHP and JS but it makes sense. It's complicated to add this support, and "no one uses tags that way" is a compelling though wrong explanation for leaving it as-is. "Just use the category interface" also carries a lot of water, despite failing use-cases like the one I brought up, where the list of terms is too long to list them all, but the admins still need control over which terms are added.

As someone who's used WP since 1.2, I'm not shocked it ended up this way. It's a natural outcome of the slow evolution of categories-only, to categories+tags, to custom taxonomies that basically just implement custom categories and custom tags despite claiming that it's about "hierarchy".

The overall proposal I'm making with this ticket is that it's time for WP taxonomies to grow up a little and truly open up custom taxonomies in a multi-faceted way that incorporates structure (hierarchy), scope (limited v. Infinite), and access control (capabilities), without pinning all three to just one flag and asking people to install a bunch of hacks on their sites if they don't fit into one of those two boxes.

Thanks for reading, sorry to dump a giant task like this with no patch.

I realize this ticket is asking a lot, but I wanted to get a fullsome explanation of what I see as the key issues up on Trac for consideration. I didn't see any tickets abotu this when searching, so maybe it's really the first time it's come up here. My hope is that this issue can be improved on with smaller patches that solve one thing at a time, starting with the most important: Fixing the tags metabox so it respects the capabilities argument** That's the part that feels the most like an actual "bug" to me.

P.S. Here are some WPSE questions that show the need for the use-case I bring up (flat taxonomy with control over new terms), as well as the ugliness and fragility of the options currently proposed to work around the failure of core:

Change History (5)

#1 @helen
11 months ago

  • Type changed from defect (bug) to feature request
  • Version trunk deleted

#2 follow-up: @megphillips91
10 months ago

I would like to propose that we take a look at how roles and capabilities interact with taxonomy terms. (If this exists in core and I have missed it, please point me in the right direction.)

Take for instance my newspaper client - she manages the paper by section (i.e. hierarchal categories). I have not found an elegant way to limit an editor's access to edit and delete articles based on the section-category of the newspaper.

A specific example is the watersports section vs. news. The watersports section editor is a pro surfer. He doesn't edit news, and should not have access. This is a common use case. Editors manage sections of blogs and newspapers.

There is much chatter within sites like stack overflow about ways of handling this simply within UX using JS, but that is not the best way in my opinion. The expected behavior is that WP Core would just do that already.

I would like to be able to use the Roles and Capabilities API to limit edit_posts, delete_posts, delete_others_posts, and edit_others_posts by term value as I can with a custom post type.

Example:

add_cap("edit_posts_term_term_id)

If this is already possible, I would be happy to help add to the documentation so that it is clearer for other developers researching this question.

Does this already exist within core?

Last edited 10 months ago by megphillips91 (previous) (diff)

#3 in reply to: ↑ 2 ; follow-up: @jerclarke
10 months ago

Replying to megphillips91:

I would like to be able to use the Roles and Capabilities API to limit edit_posts, delete_posts, delete_others_posts, and edit_others_posts by term value as I can with a custom post type.

...

Does this already exist within core?

I'm 99% sure this doesn't exist in core. Also I think it's related, but very very far from the original topic of this ticket, which is about controlling which taxonomies users can interact with based on capabilities, not which posts they can interact with based on terms.

Also, I'll quickly react to @helen's changes to make this minor and a feature request: Do you really think it's not a bug that the capability args are totally non-functional within this system? Current behavior is incoherent, that's a bug to me.

#4 in reply to: ↑ 3 ; follow-up: @helen
10 months ago

Replying to jerclarke:

Also, I'll quickly react to @helen's changes to make this minor and a feature request: Do you really think it's not a bug that the capability args are totally non-functional within this system? Current behavior is incoherent, that's a bug to me.

Hmm I did not make this minor, not sure what you mean by that. As for what I was thinking about 6 weeks ago, it seems likely to have been an accident as I was triaging bugs reported against trunk. Reconsider the way you asked that.

Skimming this now, it's not clear to me whether you mean for this ticket to be the full proposal (which I would say is a feature request) or to solicit history and potential solutions to the summarized problem which seems to be the final bolded sentence. If it's the latter, then I believe this to be a duplicate of #26409.

#5 in reply to: ↑ 4 @megphillips91
10 months ago

Replying to helen:

Replying to jerclarke:

Also, I'll quickly react to @helen's changes to make this minor and a feature request: Do you really think it's not a bug that the capability args are totally non-functional within this system? Current behavior is incoherent, that's a bug to me.

Hmm I did not make this minor, not sure what you mean by that. As for what I was thinking about 6 weeks ago, it seems likely to have been an accident as I was triaging bugs reported against trunk. Reconsider the way you asked that.

Skimming this now, it's not clear to me whether you mean for this ticket to be the full proposal (which I would say is a feature request) or to solicit history and potential solutions to the summarized problem which seems to be the final bolded sentence. If it's the latter, then I believe this to be a duplicate of #26409.

@helen Would you suggest I create a new ticket? I saw these related, but I would be very happy to create a new ticket for my request. Please let me know what you would suggest. Thank you so much for your time and attention to this matter. :)

Note: See TracTickets for help on using tickets.