WordPress.org

Make WordPress Core

Opened 3 months ago

Last modified 3 weeks 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 (1)

#1 @helen
3 weeks ago

  • Type changed from defect (bug) to feature request
  • Version trunk deleted
Note: See TracTickets for help on using tickets.