Make WordPress Core

Opened 7 years ago

Closed 4 years ago

Last modified 4 years ago

#43517 closed defect (bug) (fixed)

Adding support of default category term for custom taxonomies

Reported by: enricosorcinelli's profile enrico.sorcinelli Owned by: whyisjake's profile whyisjake
Milestone: 5.5 Priority: normal
Severity: normal Version:
Component: Taxonomy Keywords: has-patch has-dev-note
Focuses: Cc:

Description

This patch aims to add the support for default category term in custom taxonomies in the same way that is done for built-in taxonomies.

The new default_term argument is added to register_taxonomy() allowing to define the default term name and optionally slug and description. For example:

register_taxonomy( 'custom-tax', 'my-cpt', array(
   'default_term' => array( 'name' => 'My default category', 'slug' => 'default-category' ),
));

This way, by inserting a new my-cpt object without setting any custom-tax terms, the default term 'My default category' will be used for that taxonomy.

The default_taxonomy_{$axonomy} value is used as option_name in order to save default terms id in wp_options.

PS: Apparently, I haven't found any related ticket other than this old one.

Attachments (8)

43517.patch (6.9 KB) - added by enrico.sorcinelli 7 years ago.
43517.2.diff (7.2 KB) - added by davidbaumwald 5 years ago.
Refreshed patch
43517.2.patch (7.0 KB) - added by enrico.sorcinelli 5 years ago.
43517.3.patch (7.0 KB) - added by enrico.sorcinelli 4 years ago.
43517.diff (6.8 KB) - added by whyisjake 4 years ago.
43517.4.patch (8.2 KB) - added by enrico.sorcinelli 4 years ago.
43517.5.patch (2.6 KB) - added by enrico.sorcinelli 4 years ago.
43517.6.patch (4.1 KB) - added by enrico.sorcinelli 4 years ago.

Download all attachments as: .zip

Change History (51)

#1 @mukesh27
7 years ago

  • Keywords has-patch added

#2 @enrico.sorcinelli
7 years ago

  • Keywords has-unit-tests added

This ticket was mentioned in Slack in #core by enrico.sorcinelli. View the logs.


7 years ago

#4 @SergeyBiryukov
7 years ago

  • Milestone changed from Awaiting Review to 5.0

#5 @SergeyBiryukov
7 years ago

  • Owner set to SergeyBiryukov
  • Status changed from new to reviewing

#7 @pento
6 years ago

  • Milestone changed from 5.0 to 5.1

#9 @pento
6 years ago

  • Milestone changed from 5.1 to 5.2

#10 @SergeyBiryukov
6 years ago

  • Milestone changed from 5.2 to 5.3

Missed the 5.2 Beta 1 deadline, moving to 5.3.

This ticket was mentioned in Slack in #core by david.baumwald. View the logs.


5 years ago

#12 @desrosj
5 years ago

  • Keywords needs-refresh added

43517.patch needs a refresh against current trunk. @SergeyBiryukov are you still up for reviewing this one?

@davidbaumwald
5 years ago

Refreshed patch

#13 @davidbaumwald
5 years ago

  • Keywords needs-refresh removed

@SergeyBiryukov I refreshed the patch an cleaned up a couple of things. Is this something that can be reviewed in time for 5.3 Beta 1 tomorrow or should this have more time for testing?

#14 @davidbaumwald
5 years ago

  • Milestone changed from 5.3 to Future Release

The deadline for version 5.3 Beta 1 enhancements is now passed, so this is being moved to Future Release.

#15 @enrico.sorcinelli
5 years ago

I just refreshed my patch for current trunk.

This ticket was mentioned in Slack in #core by enrico.sorcinelli. View the logs.


5 years ago

#17 @whyisjake
5 years ago

  • Milestone changed from Future Release to 5.5

#18 @whyisjake
5 years ago

  • Owner changed from SergeyBiryukov to whyisjake
  • Status changed from reviewing to accepted

This ticket was mentioned in Slack in #core by david.baumwald. View the logs.


4 years ago

#20 @davidbaumwald
4 years ago

