Skip to content

Commit d5bcfb6

Browse files
committed
Bring the latest changes from Abilities API repo
1 parent aa2fcb7 commit d5bcfb6

File tree

8 files changed

+256
-290
lines changed

8 files changed

+256
-290
lines changed

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

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818
* @access private
1919
*/
2020
final class WP_Abilities_Registry {
21+
/**
22+
* The singleton instance of the registry.
23+
*
24+
* @since 0.1.0
25+
* @var ?self
26+
*/
27+
private static $instance = null;
28+
2129
/**
2230
* Holds the registered abilities.
2331
*
@@ -42,6 +50,17 @@ final class WP_Abilities_Registry {
4250
* include `label`, `description`, `input_schema`, `output_schema`,
4351
* `execute_callback`, `permission_callback`, and `meta`.
4452
* @return ?\WP_Ability The registered ability instance on success, null on failure.
53+
*
54+
* @phpstan-param array{
55+
* label?: string,
56+
* description?: string,
57+
* input_schema?: array<string,mixed>,
58+
* output_schema?: array<string,mixed>,
59+
* execute_callback?: callable( array<string,mixed> $input): (mixed|\WP_Error),
60+
* permission_callback?: ?callable( ?array<string,mixed> $input ): bool,
61+
* meta?: array<string,mixed>,
62+
* ...<string, mixed>
63+
* } $properties
4564
*/
4665
public function register( $name, array $properties = array() ): ?WP_Ability {
4766
$ability = null;
@@ -248,11 +267,9 @@ public function get_registered( string $name ): ?WP_Ability {
248267
* @return \WP_Abilities_Registry The main registry instance.
249268
*/
250269
public static function get_instance(): self {
251-
/** @var \WP_Abilities_Registry $wp_abilities */
252-
global $wp_abilities;
270+
if ( null === self::$instance ) {
271+
self::$instance = new self();
253272

254-
if ( empty( $wp_abilities ) ) {
255-
$wp_abilities = new self();
256273
/**
257274
* Fires when preparing abilities registry.
258275
*
@@ -263,10 +280,10 @@ public static function get_instance(): self {
263280
*
264281
* @param \WP_Abilities_Registry $instance Abilities registry object.
265282
*/
266-
do_action( 'abilities_api_init', $wp_abilities );
283+
do_action( 'abilities_api_init', self::$instance );
267284
}
268285

269-
return $wp_abilities;
286+
return self::$instance;
270287
}
271288

272289
/**

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

Lines changed: 62 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ class WP_Ability {
9999
* @param array<string,mixed> $properties An associative array of properties for the ability. This should
100100
* include `label`, `description`, `input_schema`, `output_schema`,
101101
* `execute_callback`, `permission_callback`, and `meta`.
102+
*
103+
* @phpstan-param array{
104+
* label: string,
105+
* description: string,
106+
* input_schema?: array<string,mixed>,
107+
* output_schema?: array<string,mixed>,
108+
* execute_callback: callable( array<string,mixed> $input): (mixed|\WP_Error),
109+
* permission_callback?: ?callable( ?array<string,mixed> $input ): bool,
110+
* meta?: array<string,mixed>,
111+
* } $properties
102112
*/
103113
public function __construct( string $name, array $properties ) {
104114
$this->name = $name;
@@ -180,29 +190,25 @@ public function get_meta(): array {
180190
* @since 0.1.0
181191
*
182192
* @param array<string,mixed> $input Optional. The input data to validate.
183-
* @return bool Returns true if valid, false if validation fails.
193+
* @return true|\WP_Error Returns true if valid or the WP_Error object if validation fails.
184194
*/
185-
protected function validate_input( array $input = array() ): bool {
195+
protected function validate_input( array $input = array() ) {
186196
$input_schema = $this->get_input_schema();
187197
if ( empty( $input_schema ) ) {
188198
return true;
189199
}
190200

191-
$valid_input = rest_validate_value_from_schema( $input, $input_schema );
201+
$valid_input = rest_validate_value_from_schema( $input, $input_schema, 'input' );
192202
if ( is_wp_error( $valid_input ) ) {
193-
_doing_it_wrong(
194-
__METHOD__,
195-
esc_html(
196-
sprintf(
197-
/* translators: %1$s ability name, %2$s error message. */
198-
__( 'Invalid input provided for ability "%1$s": %2$s.' ),
199-
$this->name,
200-
$valid_input->get_error_message()
201-
)
202-
),
203-
'0.1.0'
203+
return new \WP_Error(
204+
'ability_invalid_input',
205+
sprintf(
206+
/* translators: %1$s ability name, %2$s error message. */
207+
__( 'Ability "%1$s" has invalid input. Reason: %2$s' ),
208+
$this->name,
209+
$valid_input->get_error_message()
210+
)
204211
);
205-
return false;
206212
}
207213

208214
return true;
@@ -216,11 +222,12 @@ protected function validate_input( array $input = array() ): bool {
216222
* @since 0.1.0
217223
*
218224
* @param array<string,mixed> $input Optional. The input data for permission checking.
219-
* @return bool Whether the ability has the necessary permission.
225+
* @return true|\WP_Error Whether the ability has the necessary permission.
220226
*/
221-
public function has_permission( array $input = array() ): bool {
222-
if ( ! $this->validate_input( $input ) ) {
223-
return false;
227+
public function has_permission( array $input = array() ) {
228+
$is_valid = $this->validate_input( $input );
229+
if ( is_wp_error( $is_valid ) ) {
230+
return $is_valid;
224231
}
225232

226233
if ( ! is_callable( $this->permission_callback ) ) {
@@ -240,16 +247,13 @@ public function has_permission( array $input = array() ): bool {
240247
*/
241248
protected function do_execute( array $input ) {
242249
if ( ! is_callable( $this->execute_callback ) ) {
243-
_doing_it_wrong(
244-
__METHOD__,
245-
esc_html(
246-
/* translators: %s ability name. */
247-
sprintf( __( 'Ability "%s" does not have a valid execute callback.' ), $this->name )
248-
),
249-
'0.1.0'
250+
return new \WP_Error(
251+
'ability_invalid_execute_callback',
252+
/* translators: %s ability name. */
253+
sprintf( __( 'Ability "%s" does not have a valid execute callback.' ), $this->name )
250254
);
251-
return null;
252255
}
256+
253257
return call_user_func( $this->execute_callback, $input );
254258
}
255259

@@ -259,29 +263,25 @@ protected function do_execute( array $input ) {
259263
* @since 0.1.0
260264
*
261265
* @param mixed $output The output data to validate.
262-
* @return bool Returns true if valid, false if validation fails.
266+
* @return true|\WP_Error Returns true if valid, or a WP_Error object if validation fails.
263267
*/
264-
protected function validate_output( $output ): bool {
268+
protected function validate_output( $output ) {
265269
$output_schema = $this->get_output_schema();
266270
if ( empty( $output_schema ) ) {
267271
return true;
268272
}
269273

270-
$valid_output = rest_validate_value_from_schema( $output, $output_schema );
274+
$valid_output = rest_validate_value_from_schema( $output, $output_schema, 'output' );
271275
if ( is_wp_error( $valid_output ) ) {
272-
_doing_it_wrong(
273-
__METHOD__,
274-
esc_html(
275-
sprintf(
276-
/* translators: %1$s ability name, %2$s error message. */
277-
__( 'Invalid output provided for ability "%1$s": %2$s.' ),
278-
$this->name,
279-
$valid_output->get_error_message()
280-
)
281-
),
282-
'0.1.0'
276+
return new \WP_Error(
277+
'ability_invalid_output',
278+
sprintf(
279+
/* translators: %1$s ability name, %2$s error message. */
280+
__( 'Ability "%1$s" has invalid output. Reason: %2$s' ),
281+
$this->name,
282+
$valid_output->get_error_message()
283+
)
283284
);
284-
return false;
285285
}
286286

287287
return true;
@@ -297,28 +297,35 @@ protected function validate_output( $output ): bool {
297297
* @return mixed|\WP_Error The result of the ability execution, or WP_Error on failure.
298298
*/
299299
public function execute( array $input = array() ) {
300-
if ( ! $this->has_permission( $input ) ) {
301-
_doing_it_wrong(
302-
__METHOD__,
303-
esc_html(
304-
/* translators: %s ability name. */
305-
sprintf( __( 'Ability "%s" does not have necessary permission.' ), $this->name )
306-
),
307-
'0.1.0'
300+
$has_permissions = $this->has_permission( $input );
301+
if ( true !== $has_permissions ) {
302+
if ( is_wp_error( $has_permissions ) ) {
303+
if ( 'ability_invalid_input' === $has_permissions->get_error_code() ) {
304+
return $has_permissions;
305+
}
306+
// Don't leak the permission check error to someone without the correct perms.
307+
_doing_it_wrong(
308+
__METHOD__,
309+
esc_html( $has_permissions->get_error_message() ),
310+
'0.1.0'
311+
);
312+
}
313+
314+
return new \WP_Error(
315+
'ability_invalid_permissions',
316+
/* translators: %s ability name. */
317+
sprintf( __( 'Ability "%s" does not have necessary permission.' ), $this->name )
308318
);
309-
return null;
310319
}
311320

312321
$result = $this->do_execute( $input );
313322
if ( is_wp_error( $result ) ) {
314323
return $result;
315324
}
316325

317-
if ( ! $this->validate_output( $result ) ) {
318-
return null;
319-
}
326+
$is_valid = $this->validate_output( $result );
320327

321-
return $result;
328+
return is_wp_error( $is_valid ) ? $is_valid : $result;
322329
}
323330

324331
/**

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public function register_routes(): void {
8989
*
9090
* @since 0.1.0
9191
*
92-
* @param \WP_REST_Request $request Full details about the request.
92+
* @param \WP_REST_Request<array<string,mixed>> $request Full details about the request.
9393
* @return \WP_REST_Response Response object on success.
9494
*/
9595
public function get_items( $request ) {
@@ -144,7 +144,7 @@ public function get_items( $request ) {
144144
*
145145
* @since 0.1.0
146146
*
147-
* @param \WP_REST_Request $request Full details about the request.
147+
* @param \WP_REST_Request<array<string,mixed>> $request Full details about the request.
148148
* @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure.
149149
*/
150150
public function get_item( $request ) {
@@ -167,7 +167,7 @@ public function get_item( $request ) {
167167
*
168168
* @since 0.1.0
169169
*
170-
* @param \WP_REST_Request $request Full details about the request.
170+
* @param \WP_REST_Request<array<string,mixed>> $request Full details about the request.
171171
* @return bool True if the request has read access.
172172
*/
173173
public function get_permissions_check( $request ) {
@@ -179,8 +179,8 @@ public function get_permissions_check( $request ) {
179179
*
180180
* @since 0.1.0
181181
*
182-
* @param \WP_Ability $ability The ability object.
183-
* @param \WP_REST_Request $request Request object.
182+
* @param \WP_Ability $ability The ability object.
183+
* @param \WP_REST_Request<array<string,mixed>> $request Request object.
184184
* @return \WP_REST_Response Response object.
185185
*/
186186
public function prepare_item_for_response( $ability, $request ) {

0 commit comments

Comments
 (0)