16 Commits

Author SHA1 Message Date
gziolo 2c2a769281 Abilities API: Add wp_ability_invoked action
Introduces a new `wp_ability_invoked` action that fires at the start of `WP_Ability::execute()`, before input normalization, validation, or permission checks. This gives observers a reliable entry point for every invocation regardless of outcome (short-circuit, validation failure, permission denial, or successful execution).

Also extends the existing `wp_before_execute_ability` and `wp_after_execute_ability` actions with a new `$ability` parameter exposing the `WP_Ability` instance.

Follow-up for #64989.

Props sukhendu2002, peterwilsoncc, gziolo.
Fixes #65248.




Built from https://develop.svn.wordpress.org/trunk@62418


git-svn-id: http://core.svn.wordpress.org/trunk@61699 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2026-05-26 08:15:43 +00:00
Sergey Biryukov e138887f3a Docs: Remove extra $args in WP_Ability_Category::prepare_properties().
Follow-up to [61032].

Props thriveteam, westonruter.
Fixes #65109.
Built from https://develop.svn.wordpress.org/trunk@62416


git-svn-id: http://core.svn.wordpress.org/trunk@61697 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2026-05-25 21:36:37 +00:00
gziolo ffa39fdccd Abilities API: Stop HTML-escaping the ability name in WP_Error messages
Ability names are pattern-validated at registration, so `esc_html()` on them is always a no-op. Drop it from the `WP_Error` messages, which are commonly serialized to JSON where the escaping would be incorrect.

Follow-up to [62398].
See #64311.


Built from https://develop.svn.wordpress.org/trunk@62401


git-svn-id: http://core.svn.wordpress.org/trunk@61682 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2026-05-21 10:28:39 +00:00
gziolo 766edbe807 Abilities API: Add filters for input and output validation
Introduce the `wp_ability_validate_input` and `wp_ability_validate_output` filters so developers can layer custom validation on top of the default JSON
Schema checks, either augmenting an existing WP_Error or rejecting otherwise valid data.

Props priethor, gziolo, westonruter, enej.
Fixes #64311.


Built from https://develop.svn.wordpress.org/trunk@62398


git-svn-id: http://core.svn.wordpress.org/trunk@61679 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2026-05-21 08:32:42 +00:00
gziolo 8e76f7215a Abilities API: Add execution lifecycle filters to WP_Ability methods
Introduce four filters that give plugins hook points across the ability execution lifecycle, complementing the existing observation-only actions
(`wp_before_execute_ability`, `wp_after_execute_ability`):

- `wp_pre_execute_ability`: short-circuits `execute()` when it returns a value other than the supplied default.
- `wp_ability_normalize_input`: transforms input inside `normalize_input()`, and returning `WP_Error` halts execution.
- `wp_ability_permission_result`: overrides the `permission_callback` result inside `check_permissions()`, consistently for `execute()` and direct callers.
- `wp_ability_execute_result`: transforms the result inside `do_execute()` before output validation, and can recover from execute callback failures.

The input and result filters fire before their respective schema validation steps, so `validate_input()` and `validate_output()` remain the final integrity gates. Only `wp_pre_execute_ability` can bypass validation, with the caller owning the returned value's shape.

Add `WP_Filter_Sentinel`, a reusable marker class loaded alongside `WP_Hook`, whose per-instance identity lets a filter default be distinguished from any
user value — including `null`, `false`, or arbitrary objects — via `===`.

Update `WP_REST_Abilities_V1_Run_Controller::check_ability_permissions()` to propagate `WP_Error` results from `normalize_input()` directly, defaulting to
status 400 while preserving filter-set statuses (e.g. 422, 429).

Props gziolo, westonruter, migueluy.
Fixes #64989.


Built from https://develop.svn.wordpress.org/trunk@62397


git-svn-id: http://core.svn.wordpress.org/trunk@61678 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2026-05-21 07:57:42 +00:00
gziolo 34c56ec658 Abilities API: Catch exceptions thrown by ability callbacks and return WP_Error.
Wraps `invoke_callback()` in a try/catch so that exceptions thrown by execute or permission callbacks are converted to a `WP_Error` with the `ability_callback_exception` code instead of propagating as uncaught throwables.

Developed in: https://github.com/WordPress/wordpress-develop/pull/11544

Props priyankagusani, jamesgiroux, jeffpaul, dkotter, adamsilverstein, justlevine, jorbin, pavanpatil1.
Fixes #65058.


Built from https://develop.svn.wordpress.org/trunk@62238


