Skip to content

Commit 448075d

Browse files
committed
chore: merge trunk and resolve phpcs.xml.dist conflict
2 parents f1f2dc8 + c9abf12 commit 448075d

File tree

8 files changed

+574
-12
lines changed

8 files changed

+574
-12
lines changed

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
- [Getting Started](docs/2.getting-started.md)
2323
- [Registering Abilities](docs/3.registering-abilities.md)
2424
- [Using Abilities](docs/4.using-abilities.md)
25+
- [REST API Reference](docs/5.rest-api.md)
26+
- [Hooks](docs/6.hooks.md)
2527
- [Contributing Guidelines](CONTRIBUTING.md)
2628

2729
## Inspiration
@@ -33,18 +35,18 @@
3335
## Current Status
3436

3537
| Milestone | State |
36-
| ----------------------------------- |-------------|
38+
| ----------------------------------- | ----------- |
3739
| Placeholder repository | **created** |
38-
| Spec draft | in progress |
39-
| Prototype plugin & Composer package | in progress |
40-
| Community feedback (#core‑ai Slack) | planned |
40+
| Spec draft | **created** |
41+
| Prototype plugin & Composer package | **created** |
42+
| Community feedback (#core‑ai Slack) | in progress |
4143
| Core proposal | planned |
4244

4345
## How to Get Involved
4446

4547
- **Discuss:** `#core-ai` channel on WordPress Slack.
4648
- **File issues:** suggestions & use‑cases welcome in this repo.
47-
- **Prototype:** experiment with the upcoming Composer package once released.
49+
- **Prototype:** experiment with the [feature plugin](https://github.com/WordPress/abilities-api/releases/latest) or the [`wordpress/abilities-api`](https://packagist.org/packages/wordpress/abilities-api) Composer package.
4850

4951
## License
5052

docs/5.rest-api.md

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
# 5. REST API Reference
2+
3+
The WordPress Abilities API provides REST endpoints that allow external systems to discover and execute abilities via HTTP requests.
4+
5+
## User access
6+
7+
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.
8+
9+
## Schema
10+
11+
The Abilities API endpoints are available under the `/wp/v2/abilities` namespace.
12+
13+
### Ability Object
14+
15+
Abilities are represented in JSON with the following structure:
16+
17+
```json
18+
{
19+
"name": "my-plugin/get-site-info",
20+
"label": "Get Site Information",
21+
"description": "Retrieves basic information about the WordPress site.",
22+
"output_schema": {
23+
"type": "object",
24+
"properties": {
25+
"name": {
26+
"type": "string",
27+
"description": "Site name"
28+
},
29+
"url": {
30+
"type": "string",
31+
"format": "uri",
32+
"description": "Site URL"
33+
}
34+
}
35+
},
36+
"meta": {}
37+
}
38+
```
39+
40+
## List Abilities
41+
42+
### Definition
43+
44+
`GET /wp/v2/abilities`
45+
46+
### Arguments
47+
48+
- `page` _(integer)_: Current page of the collection. Default: `1`.
49+
- `per_page` _(integer)_: Maximum number of items to return per page. Default: `50`, Maximum: `100`.
50+
51+
### Example Request
52+
53+
```bash
54+
curl https://example.com/wp-json/wp/v2/abilities
55+
```
56+
57+
### Example Response
58+
59+
```json
60+
[
61+
{
62+
"name": "my-plugin/get-site-info",
63+
"label": "Get Site Information",
64+
"description": "Retrieves basic information about the WordPress site.",
65+
"output_schema": {
66+
"type": "object",
67+
"properties": {
68+
"name": {
69+
"type": "string",
70+
"description": "Site name"
71+
},
72+
"url": {
73+
"type": "string",
74+
"format": "uri",
75+
"description": "Site URL"
76+
}
77+
}
78+
},
79+
"meta": {}
80+
}
81+
]
82+
```
83+
84+
## Retrieve an Ability
85+
86+
### Definition
87+
88+
`GET /wp/v2/abilities/(?P<namespace>[a-z0-9-]+)/(?P<ability>[a-z0-9-]+)`
89+
90+
### Arguments
91+
92+
- `namespace` _(string)_: The namespace part of the ability name.
93+
- `ability` _(string)_: The ability name part.
94+
95+
### Example Request
96+
97+
```bash
98+
curl https://example.com/wp-json/wp/v2/abilities/my-plugin/get-site-info
99+
```
100+
101+
### Example Response
102+
103+
```json
104+
{
105+
"name": "my-plugin/get-site-info",
106+
"label": "Get Site Information",
107+
"description": "Retrieves basic information about the WordPress site.",
108+
"output_schema": {
109+
"type": "object",
110+
"properties": {
111+
"name": {
112+
"type": "string",
113+
"description": "Site name"
114+
},
115+
"url": {
116+
"type": "string",
117+
"format": "uri",
118+
"description": "Site URL"
119+
}
120+
}
121+
},
122+
"meta": {}
123+
}
124+
```
125+
126+
## Execute an Ability
127+
128+
### Definition
129+
130+
`POST /wp/v2/abilities/(?P<namespace>[a-z0-9-]+)/(?P<ability>[a-z0-9-]+)/run`
131+
132+
### Arguments
133+
134+
- `namespace` _(string)_: The namespace part of the ability name.
135+
- `ability` _(string)_: The ability name part.
136+
- `input` _(integer|number|boolean|string|array|object|null)_: Optional input data for the ability as defined by its input schema.
137+
138+
### Example Request (No Input)
139+
140+
```bash
141+
curl -X POST https://example.com/wp-json/wp/v2/abilities/my-plugin/get-site-info/run
142+
```
143+
144+
### Example Request (With Input)
145+
146+
```bash
147+
curl -X POST \
148+
-H "Content-Type: application/json" \
149+
-d '{"input":{"option_name":"blogname","option_value":"New Site Name"}}' \
150+
https://example.com/wp-json/wp/v2/abilities/my-plugin/update-option/run
151+
```
152+
153+
### Example Response (Success)
154+
155+
```json
156+
{
157+
"name": "My WordPress Site",
158+
"url": "https://example.com"
159+
}
160+
```
161+
162+
### Example Response (Error)
163+
164+
```json
165+
{
166+
"code": "ability_invalid_permissions",
167+
"message": "Ability \"my-plugin/update-option\" does not have necessary permission.",
168+
"data": {
169+
"status": 403
170+
}
171+
}
172+
```
173+
174+
## Authentication
175+
176+
The Abilities API supports all WordPress REST API authentication methods:
177+
178+
- Cookie authentication (same-origin requests)
179+
- Application passwords (recommended for external access)
180+
- Custom authentication plugins
181+
182+
### Using Application Passwords
183+
184+
```bash
185+
curl -u 'USERNAME:APPLICATION_PASSWORD' \
186+
https://example.com/wp-json/wp/v2/abilities
187+
```
188+
189+
## Error Responses
190+
191+
The API returns standard WordPress REST API error responses with these common codes:
192+
193+
- `ability_missing_input_schema` – the ability requires input but none was provided.
194+
- `ability_invalid_input` - input validation failed according to the ability's schema.
195+
- `ability_invalid_permissions` - current user lacks permission to execute the ability.
196+
- `ability_invalid_output` - output validation failed according to the ability's schema.
197+
- `ability_invalid_execute_callback` - the ability's execute callback is not callable.
198+
- `rest_ability_not_found` - the requested ability is not registered.
199+
- `rest_ability_invalid_method` - the requested HTTP method is not allowed for executing the selected ability.
200+
- `rest_ability_cannot_execute` - the ability cannot be executed due to insufficient permissions.

docs/6.hooks.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# 6. Hooks
2+
3+
The Abilities API provides [WordPress Action Hooks](https://developer.wordpress.org/apis/hooks/) that allow developers to monitor and respond to ability execution events.
4+
5+
## Available Actions
6+
7+
### `before_execute_ability`
8+
9+
Fires immediately before an ability gets executed, after permission checks have passed but before the execution callback is called.
10+
11+
```php
12+
/**
13+
* Fires before an ability gets executed.
14+
*
15+
* @since n.e.x.t
16+
*
17+
* @param string $ability_name The name of the ability.
18+
* @param mixed $input The input data for the ability.
19+
*/
20+
do_action( 'before_execute_ability', $ability_name, $input );
21+
```
22+
23+
**Parameters:**
24+
25+
- `$ability_name` (`string`): The namespaced name of the ability being executed (e.g., `my-plugin/get-posts`).
26+
- `$input` (`mixed`): The input data passed to the ability.
27+
28+
### `after_execute_ability`
29+
30+
Fires immediately after an ability has finished executing successfully, after output validation has passed.
31+
32+
```php
33+
/**
34+
* Fires immediately after an ability finished executing.
35+
*
36+
* @since n.e.x.t
37+
*
38+
* @param string $ability_name The name of the ability.
39+
* @param mixed $input The input data for the ability.
40+
* @param mixed $result The result of the ability execution.
41+
*/
42+
do_action( 'after_execute_ability', $ability_name, $input, $result );
43+
```
44+
45+
**Parameters:**
46+
47+
- `$ability_name` (`string`): The namespaced name of the ability that was executed.
48+
- `$input` (`mixed`): The input data that was passed to the ability.
49+
- `$result` (`mixed`): The validated result returned by the ability's execution callback.
50+
51+
## Usage Examples
52+
53+
**Basic Logging**
54+
55+
```php
56+
// Log all ability executions.
57+
add_action( 'before_execute_ability', function( $ability_name, $input ) {
58+
error_log( 'Executing ability: ' . $ability_name );
59+
if ( $input !== null ) {
60+
error_log( 'Input: ' . wp_json_encode( $input ) );
61+
}
62+
}, 10, 2 );
63+
64+
add_action( 'after_execute_ability', function( $ability_name, $input, $result ) {
65+
error_log( 'Completed ability: ' . $ability_name );
66+
error_log( 'Result: ' . wp_json_encode( $result ) );
67+
}, 10, 3 );
68+
```

includes/abilities-api.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
* @package WordPress
88
* @subpackage Abilities_API
99
* @since 0.1.0
10-
*
11-
* phpcs:disable WordPress.NamingConventions.PrefixAllGlobals
1210
*/
1311

1412
declare( strict_types = 1 );

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,14 +416,38 @@ public function execute( $input = null ) {
416416
);
417417
}
418418

419+
/**
420+
* Fires before an ability gets executed.
421+
*
422+
* @since n.e.x.t
423+
*
424+
* @param string $ability_name The name of the ability.
425+
* @param mixed $input The input data for the ability.
426+
*/
427+
do_action( 'before_execute_ability', $this->name, $input );
428+
419429
$result = $this->do_execute( $input );
420430
if ( is_wp_error( $result ) ) {
421431
return $result;
422432
}
423433

424434
$is_valid = $this->validate_output( $result );
435+
if ( is_wp_error( $is_valid ) ) {
436+
return $is_valid;
437+
}
425438

426-
return is_wp_error( $is_valid ) ? $is_valid : $result;
439+
/**
440+
* Fires immediately after an ability finished executing.
441+
*
442+
* @since n.e.x.t
443+
*
444+
* @param string $ability_name The name of the ability.
445+
* @param mixed $input The input data for the ability.
446+
* @param mixed $result The result of the ability execution.
447+
*/
448+
do_action( 'after_execute_ability', $this->name, $input, $result );
449+
450+
return $result;
427451
}
428452

429453
/**

phpcs.xml.dist

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,10 @@
193193

194194
<!-- Plugin-specific rule configs -->
195195
<rule ref="WordPress.NamingConventions.PrefixAllGlobals">
196+
<exclude-pattern>includes/abilities-api.php</exclude-pattern>
197+
<exclude-pattern>includes/abilities-api/*</exclude-pattern>
196198
<properties>
197199
<property name="prefixes" type="array">
198-
<element value="abilities_api_" /><!-- Hook prefix -->
199-
<element value="WP_Ability" />
200-
<element value="WP_Abilities" />
201200
<element value="WP_Abilities_Assets_Init" /><!-- Asset loader -->
202201
<element value="WP_REST_Abilities" />
203202
<element value="WP_ABILITIES_API" /><!-- Constant -->

0 commit comments

Comments
 (0)