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: Retain flat term order #64471

Closed
wants to merge 4 commits into from
Closed

Conversation

ockham
Copy link
Contributor

@ockham ockham commented Aug 13, 2024

What?

See #65052.

Why?

To retain the order in which "flat terms" (such as tags) are stored for a given post.

How?

Sort the terms obtained via getEntityRecords by the array of term IDs that reflects the order in which they were added by the user to the current post.

TODO

  • We might want to respect the sort setting that's provided to register_taxonomy to determine whether terms should be stored in the order they're given by the user (if sort === true, somewhat counter-intuitively), or if we should continue to sort them alphabetically.

Whether terms in this taxonomy should be sorted in the order they are provided to wp_set_object_terms(). Default null which equates to false.

Testing 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 order is kept (unlike previously, when they were re-ordered in alphabetical order). Note however that when saving the post, the terms are still sorted alphabetically, and their previous order is lost. See WordPress/wordpress-develop#7287 for a WIP fix.

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 or screencast

Before After
flat-terms-before flat-terms-after

@ockham ockham added the [Type] Enhancement A suggestion for improvement. label Aug 13, 2024
@ockham ockham self-assigned this Aug 13, 2024
Copy link

github-actions bot commented Aug 13, 2024

Size Change: +8 B (0%)

Total Size: 1.82 MB

