Make WordPress Core

Opened 14 hours ago

Last modified 14 hours ago

#66281 new enhancement

Taxonomy: Add description to the fields searched by WP_Term_Query / admin term search

Reported by: abditsori Owned by:
Priority: normal Milestone: Awaiting Review
Component: Taxonomy Version:
Severity: normal Keywords: has-patch has-unit-tests
Cc: Focuses:

Description

WP_Term_Query::get_search_sql() hardcodes its search matching to
just two columns:

return $wpdb->prepare( '((t.name LIKE %s) OR (t.slug LIKE %s))', $like, $like );

A term's description (stored on wp_term_taxonomy) is never
considered, even though:

  • wp_term_taxonomy is already unconditionally INNER JOINed into every term query (it's where taxonomy, parent, and count come from too), so no new join is required to reach description.
  • A description__like arg already exists for exact-field LIKE matching — it's just never combined with search.

Because edit-tags.php?taxonomy=X is the single shared admin screen
for every taxonomy (Categories, Tags, Link Categories, and any custom
taxonomy with an admin UI all use the same WP_Terms_List_Table
class), this affects all of them identically: searching the admin
term list only matches name/slug, never description, with no way to
opt in short of hooking terms_clauses and hand-building a `tt.description
LIKE` clause in a plugin.

Steps to reproduce:

  1. Create a category (or tag) with a short, generic name but a distinctive description, e.g. name "Misc", description containing the word "pineapple".
  2. Go to Posts > Categories (or Posts > Tags) in wp-admin.
  3. Search for "pineapple".

Expected: the term is found, since "pineapple" appears in its
description.

Actual: no results — only name/slug are searched.

Suggested fix: add an opt-in search_columns query var to
WP_Term_Query (accepting 'name', 'slug', 'description';
default empty array, preserving today's name+slug-only behavior for
every existing caller), and have get_search_sql() build its OR'd
LIKE clause from the configured columns instead of the hardcoded
pair — mirroring the existing user_search_columns pattern already
used by WP_User_Query. WP_Terms_List_Table::prepare_items() then
opts in to all three columns for the admin search box (both the
get_terms() call and the wp_count_terms() pagination count, so the
displayed total stays consistent with the actual results).

Change History (1)

This ticket was mentioned in ​PR #14138 on ​WordPress/wordpress-develop by ​@abditsori.


14 hours ago
#1

  • Keywords has-patch has-unit-tests added

Trac ticket: https://core.trac.wordpress.org/ticket/66281

Summary

The admin Categories/Tags search box (edit-tags.php?taxonomy=X) only ever matched a term's name or slug. WP_Term_Query::get_search_sql() hardcodes ((t.name LIKE %s) OR (t.slug LIKE %s)) — it never considers tt.description, even though wp_term_taxonomy (where description lives) is already unconditionally INNER JOINed for every term query, and a description__like arg already exists for exact-field matching (just not combined with search).

Since edit-tags.php is a single shared admin screen for every taxonomy (parameterized by ?taxonomy=, always using the same WP_Terms_List_Table class), this isn't Categories-specific — it fixes Tags, Categories, and any custom taxonomy with an admin UI at once.

Changes

  • Added an opt-in search_columns query var to WP_Term_Query (default array(), preserving today's name+slug-only behavior for every existing caller of get_terms()/WP_Term_Query). Accepts 'name', 'slug', 'description'.
  • get_search_sql() now builds its OR'd LIKE clause from the configured columns instead of being hardcoded to two columns. Mirrors WP_User_Query's user_search_columns pattern, including an equivalent term_search_columns filter for parity.
  • WP_Terms_List_Table::prepare_items() opts in to array( 'name', 'slug', 'description' ) for both the get_terms() call and the wp_count_terms() pagination count (so the "X items" total stays consistent with what's actually returned).
  • Verified the default ((t.name LIKE %s) OR (t.slug LIKE %s)) SQL string is byte-identical to before when search_columns isn't passed, so zero behavior change for any existing caller.

Test plan

  • [x] php -l on all three changed files.
  • [x] Added test_get_terms_search_does_not_match_description_by_default and test_get_terms_search_columns_can_include_description to getTerms.php.
  • [x] Ran tests/phpunit/tests/term/getTerms.php (116 tests) and tests/phpunit/tests/term/query.php (43 tests) — all passing.
  • [x] Ran the full --group taxonomy suite (911 tests) — all passing, one pre-existing unrelated PHPUnit-version warning.
  • [x] End-to-end verification through the real WP_Terms_List_Table::prepare_items() path for both category and post_tag taxonomies: a term matched only by description is found, a non-matching term is excluded, for both.
Note: See TracTickets for help on using tickets.