Skip to content

Add core/terms-query ability - #1099

Draft
jorgefilipecosta wants to merge 19 commits into
developfrom
add/core-terms-query
Draft

jorgefilipecosta wants to merge 19 commits into
developfrom
add/core-terms-query

Conversation

@jorgefilipecosta

@jorgefilipecosta jorgefilipecosta commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

What?

Adds core/terms-query, a read-only ability for categories, tags, and other taxonomy terms (#1063).

How?

  • The ability lives in includes/Abilities/Terms/Terms.php, behind the Custom Abilities experiment.
  • Three modes: a term by id (optionally guarded by taxonomy), a term by taxonomy and slug, or the terms of one taxonomy filtered by search, include, exclude, parent, post, hide_empty, orderby, order, page, and per_page, returned as { terms, total, total_pages }.
  • Taxonomies opt in with show_in_abilities, like post types do for core/content-query. Show_In_Abilities marks category and post_tag.
  • Fields: id, count, description, link, name, slug, taxonomy, and parent (hierarchical taxonomies only). The default set leaves out description and link, and id is always returned.

Testing Instructions

  1. Enable the Custom Abilities experiment.
  2. Run core/terms-query with { "taxonomy": "category" }, { "id": 1 }, and { "taxonomy": "category", "slug": "uncategorized" }.
  3. npm run test:php -- --filter 'Terms|Show_In_Abilities|Gated_Abilities'
  4. npm run test:e2e -- tests/e2e/specs/abilities/core-terms-query.spec.js

Changelog Entry

Added - New core/terms-query ability that reads categories, tags, and other taxonomy terms like the REST API terms endpoints.

Open WordPress Playground Preview

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

✅ WordPress Plugin Check Report

✅ Status: Passed

📊 Report

All checks passed! No errors or warnings found.


🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

@codecov

codecov Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.38337% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.10%. Comparing base (04e09f0) to head (bb95001).
⚠️ Report is 1 commits behind head on develop.

Files with missing lines Patch % Lines
includes/Abilities/Terms/Terms.php 98.25% 7 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             develop    #1099      +/-   ##
=============================================
+ Coverage      81.55%   82.10%   +0.55%     
- Complexity      3072     3167      +95     
=============================================
  Files            129      131       +2     
  Lines          12256    12676     +420     
=============================================
+ Hits            9995    10408     +413     
- Misses          2261     2268       +7     
Flag Coverage Δ
unit 82.10% <98.38%> (+0.55%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jorgefilipecosta

Copy link
Copy Markdown
Member Author

Tested in the browser console on WordPress 7.1.2, from a post's editor with the Excerpt Generation and Custom Abilities experiments enabled (Excerpt Generation puts @wordpress/abilities and @wordpress/core-abilities in the import map).

Test data: categories Fruit (169) with children Apple (170, one post) and Citrus (171), Vegetables (172) and Uncategorized (1); tags Red (173, one post) and Green (174); post 32 in Apple and Red.

await ( await import( '@wordpress/core-abilities' ) ).ready;
const { executeAbility } = await import( '@wordpress/abilities' );

Query the terms of a taxonomy

await executeAbility( 'core/terms-query', { taxonomy: 'category' } );
// { terms: [
//   { id: 170, count: 1, name: 'Apple', slug: 'apple', taxonomy: 'category', parent: 169 },
//   { id: 171, count: 0, name: 'Citrus', slug: 'citrus', taxonomy: 'category', parent: 169 },
//   { id: 169, count: 0, name: 'Fruit', slug: 'fruit', taxonomy: 'category', parent: 0 },
//   { id: 1, count: 0, name: 'Uncategorized', slug: 'uncategorized', taxonomy: 'category', parent: 0 },
//   { id: 172, count: 0, name: 'Vegetables', slug: 'vegetables', taxonomy: 'category', parent: 0 },
// ], total: 5, total_pages: 1 }

await executeAbility( 'core/terms-query', { taxonomy: 'category', parent: 169, hide_empty: true } );
// { terms: [ { id: 170, count: 1, name: 'Apple', slug: 'apple', taxonomy: 'category', parent: 169 } ], total: 1, total_pages: 1 }

// Tags aren't hierarchical, so they have no parent.
await executeAbility( 'core/terms-query', { taxonomy: 'post_tag', post: 32 } );
// { terms: [ { id: 173, count: 1, name: 'Red', slug: 'red', taxonomy: 'post_tag' } ], total: 1, total_pages: 1 }

await executeAbility( 'core/terms-query', { taxonomy: 'category', orderby: 'id', order: 'desc', per_page: 2, page: 2 } );
// { terms: [
//   { id: 170, count: 1, name: 'Apple', slug: 'apple', taxonomy: 'category', parent: 169 },
//   { id: 169, count: 0, name: 'Fruit', slug: 'fruit', taxonomy: 'category', parent: 0 },
// ], total: 5, total_pages: 3 }

// The ID is always included.
await executeAbility( 'core/terms-query', { taxonomy: 'category', search: 'apple', fields: [ 'name', 'description', 'link' ] } );
// { terms: [ { id: 170, description: 'Crisp and sweet.', link: 'http://localhost:8896/?cat=170', name: 'Apple' } ], total: 1, total_pages: 1 }

await executeAbility( 'core/terms-query', { taxonomy: 'category', include: [ 171, 169 ], orderby: 'include' } );
// { terms: [
//   { id: 171, count: 0, name: 'Citrus', slug: 'citrus', taxonomy: 'category', parent: 169 },
//   { id: 169, count: 0, name: 'Fruit', slug: 'fruit', taxonomy: 'category', parent: 0 },
// ], total: 2, total_pages: 1 }

Get a single term by ID

await executeAbility( 'core/terms-query', { id: 170 } );
// { id: 170, count: 1, name: 'Apple', slug: 'apple', taxonomy: 'category', parent: 169 }

Get a single term by taxonomy and slug

await executeAbility( 'core/terms-query', { taxonomy: 'post_tag', slug: 'red' } );
// { id: 173, count: 1, name: 'Red', slug: 'red', taxonomy: 'post_tag' }

Errors

// A term outside the given taxonomy is denied the same way as a missing one.
await executeAbility( 'core/terms-query', { id: 173, taxonomy: 'category' } );
await executeAbility( 'core/terms-query', { id: 999999 } );
// Both reject with { code: 'rest_ability_cannot_execute', message: 'Sorry, you are not allowed to execute this ability.', data: { status: 403 } }

await executeAbility( 'core/terms-query', { taxonomy: 'category', post: 999999 } );
// Rejects with { code: 'terms_post_invalid_id', message: 'Invalid post ID.', data: { status: 400 } }

// The client rejects these before sending a request, with an Error whose code is 'ability_invalid_input'.
await executeAbility( 'core/terms-query', { id: 170, per_page: 5 } ); // Modes can't be mixed.
await executeAbility( 'core/terms-query', { slug: 'red' } ); // A slug needs a taxonomy.
await executeAbility( 'core/terms-query', { taxonomy: 'nav_menu' } ); // Not exposed to abilities.

@gziolo

gziolo commented Oct 2, 2026

Copy link
Copy Markdown
Member

See my #1063 (comment) – this duplicates efforts started by @muneeb-ashraf in #1084.

@jeffpaul

jeffpaul commented Oct 4, 2026

Copy link
Copy Markdown
Member

@jorgefilipecosta note that I'm holding off on requesting reviews until this comes out of draft status

@jeffpaul jeffpaul linked an issue Oct 4, 2026 that may be closed by this pull request
@jeffpaul jeffpaul added this to the 1.5.0 milestone Oct 4, 2026
…re-terms-query

# Conflicts:
#	tests/Integration/Includes/Abilities/Gated/Gated_AbilitiesTest.php
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Status] Duplicate This issue or pull request already exists

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a core/terms-query ability (taxonomies, categories, tags)

3 participants