Filename Size Change
build/editor/index.min.js 112 kB +8 B (+0.01%)
ℹ️ View Unchanged
Filename Size
build-module/a11y/index.min.js 482 B
build-module/block-library/file/view.min.js 447 B
build-module/block-library/image/view.min.js 1.78 kB
build-module/block-library/navigation/view.min.js 1.16 kB
build-module/block-library/query/view.min.js 742 B
build-module/block-library/search/view.min.js 616 B
build-module/interactivity-router/index.min.js 3.03 kB
build-module/interactivity/debug.min.js 17.2 kB
build-module/interactivity/index.min.js 13.6 kB
build/a11y/index.min.js 952 B
build/annotations/index.min.js 2.26 kB
build/api-fetch/index.min.js 2.32 kB
build/autop/index.min.js 2.12 kB
build/blob/index.min.js 579 B
build/block-directory/index.min.js 7.26 kB
build/block-directory/style-rtl.css 1 kB
build/block-directory/style.css 1 kB
build/block-editor/content-rtl.css 4.42 kB
build/block-editor/content.css 4.41 kB
build/block-editor/default-editor-styles-rtl.css 394 B
build/block-editor/default-editor-styles.css 394 B
build/block-editor/index.min.js 255 kB
build/block-editor/style-rtl.css 15.4 kB
build/block-editor/style.css 15.4 kB
build/block-library/blocks/archives/editor-rtl.css 84 B
build/block-library/blocks/archives/editor.css 83 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 149 B
build/block-library/blocks/audio/editor.css 151 B
build/block-library/blocks/audio/style-rtl.css 132 B
build/block-library/blocks/audio/style.css 132 B
build/block-library/blocks/audio/theme-rtl.css 134 B
build/block-library/blocks/audio/theme.css 134 B
build/block-library/blocks/avatar/editor-rtl.css 115 B
build/block-library/blocks/avatar/editor.css 115 B
build/block-library/blocks/avatar/style-rtl.css 104 B
build/block-library/blocks/avatar/style.css 104 B
build/block-library/blocks/button/editor-rtl.css 265 B
build/block-library/blocks/button/editor.css 265 B
build/block-library/blocks/button/style-rtl.css 555 B
build/block-library/blocks/button/style.css 555 B
build/block-library/blocks/buttons/editor-rtl.css 291 B
build/block-library/blocks/buttons/editor.css 291 B
build/block-library/blocks/buttons/style-rtl.css 345 B
build/block-library/blocks/buttons/style.css 345 B
build/block-library/blocks/calendar/style-rtl.css 240 B
build/block-library/blocks/calendar/style.css 240 B
build/block-library/blocks/categories/editor-rtl.css 132 B
build/block-library/blocks/categories/editor.css 131 B
build/block-library/blocks/categories/style-rtl.css 152 B
build/block-library/blocks/categories/style.css 152 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 139 B
build/block-library/blocks/code/style.css 139 B
build/block-library/blocks/code/theme-rtl.css 122 B
build/block-library/blocks/code/theme.css 122 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 420 B
build/block-library/blocks/columns/style.css 420 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 124 B
build/block-library/blocks/comment-author-avatar/editor.css 124 B
build/block-library/blocks/comment-author-name/style-rtl.css 72 B
build/block-library/blocks/comment-author-name/style.css 72 B
build/block-library/blocks/comment-content/style-rtl.css 120 B
build/block-library/blocks/comment-content/style.css 120 B
build/block-library/blocks/comment-date/style-rtl.css 65 B
build/block-library/blocks/comment-date/style.css 65 B
build/block-library/blocks/comment-edit-link/style-rtl.css 70 B
build/block-library/blocks/comment-edit-link/style.css 70 B
build/block-library/blocks/comment-reply-link/style-rtl.css 71 B
build/block-library/blocks/comment-reply-link/style.css 71 B
build/block-library/blocks/comment-template/style-rtl.css 200 B
build/block-library/blocks/comment-template/style.css 199 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 228 B
build/block-library/blocks/comments-pagination/editor.css 217 B
build/block-library/blocks/comments-pagination/style-rtl.css 234 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 837 B
build/block-library/blocks/comments/editor.css 836 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 637 B
build/block-library/blocks/cover/editor-rtl.css 631 B
build/block-library/blocks/cover/editor.css 631 B
build/block-library/blocks/cover/style-rtl.css 1.7 kB
build/block-library/blocks/cover/style.css 1.69 kB
build/block-library/blocks/details/editor-rtl.css 65 B
build/block-library/blocks/details/editor.css 65 B
build/block-library/blocks/details/style-rtl.css 86 B
build/block-library/blocks/details/style.css 86 B
build/block-library/blocks/embed/editor-rtl.css 331 B
build/block-library/blocks/embed/editor.css 331 B
build/block-library/blocks/embed/style-rtl.css 419 B
build/block-library/blocks/embed/style.css 419 B
build/block-library/blocks/embed/theme-rtl.css 133 B
build/block-library/blocks/embed/theme.css 133 B
build/block-library/blocks/file/editor-rtl.css 326 B
build/block-library/blocks/file/editor.css 326 B
build/block-library/blocks/file/style-rtl.css 278 B
build/block-library/blocks/file/style.css 279 B
build/block-library/blocks/footnotes/style-rtl.css 198 B
build/block-library/blocks/footnotes/style.css 197 B
build/block-library/blocks/form-input/editor-rtl.css 229 B
build/block-library/blocks/form-input/editor.css 229 B
build/block-library/blocks/form-input/style-rtl.css 357 B
build/block-library/blocks/form-input/style.css 357 B
build/block-library/blocks/form-submission-notification/editor-rtl.css 344 B
build/block-library/blocks/form-submission-notification/editor.css 341 B
build/block-library/blocks/form-submit-button/style-rtl.css 69 B
build/block-library/blocks/form-submit-button/style.css 69 B
build/block-library/blocks/form/view.min.js 470 B
build/block-library/blocks/freeform/editor-rtl.css 2.6 kB
build/block-library/blocks/freeform/editor.css 2.6 kB
build/block-library/blocks/gallery/editor-rtl.css 946 B
build/block-library/blocks/gallery/editor.css 951 B
build/block-library/blocks/gallery/style-rtl.css 1.83 kB
build/block-library/blocks/gallery/style.css 1.82 kB
build/block-library/blocks/gallery/theme-rtl.css 108 B
build/block-library/blocks/gallery/theme.css 108 B
build/block-library/blocks/group/editor-rtl.css 334 B
build/block-library/blocks/group/editor.css 334 B
build/block-library/blocks/group/style-rtl.css 103 B
build/block-library/blocks/group/style.css 103 B
build/block-library/blocks/group/theme-rtl.css 79 B
build/block-library/blocks/group/theme.css 79 B
build/block-library/blocks/heading/style-rtl.css 188 B
build/block-library/blocks/heading/style.css 188 B
build/block-library/blocks/html/editor-rtl.css 346 B
build/block-library/blocks/html/editor.css 347 B
build/block-library/blocks/image/editor-rtl.css 799 B
build/block-library/blocks/image/editor.css 799 B
build/block-library/blocks/image/style-rtl.css 1.59 kB
build/block-library/blocks/image/style.css 1.59 kB
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/latest-comments/style-rtl.css 355 B
build/block-library/blocks/latest-comments/style.css 354 B
build/block-library/blocks/latest-posts/editor-rtl.css 139 B
build/block-library/blocks/latest-posts/editor.css 138 B
build/block-library/blocks/latest-posts/style-rtl.css 509 B
build/block-library/blocks/latest-posts/style.css 510 B
build/block-library/blocks/list/style-rtl.css 107 B
build/block-library/blocks/list/style.css 107 B
build/block-library/blocks/loginout/style-rtl.css 61 B
build/block-library/blocks/loginout/style.css 61 B
build/block-library/blocks/media-text/editor-rtl.css 321 B
build/block-library/blocks/media-text/editor.css 320 B
build/block-library/blocks/media-text/style-rtl.css 552 B
build/block-library/blocks/media-text/style.css 550 B
build/block-library/blocks/more/editor-rtl.css 427 B
build/block-library/blocks/more/editor.css 427 B
build/block-library/blocks/navigation-link/editor-rtl.css 644 B
build/block-library/blocks/navigation-link/editor.css 645 B
build/block-library/blocks/navigation-link/style-rtl.css 192 B
build/block-library/blocks/navigation-link/style.css 191 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 295 B
build/block-library/blocks/navigation-submenu/editor.css 294 B
build/block-library/blocks/navigation/editor-rtl.css 2.2 kB
build/block-library/blocks/navigation/editor.css 2.2 kB
build/block-library/blocks/navigation/style-rtl.css 2.25 kB
build/block-library/blocks/navigation/style.css 2.23 kB
build/block-library/blocks/nextpage/editor-rtl.css 392 B
build/block-library/blocks/nextpage/editor.css 392 B
build/block-library/blocks/page-list/editor-rtl.css 378 B
build/block-library/blocks/page-list/editor.css 378 B
build/block-library/blocks/page-list/style-rtl.css 192 B
build/block-library/blocks/page-list/style.css 192 B
build/block-library/blocks/paragraph/editor-rtl.css 236 B
build/block-library/blocks/paragraph/editor.css 236 B
build/block-library/blocks/paragraph/style-rtl.css 341 B
build/block-library/blocks/paragraph/style.css 340 B
build/block-library/blocks/post-author-biography/style-rtl.css 74 B
build/block-library/blocks/post-author-biography/style.css 74 B
build/block-library/blocks/post-author-name/style-rtl.css 69 B
build/block-library/blocks/post-author-name/style.css 69 B
build/block-library/blocks/post-author/editor-rtl.css 107 B
build/block-library/blocks/post-author/editor.css 107 B
build/block-library/blocks/post-author/style-rtl.css 188 B
build/block-library/blocks/post-author/style.css 189 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 527 B
build/block-library/blocks/post-comments-form/style.css 528 B
build/block-library/blocks/post-content/style-rtl.css 61 B
build/block-library/blocks/post-content/style.css 61 B
build/block-library/blocks/post-date/style-rtl.css 62 B
build/block-library/blocks/post-date/style.css 62 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 155 B
build/block-library/blocks/post-excerpt/style.css 155 B
build/block-library/blocks/post-featured-image/editor-rtl.css 729 B
build/block-library/blocks/post-featured-image/editor.css 726 B
build/block-library/blocks/post-featured-image/style-rtl.css 347 B
build/block-library/blocks/post-featured-image/style.css 347 B
build/block-library/blocks/post-navigation-link/style-rtl.css 215 B
build/block-library/blocks/post-navigation-link/style.css 214 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 399 B
build/block-library/blocks/post-template/style.css 398 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-time-to-read/style-rtl.css 70 B
build/block-library/blocks/post-time-to-read/style.css 70 B
build/block-library/blocks/post-title/style-rtl.css 162 B
build/block-library/blocks/post-title/style.css 162 B
build/block-library/blocks/preformatted/style-rtl.css 125 B
build/block-library/blocks/preformatted/style.css 125 B
build/block-library/blocks/pullquote/editor-rtl.css 134 B
build/block-library/blocks/pullquote/editor.css 134 B
build/block-library/blocks/pullquote/style-rtl.css 342 B
build/block-library/blocks/pullquote/style.css 342 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 121 B
build/block-library/blocks/query-pagination-numbers/editor.css 118 B
build/block-library/blocks/query-pagination/editor-rtl.css 154 B
build/block-library/blocks/query-pagination/editor.css 154 B
build/block-library/blocks/query-pagination/style-rtl.css 237 B
build/block-library/blocks/query-pagination/style.css 237 B
build/block-library/blocks/query-title/style-rtl.css 64 B
build/block-library/blocks/query-title/style.css 64 B
build/block-library/blocks/query/editor-rtl.css 452 B
build/block-library/blocks/query/editor.css 451 B
build/block-library/blocks/quote/style-rtl.css 238 B
build/block-library/blocks/quote/style.css 238 B
build/block-library/blocks/quote/theme-rtl.css 233 B
build/block-library/blocks/quote/theme.css 236 B
build/block-library/blocks/read-more/style-rtl.css 138 B
build/block-library/blocks/read-more/style.css 138 B
build/block-library/blocks/rss/editor-rtl.css 101 B
build/block-library/blocks/rss/editor.css 101 B
build/block-library/blocks/rss/style-rtl.css 288 B
build/block-library/blocks/rss/style.css 287 B
build/block-library/blocks/search/editor-rtl.css 199 B
build/block-library/blocks/search/editor.css 199 B
build/block-library/blocks/search/style-rtl.css 672 B
build/block-library/blocks/search/style.css 671 B
build/block-library/blocks/search/theme-rtl.css 113 B
build/block-library/blocks/search/theme.css 113 B
build/block-library/blocks/separator/editor-rtl.css 100 B
build/block-library/blocks/separator/editor.css 100 B
build/block-library/blocks/separator/style-rtl.css 248 B
build/block-library/blocks/separator/style.css 248 B
build/block-library/blocks/separator/theme-rtl.css 195 B
build/block-library/blocks/separator/theme.css 195 B
build/block-library/blocks/shortcode/editor-rtl.css 286 B
build/block-library/blocks/shortcode/editor.css 286 B
build/block-library/blocks/site-logo/editor-rtl.css 806 B
build/block-library/blocks/site-logo/editor.css 803 B
build/block-library/blocks/site-logo/style-rtl.css 218 B
build/block-library/blocks/site-logo/style.css 218 B
build/block-library/blocks/site-tagline/editor-rtl.css 87 B
build/block-library/blocks/site-tagline/editor.css 87 B
build/block-library/blocks/site-tagline/style-rtl.css 65 B
build/block-library/blocks/site-tagline/style.css 65 B
build/block-library/blocks/site-title/editor-rtl.css 85 B
build/block-library/blocks/site-title/editor.css 85 B
build/block-library/blocks/site-title/style-rtl.css 143 B
build/block-library/blocks/site-title/style.css 143 B
build/block-library/blocks/social-link/editor-rtl.css 273 B
build/block-library/blocks/social-link/editor.css 273 B
build/block-library/blocks/social-links/editor-rtl.css 729 B
build/block-library/blocks/social-links/editor.css 727 B
build/block-library/blocks/social-links/style-rtl.css 1.51 kB
build/block-library/blocks/social-links/style.css 1.5 kB
build/block-library/blocks/spacer/editor-rtl.css 346 B
build/block-library/blocks/spacer/editor.css 346 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table-of-contents/style-rtl.css 83 B
build/block-library/blocks/table-of-contents/style.css 83 B
build/block-library/blocks/table/editor-rtl.css 394 B
build/block-library/blocks/table/editor.css 394 B
build/block-library/blocks/table/style-rtl.css 640 B
build/block-library/blocks/table/style.css 639 B
build/block-library/blocks/table/theme-rtl.css 152 B
build/block-library/blocks/table/theme.css 152 B
build/block-library/blocks/tag-cloud/editor-rtl.css 144 B
build/block-library/blocks/tag-cloud/editor.css 144 B
build/block-library/blocks/tag-cloud/style-rtl.css 266 B
build/block-library/blocks/tag-cloud/style.css 265 B
build/block-library/blocks/template-part/editor-rtl.css 368 B
build/block-library/blocks/template-part/editor.css 368 B
build/block-library/blocks/template-part/theme-rtl.css 113 B
build/block-library/blocks/template-part/theme.css 113 B
build/block-library/blocks/term-description/style-rtl.css 126 B
build/block-library/blocks/term-description/style.css 126 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 165 B
build/block-library/blocks/text-columns/style.css 165 B
build/block-library/blocks/verse/style-rtl.css 98 B
build/block-library/blocks/verse/style.css 98 B
build/block-library/blocks/video/editor-rtl.css 396 B
build/block-library/blocks/video/editor.css 397 B
build/block-library/blocks/video/style-rtl.css 192 B
build/block-library/blocks/video/style.css 192 B
build/block-library/blocks/video/theme-rtl.css 134 B
build/block-library/blocks/video/theme.css 134 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.08 kB
build/block-library/common.css 1.08 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11.6 kB
build/block-library/editor.css 11.6 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/index.min.js 221 kB
build/block-library/reset-rtl.css 472 B
build/block-library/reset.css 472 B
build/block-library/style-rtl.css 15 kB
build/block-library/style.css 15 kB
build/block-library/theme-rtl.css 708 B
build/block-library/theme.css 712 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.87 kB
build/blocks/index.min.js 52.6 kB
build/commands/index.min.js 16.1 kB
build/commands/style-rtl.css 955 B
build/commands/style.css 952 B
build/components/index.min.js 227 kB
build/components/style-rtl.css 12.4 kB
build/components/style.css 12.4 kB
build/compose/index.min.js 12.7 kB
build/core-commands/index.min.js 3.08 kB
build/core-data/index.min.js 74.3 kB
build/customize-widgets/index.min.js 11 kB
build/customize-widgets/style-rtl.css 1.35 kB
build/customize-widgets/style.css 1.35 kB
build/data-controls/index.min.js 641 B
build/data/index.min.js 8.69 kB
build/date/index.min.js 18 kB
build/deprecated/index.min.js 458 B
build/dom-ready/index.min.js 325 B
build/dom/index.min.js 4.66 kB
build/edit-post/classic-rtl.css 578 B
build/edit-post/classic.css 580 B
build/edit-post/index.min.js 13.5 kB
build/edit-post/style-rtl.css 2.76 kB
build/edit-post/style.css 2.75 kB
build/edit-site/index.min.js 219 kB
build/edit-site/posts-rtl.css 7.51 kB
build/edit-site/posts.css 7.51 kB
build/edit-site/style-rtl.css 13.3 kB
build/edit-site/style.css 13.4 kB
build/edit-widgets/index.min.js 17.7 kB
build/edit-widgets/style-rtl.css 4.09 kB
build/edit-widgets/style.css 4.09 kB
build/editor/style-rtl.css 9.66 kB
build/editor/style.css 9.68 kB
build/element/index.min.js 4.82 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 8.05 kB
build/format-library/style-rtl.css 476 B
build/format-library/style.css 476 B
build/hooks/index.min.js 1.65 kB
build/html-entities/index.min.js 445 B
build/i18n/index.min.js 3.58 kB
build/is-shallow-equal/index.min.js 526 B
build/keyboard-shortcuts/index.min.js 1.31 kB
build/keycodes/index.min.js 1.46 kB
build/list-reusable-blocks/index.min.js 2.13 kB
build/list-reusable-blocks/style-rtl.css 852 B
build/list-reusable-blocks/style.css 852 B
build/media-utils/index.min.js 3.58 kB
build/notices/index.min.js 946 B
build/nux/index.min.js 1.62 kB
build/nux/style-rtl.css 749 B
build/nux/style.css 745 B
build/patterns/index.min.js 7.35 kB
build/patterns/style-rtl.css 687 B
build/patterns/style.css 685 B
build/plugins/index.min.js 1.86 kB
build/preferences-persistence/index.min.js 2.06 kB
build/preferences/index.min.js 2.9 kB
build/preferences/style-rtl.css 554 B
build/preferences/style.css 554 B
build/primitives/index.min.js 829 B
build/priority-queue/index.min.js 1.54 kB
build/private-apis/index.min.js 961 B
build/react-i18n/index.min.js 630 B
build/react-refresh-entry/index.min.js 9.47 kB
build/react-refresh-runtime/index.min.js 6.76 kB
build/redux-routine/index.min.js 2.7 kB
build/reusable-blocks/index.min.js 2.55 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.2 kB
build/router/index.min.js 2.11 kB
build/server-side-render/index.min.js 1.94 kB
build/shortcode/index.min.js 1.4 kB
build/style-engine/index.min.js 2.04 kB
build/token-list/index.min.js 581 B
build/url/index.min.js 3.9 kB
build/vendors/react-dom.min.js 41.7 kB
build/vendors/react-jsx-runtime.min.js 556 B
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 965 B
build/vips/index.min.js 36.2 kB
build/warning/index.min.js 250 B
build/widgets/index.min.js 7.16 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.03 kB

