-
Notifications
You must be signed in to change notification settings - Fork 43
Add Filtering Capabilities for Registered Abilities #115
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
Open
galatanovidiu
wants to merge
15
commits into
trunk
Choose a base branch
from
feature/filter-registered-abilities
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,632
−4
Open
Changes from 12 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
01cff2f
feat(abilities-api): Introduce WP_Abilities_Query class
galatanovidiu 46d4711
feat(abilities-api): Add filtering capabilities to wp_get_abilities
galatanovidiu 3ebeb37
test(abilities-api): Add unit tests for WP_Abilities_Query
galatanovidiu 45d3917
docs(abilities-api): Add documentation for querying and filtering abi…
galatanovidiu f114dae
Refactor `WP_Abilities_Query` for compatibility
galatanovidiu c89f085
Remove redundant empty args check in wp_get_abilities()
galatanovidiu 2ca7dae
Clarifies array type annotations in documentation
galatanovidiu 68fea1b
Rename validation methods to sanitization methods
galatanovidiu de10fa7
Clarifies abilities retrieval and filtering doc
galatanovidiu 74c0990
Enforces non-negative offset and valid limit in pagination
galatanovidiu 844dddb
Refactor sanitize_pagination_args to use early exit pattern
galatanovidiu 937c778
Merge branch 'trunk' into feature/filter-registered-abilities
galatanovidiu d3275fd
Refactor ability query args to a reusable PHPStan type
galatanovidiu 863b73e
Harden WP_Abilities_Query as an internal class
galatanovidiu 8a5c01f
Update includes/abilities-api/class-wp-abilities-query.php
galatanovidiu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,213 @@ | ||
| # 8. Querying and Filtering Abilities | ||
|
|
||
| The Abilities API provides powerful filtering capabilities through the `WP_Abilities_Query` class and the `wp_get_abilities()` function. This allows you to efficiently find and retrieve specific abilities from potentially thousands of registered abilities. | ||
|
|
||
| `wp_get_abilities()` returns an array of `WP_Ability` objects, keyed by ability name. | ||
|
|
||
| When no abilities match the query, an empty array is returned. | ||
|
|
||
| Invalid query parameters are normalized to safe defaults. | ||
|
|
||
| ## Overview | ||
|
|
||
| When working with large numbers of abilities registered by core and various plugins, the query system provides optimized server-side filtering. You can pass query arguments to `wp_get_abilities()` to filter abilities by category, namespace, meta properties, and more. | ||
|
|
||
| ```php | ||
| // Get all abilities | ||
| $abilities = wp_get_abilities(); | ||
|
|
||
| // Filter by category | ||
| $abilities = wp_get_abilities( array( 'category' => 'data-retrieval' ) ); | ||
|
|
||
| // Combine multiple filters | ||
| $abilities = wp_get_abilities( array( | ||
| 'namespace' => 'my-plugin', | ||
| 'category' => 'communication', | ||
| 'orderby' => 'label', | ||
| ) ); | ||
| ``` | ||
|
|
||
| ## Quick Reference: Query Parameters | ||
|
|
||
| | Parameter | Type | Default | Description | | ||
| |-----------|------|---------|-------------| | ||
| | `category` | string\|array | `''` | Filter by category slug. Accepts single value or array for multiple categories (OR logic) | | ||
| | `namespace` | string\|array | `''` | Filter by namespace. Accepts single value or array for multiple namespaces (OR logic) | | ||
| | `search` | string | `''` | Search in name, label, and description (case-insensitive) | | ||
| | `meta` | array | `array()` | Filter by meta properties using nested arrays (AND logic between multiple meta filters) | | ||
| | `orderby` | string | `''` | Sort by: `'name'`, `'label'`, or `'category'`. Empty = no sorting | | ||
| | `order` | string | `'ASC'` | Sort direction: `'ASC'` or `'DESC'` | | ||
| | `limit` | int | `-1` | Maximum results to return. `-1` = unlimited | | ||
| | `offset` | int | `0` | Number of results to skip | | ||
|
|
||
| ## Basic Filtering | ||
|
|
||
| ### Filter by Category | ||
|
|
||
| ```php | ||
| // Get all data retrieval abilities | ||
| $abilities = wp_get_abilities( array( 'category' => 'data-retrieval' ) ); | ||
|
|
||
| // Get all communication abilities | ||
| $abilities = wp_get_abilities( array( 'category' => 'communication' ) ); | ||
|
|
||
| // Get abilities from multiple categories (OR logic) | ||
| $abilities = wp_get_abilities( array( | ||
| 'category' => array( 'math', 'communication', 'data-retrieval' ), | ||
| ) ); | ||
| ``` | ||
|
|
||
| ### Filter by Namespace | ||
|
|
||
| Namespace is the part before the `/` in the ability name (e.g., `my-plugin` in `my-plugin/send-email`). | ||
|
|
||
| ```php | ||
| // Get all abilities from your plugin | ||
| $abilities = wp_get_abilities( array( 'namespace' => 'my-plugin' ) ); | ||
|
|
||
| // Get all WooCommerce abilities | ||
| $abilities = wp_get_abilities( array( 'namespace' => 'woocommerce' ) ); | ||
|
|
||
| // Get abilities from multiple namespaces (OR logic) | ||
| $abilities = wp_get_abilities( array( | ||
| 'namespace' => array( 'my-plugin', 'woocommerce', 'jetpack' ), | ||
| ) ); | ||
| ``` | ||
|
|
||
| ### Search Abilities | ||
|
|
||
| Search is case-insensitive and searches in name, label, and description: | ||
|
|
||
| ```php | ||
| // Find all abilities related to email | ||
| $abilities = wp_get_abilities( array( 'search' => 'email' ) ); | ||
|
|
||
| // Find payment-related abilities | ||
| $abilities = wp_get_abilities( array( 'search' => 'payment' ) ); | ||
| ``` | ||
|
|
||
| ### Combine Multiple Filters | ||
|
|
||
| Filters are cumulative (AND logic): | ||
|
|
||
| ```php | ||
| // Get communication abilities from my-plugin only | ||
| $abilities = wp_get_abilities( array( | ||
| 'category' => 'communication', | ||
| 'namespace' => 'my-plugin', | ||
| ) ); | ||
|
|
||
| // Search for email abilities in the communication category | ||
| $abilities = wp_get_abilities( array( | ||
| 'category' => 'communication', | ||
| 'search' => 'email', | ||
| ) ); | ||
| ``` | ||
|
|
||
| ## Meta Filtering | ||
|
|
||
| Filter abilities by their meta properties, including `show_in_rest`, `annotations`, and custom meta keys. All meta filters use AND logic — abilities must match all specified criteria. | ||
|
|
||
| ### Filter by REST API Visibility | ||
|
|
||
| ```php | ||
| // Get abilities exposed in REST API | ||
| $abilities = wp_get_abilities( array( | ||
| 'meta' => array( | ||
| 'show_in_rest' => true, | ||
| ), | ||
| ) ); | ||
|
|
||
| // Get abilities hidden from REST API | ||
| $abilities = wp_get_abilities( array( | ||
| 'meta' => array( | ||
| 'show_in_rest' => false, | ||
| ), | ||
| ) ); | ||
| ``` | ||
|
|
||
| ### Filter by Annotations | ||
|
|
||
| ```php | ||
| // Get readonly abilities | ||
| $abilities = wp_get_abilities( array( | ||
| 'meta' => array( | ||
| 'annotations' => array( | ||
| 'readonly' => true, | ||
| ), | ||
| ), | ||
| ) ); | ||
|
|
||
| // Get non-destructive, idempotent abilities | ||
| $abilities = wp_get_abilities( array( | ||
| 'meta' => array( | ||
| 'annotations' => array( | ||
| 'destructive' => false, | ||
| 'idempotent' => true, | ||
| ), | ||
| ), | ||
| ) ); | ||
| ``` | ||
|
|
||
| ### Combine Multiple Meta Filters | ||
|
|
||
| When you specify multiple meta conditions, abilities must match all of them (AND logic): | ||
|
|
||
| ```php | ||
| // Get readonly abilities that are exposed in REST API | ||
| $abilities = wp_get_abilities( array( | ||
| 'meta' => array( | ||
| 'show_in_rest' => true, | ||
| 'annotations' => array( | ||
| 'readonly' => true, | ||
| ), | ||
| ), | ||
| ) ); | ||
|
|
||
| // Get REST-enabled, readonly, idempotent abilities | ||
| $abilities = wp_get_abilities( array( | ||
| 'meta' => array( | ||
| 'show_in_rest' => true, | ||
| 'annotations' => array( | ||
| 'readonly' => true, | ||
| 'idempotent' => true, | ||
| ), | ||
| ), | ||
| ) ); | ||
| ``` | ||
|
|
||
| ### Filter by Custom Meta | ||
|
|
||
| You can filter by any custom meta keys you've added to abilities: | ||
|
|
||
| ```php | ||
| $abilities = wp_get_abilities( array( | ||
| 'meta' => array( | ||
| 'custom_key' => 'custom_value', | ||
| 'another_meta' => 'another_value', | ||
| ), | ||
| ) ); | ||
| ``` | ||
|
|
||
| ## Ordering and Pagination | ||
|
|
||
| ```php | ||
| // Order by name, label, or category | ||
| $abilities = wp_get_abilities( array( | ||
| 'orderby' => 'label', | ||
| 'order' => 'ASC', // or 'DESC' | ||
| ) ); | ||
|
|
||
| // Paginate results | ||
| $abilities = wp_get_abilities( array( | ||
| 'limit' => 10, | ||
| 'offset' => 0, | ||
| ) ); | ||
| ``` | ||
|
|
||
| ## See Also | ||
|
|
||
| - [Registering Abilities](3.registering-abilities.md) - How to register abilities with proper metadata | ||
| - [Using Abilities](4.using-abilities.md) - Basic ability usage, execution, and permissions | ||
| - [Registering Categories](7.registering-categories.md) - How to register ability categories | ||
| - [REST API](5.rest-api.md) - REST API endpoints for abilities | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a specific need for pagination?
I see that you're trying to mirror
WP_Queryet al (versus adding sorting/filtering as registry methods) but abilities are in a PHP array, not a database. Do we really need a shortcut for what's essentially anarray_slice()?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filtering abilities are the most crucial aspect from my perspective. Ordering and pagination are nice-to-haves, but I want to acknowledge that they fit well together in the proposed implementation, as they allow easy selection of a precise number of abilities that meet specific criteria, which might be useful when passing data to an LLM with limited context. @galatanovidiu might have a better overview of the real needs based on the work he has done for the MCP Adapter.