git-svn-id: http://core.svn.wordpress.org/trunk@61518 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2026-04-16 07:24:05 +00:00
Aaron Jorbin 239e8edce5 Abilities API: Revert Allow nested namespace ability names.
Abilities should follow the same pattern as all other namespaces and use a single namespace.

Reverts [61602].

See #64596.
Props jorgefilipecosta, justlevine, audrasjb.

Built from https://develop.svn.wordpress.org/trunk@62094


git-svn-id: http://core.svn.wordpress.org/trunk@61376 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2026-03-23 19:41:51 +00:00
jorgefilipecosta d6192305d3 Abilities API: Allow nested namespace ability names (2-4 segments).
Expand ability name validation from exactly 2 segments (`namespace/ability`) to 2-4 segments, enabling names like `my-plugin/resource/find` and `my-plugin/resource/sub/find`.
This allows plugins to organize abilities into logical resource groups. The validation regex changes from `/^[a-z0-9-]+\/[a-z0-9-]+$/` to `/^[a-z0-9-]+(?:\/[a-z0-9-]+){1,3}$/`, which accepts the first segment plus 1-3 additional slash-delimited segments.
Updates the validation regex, error messages, docblocks, and adds corresponding unit and REST API tests.

Props jorgefilipecosta, justlevine, jorbin.
Fixes #64596.
Built from https://develop.svn.wordpress.org/trunk@61602


git-svn-id: http://core.svn.wordpress.org/trunk@60913 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2026-02-09 17:00:43 +00:00
John Blackbourn 6fa9fcb3dc Docs: Remove redundant syntax from callable type declarations.
The parameter name is optional in PHPStan but not supported by Psalm. While neither tools are officially supported, this removes the parse error that Psalm users otherwise see.

See https://github.com/php-stubs/wordpress-stubs/issues/410 for some external discussion.

Props farhad0, marian1

See #64224

Built from https://develop.svn.wordpress.org/trunk@61505


git-svn-id: http://core.svn.wordpress.org/trunk@60816 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2026-01-21 12:15:33 +00:00
Weston Ruter a8a7f9da23 Docs: Fix grammatical error in docs for WP_Ability::prepare_properties().
Follow-up to [61032].

Props hbhalodia.
See #64098.
Fixes #64503.

Built from https://develop.svn.wordpress.org/trunk@61483


git-svn-id: http://core.svn.wordpress.org/trunk@60795 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2026-01-14 20:25:54 +00:00
jorgefilipecosta c3ad8bbe52 Abilities API: Enhance WP_Ability validation for execute_callback and permission_callback.
Abilities API allows for extending WP_Ability by providing ability_class during the ability registration. This is meant to unlock complex abilities holding some sort of state or logic that requires multiple helper methods.
In all of those scenarios you would ovewrite execute or do_execute method.
However, because the check for execute_callback is in constructor, then in order to register an ability with ability_class overwrite, you have to BOTH: provide do_execute and provide a dummy execute_callback. The same need happens for permission_callback.
This commit fixes the issue execute_callback and permission_callback are now optional when a class is provided. 


Props artpi, swissspidy, jorgefilipecosta, mindctrl.
Fixes #64407.
Built from https://develop.svn.wordpress.org/trunk@61390


git-svn-id: http://core.svn.wordpress.org/trunk@60702 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2025-12-17 15:29:38 +00:00
gziolo f6b747ff6f Abilities API: Improve annotations documentation and add permission callback validation
Code quality changes included:
- Expands `annotations` parameter documentation with detailed descriptions for readonly,
destructive, and idempotent properties.
- Standardizes type order from `null|bool` to `bool|null` per coding standards.
- Adds validation check to ensure permission callback is callable before invocation.

Developed in https://github.com/WordPress/wordpress-develop/pull/10431.

Follow-up for [61067], [61032].
See #64134.


Built from https://develop.svn.wordpress.org/trunk@61086


git-svn-id: http://core.svn.wordpress.org/trunk@60422 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2025-10-29 13:45:35 +00:00
gziolo ed37a97f8c Abilities API: Code quality fixes around translations
This aligns with how translations are handled across all places in the Abilities API codebase. It addresses the feedback raised during syncing back changes to Abilities API repository with https://github.com/WordPress/abilities-api/pull/126.

Developed in https://github.com/WordPress/wordpress-develop/pull/10424.

Follow-up [61032].
Props gziolo, jorgefilipecosta.
See #64098.


Built from https://develop.svn.wordpress.org/trunk@61071


git-svn-id: http://core.svn.wordpress.org/trunk@60407 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2025-10-27 11:57:35 +00:00
gziolo 1f1e5dfdd5 Abilities API: Ensure public method is used in the codebase
Discovered when syncing code back to Abilities API repository in https://github.com/WordPress/abilities-api/pull/126.