compressed-size-action

@ockham ockham force-pushed the fix/retain-flat-term-order branch from 958c94f to d73d159 Compare August 13, 2024 10:47
@ockham ockham force-pushed the fix/retain-flat-term-order branch from d73d159 to 9859995 Compare August 21, 2024 08:06
@ockham
Copy link
Contributor Author

ockham commented Sep 4, 2024

The server-side part that would be needed for this seems to be a bit more complex. I'll file an issue to accompany this PR and will track my findings there.

@jsnajdr
Copy link
Member

jsnajdr commented Oct 3, 2024

There's one additional caveat when it comes to sorting terms in a "natural" order. WooCommerce is adding several taxonomies, e.g., Product Categories, and lets users to sort the terms using drag&drop handles:

Screenshot 2024-10-03 at 12 50 00

This order is sorted as an order field in term meta and is supposed to be the natural order in which the terms are displayed on frontend, when there is no other order_by specified.

Therefore, the "natural" order is not always by ID, how the terms were chronologically added.

Besides Woo, there are also specialized popular plugins that add the same feature to any taxonomy.

This Woo feature currently doesn't work with Gutenberg. It probably works when the terms are listed in a classic theme using a PHP function, but i) the REST API doesn't respect this order ii) neither the Gutenberg categories block respects that when rendered by the server for the frontend. Note in the following screenshots that the "Tables" category should be the first, but it isn't:

