Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Taxonomies: Term order not retained (if sort is true) #65052

Closed
2 tasks done
ockham opened this issue Sep 4, 2024 · 1 comment · Fixed by #67154
Closed
2 tasks done

Taxonomies: Term order not retained (if sort is true) #65052

ockham opened this issue Sep 4, 2024 · 1 comment · Fixed by #67154
Assignees
Labels
[Status] In Progress Tracking issues with work in progress [Type] Bug An existing feature does not function as intended

Comments

@ockham
Copy link
Contributor

ockham commented Sep 4, 2024

Description

For any taxonomy registered via register_taxonomy that has show_in_rest set totrue, the block editor automatically adds a panel to the sidebar that allows editing the terms associated with the current post. (The UI is the same that's used for WP's built-in categories and tags, respectively -- for hierarchical and non-hierarchical ("flat") taxonomies, respectively.)

When the user edits any of those flat taxonomy terms, they are always sorted alphabetically. This might be fine for Tags; however, register_taxonomy includes an argument called sort, which, if set to true, is supposed to retain the order in which terms are added by the user. This is currently being ignored.

--

There's a workaround, which consists in setting 'args' => array( 'orderby' => 'term_order' ) upon registering the taxonomy. This forcibly sets the sort order to term_order in any query for the taxonomy. But arguably, this workaround shouldn't be needed; setting 'sort' => true should be enough.

Step-by-step reproduction instructions

Add the following code (e.g. to your theme's functions.php) and use the "Actors" panel in the block inspector to assign a number of actor names to a given post. Note that the actors are re-ordered alphabetically every time a new actor is added. Try saving and reloading the post, and view it on the frontend, and note that the actors also appear in alphabetical order there.

function register_taxonomies() {
	/**
	 * Taxonomy: Actors.
	 */

	 $labels = array(
		'name'          => __( 'Actors' ),
		'singular_name' => __( 'Actor' ),
		'add_new_item'  => __( 'Add Actor' ),
		'new_item_name' => __( 'New Actor' ),
	);

	$args = array(
		'label'                 => __( 'Cast' ),
		'labels'                => $labels,
		'public'                => true,
		'publicly_queryable'    => true,
		'hierarchical'          => false,
		'show_ui'               => true,
		'show_in_menu'          => true,
		'show_in_nav_menus'     => true,
		'query_var'             => true,
		'show_admin_column'     => false,
		'show_in_rest'          => true,
		'show_tagcloud'         => false,
		'rest_base'             => 'actors',
		'rest_controller_class' => 'WP_REST_Terms_Controller',
		'rest_namespace'        => 'wp/v2',
		'show_in_quick_edit'    => false,
		'show_in_graphql'       => false,
		'sort'                  => true, // Note this.
	);

	register_taxonomy( 'actors', array( 'post' ), $args );
}

add_action( 'init', 'register_taxonomies', 0 );

Screenshots, screen recording, code snippet

flat-terms-before

Environment info

No response

Please confirm that you have searched existing issues in the repo.

  • Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

  • Yes
@ockham ockham added the [Type] Bug An existing feature does not function as intended label Sep 4, 2024
@ockham
Copy link
Contributor Author

ockham commented Sep 4, 2024

The fix requires a client-side part to retain the order of terms during editing. That fix is fairly straight-forward: #64471

However, it also requires a server-side part, to retain the order when saving: Specifically when updating a post -- and associated terms -- via the REST API: Currently, when a post is updated this way, the original order is lost, and the endpoint returns the terms in alphabetical order instead. Consider the following payload:

_locale user

(This is with #64471 applied, which allowed retaining the actors term order -- 22, 23, 24.)

The response for this request reads:

• {id 59, date 2024-08-26T114905

(Here, the actors have been re-ordered alphabetically, resulting in 22, 24, 23.)

The code responsible for this is the Post Controller's handle_terms method.

OTOH, terms are included in the response by this code. This is where things get tricky: Note that it uses get_the_terms. The latter is a higher-level wrapper for wp_get_object_terms. Unlike the latter, get_the_terms doesn't support specifying query arguments to set the sort order etc (possibly as it also caches terms for a given post -- which might be less effective if it had to take those extra arguments into account). Arguments set directly during register_taxonomy make it through, however -- this is why the workaround described in the issue description works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Status] In Progress Tracking issues with work in progress [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant