Skip to content

Commit 82f888b

Browse files
authored
Merge branch 'trunk' into update/docs-annotation
2 parents 4731ff3 + 76f9cea commit 82f888b

14 files changed

+193
-15
lines changed

docs/1.intro.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ It acts as a central registry, making it easier for different parts of WordPress
1212
- **Registry:** A central, singleton object (`WP_Abilities_Registry`) that holds all registered abilities. It provides methods for registering, unregistering, finding, and querying abilities.
1313
- **Callback:** The PHP function or method executed when an ability is called via `WP_Ability::execute()`.
1414
- **Schema:** JSON Schema definitions for an ability's expected input (`input_schema`) and its returned output (`output_schema`). This allows for validation and helps agents understand how to use the ability.
15-
- **Permission Callback:** An optional function that determines if the current user can execute a specific ability.
15+
- **Permission Callback:** An optional function that determines if the current user can execute a specific ability.
1616
- **Namespace:** The first part of an ability name (before the slash), typically matching the plugin or component name that registers the ability.
1717

1818
## Goals and Benefits
@@ -76,7 +76,8 @@ function my_plugin_register_ability(){
7676
'execute_callback' => 'my_plugin_get_siteinfo',
7777
'permission_callback' => function( $input ) {
7878
return current_user_can( 'manage_options' );
79-
}
79+
},
80+
'show_in_rest' => true,
8081
));
8182
}
8283
```

docs/2.getting-started.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ function my_plugin_register_abilities() {
124124
'meta' => array(
125125
'category' => 'site-info',
126126
),
127+
'show_in_rest' => true, // Optional: expose via REST API
127128
) );
128129
}
129130

docs/3.registering-abilities.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ The `$args` array accepts the following keys:
3232
- `readonly` (`bool`): Whether the ability only reads data without modifying its environment (default: `false`).
3333
- `destructive` (`bool`): Whether the ability may perform destructive updates to its environment. If `true`, the ability may perform any type of modification, including deletions or other destructive changes. If `false`, the ability performs only additive updates (default: `true`).
3434
- `idempotent` (`bool`): Whether calling the ability repeatedly with the same arguments will have no additional effect on its environment (default: `false`).
35+
- `show_in_rest` (`boolean`, **Optional**): Whether to expose this ability via the REST API. Default: `false`.
36+
- When `true`, the ability will be listed in REST API responses and can be executed via REST endpoints.
37+
- When `false`, the ability will be hidden from REST API listings and cannot be executed via REST endpoints, but remains available for internal PHP usage.
3538
- `meta` (`array`, **Optional**): An associative array for storing arbitrary additional metadata about the ability.
3639

3740
## Ability ID Convention

docs/5.rest-api.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ The WordPress Abilities API provides REST endpoints that allow external systems
66

77
Access to all Abilities REST API endpoints requires an authenticated user (see the [Authentication](#authentication) section). Access to execute individual Abilities is restricted based on the `permission_callback()` of the Ability.
88

9+
## Controlling REST API Exposure
10+
11+
By default, registered abilities are **not** exposed via the REST API. You can control whether an individual ability appears in the REST API by using the `show_in_rest` argument when registering the ability:
12+
13+
- `show_in_rest => true`: The ability is listed in REST API responses and can be executed via REST endpoints.
14+
- `show_in_rest => false` (default): The ability is hidden from REST API listings and cannot be executed via REST endpoints. The ability remains available for internal PHP usage via `wp_execute_ability()`.
15+
16+
Abilities with `show_in_rest => false` will return a `rest_ability_not_found` error if accessed via REST endpoints.
17+
918
## Schema
1019

1120
The Abilities API endpoints are available under the `/wp/v2/abilities` namespace.

includes/abilities-api.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
* alphanumeric characters, dashes and the forward slash.
2626
* @param array<string,mixed> $args An associative array of arguments for the ability. This should include
2727
* `label`, `description`, `input_schema`, `output_schema`, `execute_callback`,
28-
* `permission_callback`, `annotations`, `meta`, and `ability_class`.
28+
* `permission_callback`, `annotations`, `meta`, `show_in_rest`, and `ability_class`.
2929
* @return ?\WP_Ability An instance of registered ability on success, null on failure.
3030
*
3131
* @phpstan-param array{
@@ -37,6 +37,7 @@
3737
* output_schema?: array<string,mixed>,
3838
* annotations?: array<string,mixed>,
3939
* meta?: array<string,mixed>,
40+
* show_in_rest?: bool,
4041
* ability_class?: class-string<\WP_Ability>,
4142
* ...<string, mixed>
4243
* } $args

includes/abilities-api/class-wp-abilities-registry.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ final class WP_Abilities_Registry {
5959
* output_schema?: array<string,mixed>,
6060
* annotations?: array<string,mixed>,
6161
* meta?: array<string,mixed>,
62+
* show_in_rest?: bool,
6263
* ability_class?: class-string<\WP_Ability>,
6364
* ...<string, mixed>
6465
* } $args

includes/abilities-api/class-wp-ability.php

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,14 @@ class WP_Ability {
116116
*/
117117
protected $meta = array();
118118

119+
/**
120+
* Whether to show the ability in the REST API.
121+
*
122+
* @since n.e.x.t
123+
* @var bool
124+
*/
125+
protected $show_in_rest = false;
126+
119127
/**
120128
* Constructor.
121129
*
@@ -128,9 +136,9 @@ class WP_Ability {
128136
* @see wp_register_ability()
129137
*
130138
* @param string $name The name of the ability, with its namespace.
131-
* @param array<string,mixed> $args An associative array of arguments for the ability. This should
132-
* include `label`, `description`, `input_schema`, `output_schema`,
133-
* `execute_callback`, `permission_callback`, `annotations`, and `meta`.
139+
* @param array<string,mixed> $args An associative array of arguments for the ability. This should include
140+
* `label`, `description`, `input_schema`, `output_schema`, `execute_callback`,
141+
* `permission_callback`, `annotations`, `meta`, and `show_in_rest`.
134142
*/
135143
public function __construct( string $name, array $args ) {
136144
$this->name = $name;
@@ -180,6 +188,7 @@ public function __construct( string $name, array $args ) {
180188
* output_schema?: array<string,mixed>,
181189
* annotations?: array<string,mixed>,
182190
* meta?: array<string,mixed>,
191+
* show_in_rest?: bool,
183192
* ...<string, mixed>,
184193
* } $args
185194
*/
@@ -234,6 +243,12 @@ protected function prepare_properties( array $args ): array {
234243
);
235244
}
236245

246+
if ( isset( $args['show_in_rest'] ) && ! is_bool( $args['show_in_rest'] ) ) {
247+
throw new \InvalidArgumentException(
248+
esc_html__( 'The ability properties should provide a valid `show_in_rest` boolean.' )
249+
);
250+
}
251+
237252
// Set defaults for optional args.
238253
$args['annotations'] = wp_parse_args(
239254
$args['annotations'] ?? array(),
@@ -321,6 +336,17 @@ public function get_meta(): array {
321336
return $this->meta;
322337
}
323338

339+
/**
340+
* Checks whether the ability should be shown in the REST API.
341+
*
342+
* @since n.e.x.t
343+
*
344+
* @return bool True if the ability should be shown in the REST API, false otherwise.
345+
*/
346+
public function show_in_rest(): bool {
347+
return $this->show_in_rest;
348+
}
349+
324350
/**
325351
* Validates input data against the input schema.
326352
*

includes/rest-api/endpoints/class-wp-rest-abilities-list-controller.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,12 @@ public function register_routes(): void {
9494
* @return \WP_REST_Response Response object on success.
9595
*/
9696
public function get_items( $request ) {
97-
$abilities = wp_get_abilities();
97+
$abilities = array_filter(
98+
wp_get_abilities(),
99+
static function ( $ability ) {
100+
return $ability->show_in_rest();
101+
}
102+
);
98103

99104
// Handle pagination with explicit defaults.
100105
$params = $request->get_params();
@@ -150,8 +155,7 @@ public function get_items( $request ) {
150155
*/
151156
public function get_item( $request ) {
152157
$ability = wp_get_ability( $request->get_param( 'name' ) );
153-
154-
if ( ! $ability ) {
158+
if ( ! $ability || ! $ability->show_in_rest() ) {
155159
return new \WP_Error(
156160
'rest_ability_not_found',
157161
__( 'Ability not found.' ),

includes/rest-api/endpoints/class-wp-rest-abilities-run-controller.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ public function run_ability( $request ) {
154154
*/
155155
public function run_ability_permissions_check( $request ) {
156156
$ability = wp_get_ability( $request->get_param( 'name' ) );
157-
if ( ! $ability ) {
157+
if ( ! $ability || ! $ability->show_in_rest() ) {
158158
return new \WP_Error(
159159
'rest_ability_not_found',
160160
__( 'Ability not found.' ),

tests/unit/abilities-api/wpAbilitiesRegistry.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public function set_up(): void {
6262
'meta' => array(
6363
'category' => 'math',
6464
),
65+
'show_in_rest' => true,
6566
);
6667
}
6768

@@ -297,6 +298,21 @@ public function test_register_invalid_meta_type() {
297298
$this->assertNull( $result );
298299
}
299300

301+
/**
302+
* Should reject ability registration with invalid show in REST type.
303+
*
304+
* @covers WP_Abilities_Registry::register
305+
* @covers WP_Ability::prepare_properties
306+
*
307+
* @expectedIncorrectUsage WP_Abilities_Registry::register
308+
*/
309+
public function test_register_invalid_show_in_rest_type() {
310+
self::$test_ability_args['show_in_rest'] = 5;
311+
312+
$result = $this->registry->register( self::$test_ability_name, self::$test_ability_args );
313+
$this->assertNull( $result );
314+
}
315+
300316
/**
301317
* Should reject registration for already registered ability.
302318
*

0 commit comments

Comments
 (0)