Follow-up to [61032].
See #64098.


Built from https://develop.svn.wordpress.org/trunk@61059


git-svn-id: http://core.svn.wordpress.org/trunk@60395 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2025-10-24 11:57:30 +00:00
gziolo 7aa1b7ef5b Abilities API: Normalize input from schema
Without this patch REST API would require a weird empty `?input` field for optional input given how the current controller works with input schema when it defines the expected shape. This patch normalizes the input for the ability, applying the default value from the input schema when needed.

Developed in https://github.com/WordPress/wordpress-develop/pull/10395.

Follow-up [61032], [61045].

Props gziolo, jorgefilipecosta, mukesh27.
Fixes #64139.



Built from https://develop.svn.wordpress.org/trunk@61047


git-svn-id: http://core.svn.wordpress.org/trunk@60383 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2025-10-22 15:04:30 +00:00
gziolo d3fe16afc4 Abilities API: Introduce server-side registry and REST API endpoints
Feature proposal at https://make.wordpress.org/ai/2025/07/17/abilities-api/.
Project developed in https://github.com/WordPress/abilities-api.

Introduces a new Abilities API that allows WordPress plugins and themes to register and execute custom abilities with built-in permission checking, input/output validation via JSON Schema, and REST API integration.

## Public Functions

### Ability Management
- `wp_register_ability( string $name, array $args ): ?WP_Ability` - Registers a new ability (must be called on `wp_abilities_api_init` hook)
- `wp_unregister_ability( string $name ): ?WP_Ability` - Unregisters an ability
- `wp_has_ability( string $name ): bool` - Checks if an ability is registered
- `wp_get_ability( string $name ): ?WP_Ability` - Retrieves a registered ability
- `wp_get_abilities(): array` - Retrieves all registered abilities

### Ability Category Management
- `wp_register_ability_category( string $slug, array $args ): ?WP_Ability_Category` - Registers an ability category (must be called on `wp_abilities_api_categories_init` hook)
- `wp_unregister_ability_category( string $slug ): ?WP_Ability_Category` - Unregisters an ability category
- `wp_has_ability_category( string $slug ): bool` - Checks if an ability category is registered
- `wp_get_ability_category( string $slug ): ?WP_Ability_Category` - Retrieves a registered ability category
- `wp_get_ability_categories(): array` - Retrieves all registered ability categories

## Public Classes

- `WP_Ability` - Encapsulates ability properties and methods (execute, check_permission, validate_input, etc.)
- `WP_Ability_Category` - Encapsulates ability category properties
- `WP_Abilities_Registry` - Manages ability registration and lookup (private, accessed via functions)
- `WP_Ability_Categories_Registry` - Manages ability category registration (private, accessed via functions)
- `WP_REST_Abilities_V1_List_Controller` - REST controller for listing abilities
- `WP_REST_Abilities_V1_Run_Controller` - REST controller for executing abilities

## REST API Endpoints

### Namespace: `wp-abilities/v1`

#### List Abilities
- `GET /wp-abilities/v1/abilities` - Retrieve all registered abilities
  - Query parameters: `page`, `per_page`, `category`

#### Get Single Ability
- `GET /wp-abilities/v1/abilities/(?P<name>[a-zA-Z0-9\-\/]+)` - Retrieve a specific ability by name

#### Execute Ability
- `GET|POST|DELETE /wp-abilities/v1/abilities/(?P<name>[a-zA-Z0-9\-\/]+)/run` - Execute an ability
  - Supports multiple HTTP methods based on ability annotations
  - Validates input against ability's input schema
  - Validates output against ability's output schema
  - Performs permission checks via ability's permission callback

## Hooks

### Actions
- `wp_abilities_api_categories_init` - Fired when ability categories registry is initialized (register categories here)
- `wp_abilities_api_init` - Fired when abilities registry is initialized (register abilities here)
- `wp_before_execute_ability` - Fired before an ability gets executed, after input validation and permissions check

- `wp_after_execute_ability` - Fires immediately after an ability finished executing

### Filters
- `wp_register_ability_category_args` - Filters ability category arguments before registration
- `wp_register_ability_args` - Filters ability arguments before registration

Developed in https://github.com/WordPress/wordpress-develop/pull/9410.

Props gziolo, jorbin, justlevine, westonruter, jason_the_adams, flixos90, karmatosed, timothyblynjacobs.
Fixes #64098.



Built from https://develop.svn.wordpress.org/trunk@61032


git-svn-id: http://core.svn.wordpress.org/trunk@60368 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2025-10-21 13:52:27 +00:00