@whyisjake Is this still on your list to review prior to Beta 1 for 5.5 due to release next week?

#21 @enrico.sorcinelli
4 years ago

I uploaded a refreshed patch in order to apply cleanly to current trunk.
@davidbaumwald as far i know, I think that the ticket is on the @SergeyBiryukov list

Last edited 4 years ago by enrico.sorcinelli (previous) (diff)

@whyisjake
4 years ago

#22 @whyisjake
4 years ago

43517.diff runs the changes through composer format.

#23 @whyisjake
4 years ago

  • Resolution set to fixed
  • Status changed from accepted to closed

In 48356:

Taxonomy: Add support for default terms for custom taxonomies.

The new default_term argument is added to register_taxonomy() allowing a user to define the default term name and optionally slug and description.

Fixes #43517.

Props enrico.sorcinelli, SergeyBiryukov, desrosj, davidbaumwald, whyisjake.

#24 @TimothyBlynJacobs
4 years ago

What is the performance impact of this change? AFAICT, this is adding a term_exists query to every page load. Can we check for the option first before checking the term?

#25 @whyisjake
4 years ago

  • Keywords dev-feedback added; has-patch has-unit-tests removed
  • Resolution fixed deleted
  • Status changed from closed to reopened
  • Type changed from enhancement to defect (bug)

Going to reopen to look into adding a check for the option. @enricosorcinelli, can you check?

#26 @johnbillion
4 years ago

  • Keywords needs-patch added
  • Version 5.1 deleted

Can we also avoid the mixed type and just go with an array? It's not clear from the parameter description whether this field accepts a slug, name, or ID, and we might as well be explicit about it.

#27 @johnbillion
4 years ago

Sorry I meant the array|string type, not mixed.

#28 @enrico.sorcinelli
4 years ago

The term_exists call is made only for custom taxonomies for which has been defined a default_term (and the default value in null).
However term_exists() doesn't cache results anyway and adding it could be an interesting new functionality.

Moreover I'd like to add some missing features like:

  • remove default_taxonomy_{$taxonomy} option on unregister_taxonomy()
  • check and prevent to delete the default term for custom taxonomies like wp_delete_term() does for category taxonomy.

So I refreshed the patch by updating also default_term parameter documentation (I leaved string|array type).

Last edited 4 years ago by enrico.sorcinelli (previous) (diff)

#29 @TimothyBlynJacobs
4 years ago

The term_exists call is made only for custom taxonomies for which has been defined a default_term (and the default value in null).
However term_exists() doesn't cache results anyway and adding it could be an interesting new functionality.

Right, which is why I think we should first check if the default taxonomy option is already set so we can avoid that uncached query.

So I refreshed the patch by updating also default_term parameter documentation (I leaved string|array type).

The patch has been committed already, so it needs to be refreshed against trunk.

A separate thing. With the current version, is it possible to completely remove all terms from a post? Looking at the code it seems like the default term will always get added back.

#30 @enrico.sorcinelli
4 years ago

I've just uploaded a refreshed patch.
@TimothyBlynJacobs If I understood your question, as far I know, it is possible with wp_delete_object_term_relationships() that that uses wp_remove_object_terms() behind the scenes.
The default term is added with wp_set_object_terms() instead.

#31 @TimothyBlynJacobs
4 years ago

Hm, previously though calling wp_set_object_terms() with an empty array would work though, no? It does the diffing and then calls wp_remove_object_terms. That is how the REST API sets the terms for a post and it looks like wp_insert_post as well.

#32 @enrico.sorcinelli
4 years ago

  • Keywords dev-feedback needs-patch removed

@TimothyBlynJacobs My fault, and I agree with you that wp_set_object_terms() shouldn't assign the default taxonomy term so I moved related code into wp_insert_post().

PS: I discovered a strange/different behavior between different editors API described in #50648

#33 @davidbaumwald
4 years ago

  • Keywords dev-feedback has-patch added

#34 @SergeyBiryukov
4 years ago

In 48480:

Taxonomy: Make some adjustments to handling default terms for custom taxonomies:

  • Move default term assignment from wp_set_object_terms() to wp_insert_post().
  • Make sure the passed taxonomy list overwrites the existing list if not empty.
  • Remove the default term option on unregister_taxonomy().
  • Prevent deletion of the default term in wp_delete_term().

Props enrico.sorcinelli, TimothyBlynJacobs.
See #43517.

#35 @whyisjake
4 years ago

@SergeyBiryukov can we close this out, or do we want to track a few more changes?

#36 @whyisjake
4 years ago

  • Resolution set to fixed
  • Status changed from reopened to closed

I think with the changes in [48480] we are good to close this out.

#37 @SergeyBiryukov
4 years ago

In 48664:

Coding Standards: Reformat a condifion for default taxonomy terms in map_meta_cap() for better readability.

Follow-up to [48356], [48480].

See #43517.

#38 @SergeyBiryukov
4 years ago

In 48665:

Taxonomy: Rename the default_taxonomy_$taxonomy option key to default_term_$taxonomy.

This better reflects the purpose of the option.

Follow-up to [48356], [48480].

See #43517.

#39 @SergeyBiryukov
4 years ago

  • Keywords needs-dev-note added; dev-feedback removed

#41 @helgatheviking
4 years ago

Is the default term meant to be saved for the taxonomy in the absence of other chosen terms? With posts and categories, if you don't select any other category "uncategorized" is checked the next time the post editor is loaded. This doesn't happen with the default term in a custom taxonomy. But if it's meant to be equivalent to "uncategorized" shouldn't this term be saved to a post when no other terms are selected?

#42 @enrico.sorcinelli
4 years ago

Hi @helgatheviking,
in order to auto-add the default custom taxonomy term when saving or updating post without custom taxonomy terms you have to explicitly define default_term when registering the custom taxonomy, for example:

register_taxonomy(
        'custom-tax',
        'post',
        array(
                'labels'=> array(
                        'name' => 'Custom tax'
                ),
                'hierarchical' => true,
                'public'       => true,
                'show_ui'      => true,
                'show_admin_column' => true,
                'show_in_nav_menus' => true,
                'show_in_menu'      => true,
                'show_in_rest'      => true,
                'default_term' => array(
                        'name' => 'Default category',
                        'slug' => 'default-category',
                ),
        )
);

However note that with block editor this doesn't happen in the same manner (for example if you remove all category or custom taxonomy terms, the default term will not be auto re-added to the post). See #50648

#43 @johnjamesjacoby
4 years ago

A bit of feedback about this feature, now that I've implemented it into a plugin I help maintain.

Coupling the 'default_term' WP_Taxonomy argument with a registered setting (for storing the ID of the default term) puts developers into a catch 22 situation.

The setting stores a term ID, but the argument requires a term Name. 🤔

So you don't want to register the taxonomy without default_term (because you want all the admin-area UI goodies that come with that argument being non-empty) but you can't get the default-term name from the database without a call to get_term() which works best when it's supplied a taxonomy, which isn't registered yet. 🔁

It means an early get_term() call that may potentially have legacy issues with shared terms even before the call to register_taxonomy() happens to register the taxonomy being queried for via get_term(). 🔁

// Default arguments
$args = array();

// Default term
$default = get_option( 'default_term_taxonomy_name' );

// Default exists
if ( ! empty( $default ) ) {

	// Get term (does not use taxonomy, because it's not registered yet)
	$term = get_term( $default );

	// Term exists
	if ( ! empty( $term->name ) ) {
		$args['default_term'] = array( 'name' => $term->name );
	}
}

// Register
register_taxonomy(
	'taxonomy_name',
	'post_type,
	$args
);

This above code and approach will work reliably for sites that do not have shared terms, but has a small potential to not work correctly on sites that are sharing terms across taxonomies.

It also was quite weird to implement. I had hoped the default_term argument would accept the numeric ID of the value straight from the registered setting, handling verification & fallback internally. I understand why that isn't how it works, but it also doesn't seem super great to pass that burden down to each plugin that uses it.

I'm glad to see this feature exist and working how it does in WordPress admin, and hope to see further improvements to it. 🙏

Note: See TracTickets for help on using tickets.