Gutenberg:
Screenshot 2024-10-03 at 12 54 45

Frontend:
Screenshot 2024-10-03 at 12 55 12

I'm sharing this here because it seems to me that all these problems are closely related and a 100% correct patch will solve them all at once.

@ockham ockham force-pushed the fix/retain-flat-term-order branch from 9859995 to acae7f6 Compare November 12, 2024 13:18
Copy link

github-actions bot commented Nov 12, 2024

Flaky tests detected in ef8ef09.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/11918419850
📝 Reported issues:

@ockham ockham force-pushed the fix/retain-flat-term-order branch from acae7f6 to 70a8855 Compare November 19, 2024 09:59
@ockham
Copy link
Contributor Author

ockham commented Nov 19, 2024

I finally managed to get back to this. I've given this some more thought, and I think one of the key problems here is that setting sort to true in register_taxonomy only affects the order in which terms are stored; it doesn't make any statements about the order in which they're sorted when read from the DB.

This is complicated by the fact that high-level functions such as get_the_terms, get_the_term_list do not support any arguments to modify the order in which terms are listed (or any arguments to impact how they're presented, really); you have to use the lower-level wp_get_object_terms to specify those. This seems to be (at least partly) because of caching; by locking down get_the_terms and friends to only one canonical form, caching becomes much easier than if it'd had to deal with different possible ways of ordering terms.

It seems that the recommended way of defining a different sort order is at register_taxonomy time, which supports an argument called args:

Array of arguments to automatically use inside wp_get_object_terms() for this taxonomy.

For example, args => array( 'orderby' => 'term_order' ) will return terms in the order they were saved (if sort is set to true). This is found in these two unit tests in Core that actually set sort to true.

(As a corollary, I believe that using args => array( 'orderby' => /* Woo order term meta */ ) in Woo's register_taxonomy call should fix the issue that @jsnajdr described. Can you give that a try and confirm, Jarda? 😊)


This raises the question if 'sort' => true should implicitly set args => array( 'orderby' => 'term_order' ). Unit tests aside, Core doesn't really provide an answer for this, as 'sort' => true isn't used for any of its own taxonomies -- after all, categories and tags are rendered in alphabetic order.

I'm torn on this. I've started trying it out in WordPress/wordpress-develop#7287. It's working for the REST API (thus retaining term order in the editor sidebar panel), but not on the frontend, which goes through a different pipeline (via get_the_terms(). It's been a while since I've touched that code, but I think the biggest hurdle there was to default to args => array( 'orderby' => 'term_order' ) if sort is set to true, while still allowing the user to override that behavior (e.g. by setting args[ 'orderby' ] to a different value); the latter was hard if not impossible to do IIRC.

I'd be very curious to hear your thoughts on this @jsnajdr!

@ockham
Copy link
Contributor Author

ockham commented Nov 19, 2024

One more interesting find: The WP_Taxonomy class has a sort field (reflecting the register_taxonomy argument of the same name), whose PHPDoc says:

Use this in combination with `'orderby' => 'term_order'` when fetching terms.

@ockham
Copy link
Contributor Author

ockham commented Nov 19, 2024

I think I have an idea how to proceed.

  • I'll probably close Taxonomies: Return terms in term order if taxonomy is registered with sort: true wordpress-develop#7287 -- at least for now -- since the user can achieve the same effect by setting both sort to true, and args to array( 'orderby' => 'term_order' ) (as explained in this comment).
  • I'll expose args -- or at least the orderby arg -- in the taxonomies controller, and will then update the query in packages/editor/src/components/post-taxonomies/flat-term-selector.js to set orderby to whatever the taxonomies controller returns for that. (I'll do this as part of this PR, i.e. with an override class for the Taxonomies controller in the 6.8 compat layer).

@ockham ockham force-pushed the fix/retain-flat-term-order branch from f421545 to 239cee2 Compare November 19, 2024 17:13
@ockham
Copy link
Contributor Author

ockham commented Nov 20, 2024

Something doesn't sit quite right with me about querying the sort order from the network only to include in another network request -- it sounds like the server should have all the information it needs, so I'll try to think about this some more.

The big question is: If a taxonomy is registered with both sort set to true, and args => array( 'orderby' => 'term_order' ) -- why are terms still being ordered alphabetically when a new term is entered into the terms input panel? Shouldn't the endpoint respect the args (and thus the orderby) that were specified when the taxonomy was registered? 🤔

@ockham
Copy link
Contributor Author

ockham commented Nov 20, 2024

The big question is: If a taxonomy is registered with both sort set to true, and args => array( 'orderby' => 'term_order' ) -- why are terms still being ordered alphabetically when a new term is entered into the terms input panel? Shouldn't the endpoint respect the args (and thus the orderby) that were specified when the taxonomy was registered? 🤔

Getting closer to an answer. Turns out that to get the list of terms, the controller uses either wp_get_object_terms (if a post ID is specified by the network request), or get_terms (if there isn't). And while wp_get_object_terms takes the args from register_taxonomy into account, it appears that get_terms doesn't (although I haven't yet checked the entire callstack for the latter).

And the queries that flat-term-selector.js actually don't contain a post ID! So if my theory is correct, there might be a potential quick fix by including the latter in the query.

(We might still want to consider why get_terms ignores the taxonomy's default args, and if we should change that.)

@ockham
Copy link
Contributor Author

ockham commented Nov 20, 2024

So if my theory is correct, there might be a potential quick fix by including the latter in the query.

Ah, we can't really do that. The problem is that when a new term is entered by the user, it is created (via a POST request), but not yet associated with the current post. This is by design: We only want that to happen once the user clicks the 'Save' button in order to persist their changes. (Otherwise, the new term would show up on that post, even if the user ends up never saving the post.)

So it looks like we need to explore the other avenue:

We might still want to consider why get_terms ignores the taxonomy's default args, and if we should change that.

@ockham
Copy link
Contributor Author

ockham commented Nov 20, 2024

We might still want to consider why get_terms ignores the taxonomy's default args, and if we should change that.

The following works (for a taxonomy called actors) 🎉

diff --git a/lib/compat/wordpress-6.8/rest-api.php b/lib/compat/wordpress-6.8/rest-api.php
index da1b657cda0..3c465e2a487 100644
--- a/lib/compat/wordpress-6.8/rest-api.php
+++ b/lib/compat/wordpress-6.8/rest-api.php
@@ -20,3 +20,13 @@ if ( ! function_exists( 'gutenberg_add_post_type_rendering_mode' ) ) {
        }
 }
 add_action( 'rest_api_init', 'gutenberg_add_post_type_rendering_mode' );
+
+function gutenberg_respect_taxonomy_default_args( $args ) {
+       $taxonomy = $args['taxonomy'];
+       $t = get_taxonomy( $taxonomy );
+       if ( isset( $t->args ) && is_array( $t->args ) ) {
+               $args = array_merge( $args, $t->args );
+       }
+       return $args;
+}
+add_filter( 'rest_actors_query', 'gutenberg_respect_taxonomy_default_args' );

Now I'll have to see how I can generalize it 🙂

@ockham
Copy link
Contributor Author

ockham commented Nov 20, 2024

Closing in favor of #67154.

@ockham ockham closed this Nov 20, 2024
@ockham ockham deleted the fix/retain-flat-term-order branch November 20, 2024 11:42
@jsnajdr
Copy link
Member

jsnajdr commented Nov 22, 2024

As a corollary, I believe that using args => array( 'orderby' => /* Woo order term meta */ ) in Woo's register_taxonomy call should fix the issue that @jsnajdr described. Can you give that a try and confirm, Jarda?

Yes, Woo stores the custom order in an order field in term meta and WordPress has a native support for sorting by a meta value:

args => array(
  'orderby' => 'meta_value_num',
  'meta_key' => 'order'
)

Woo doesn't add these default args in register_taxonomy, but instead adds them in various filters and custom wrappers. So, listing the terms for the wp-admin/edit-tags.php page works because the query goes through a filter. I'm not so sure about the more recently added REST queries used by Gutenberg. If they don't work, it's a Woo bug where Woo should add or extend a filter that sets the orderby args.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants