Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 18 additions & 27 deletions docs/2.getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ wp plugin install https://github.com/WordPress/abilities-api/releases/latest/dow
"$schema": "https://schemas.wp.org/trunk/wp-env.json",
// ... other config ...
"plugins": [
"WordPress/abilities-api",
"WordPress/abilities-api"
// ... other plugins ...
],
]
// ... more config ...
}
```
Expand Down Expand Up @@ -97,13 +97,13 @@ The below example is for a plugin implementation, but it could also be adapted f
```php
<?php

// 1. Define a callback function for your ability
// 1. Define a callback function for your ability.
function my_plugin_get_site_title( array $input = array() ): string {
return get_bloginfo( 'name' );
}

// 2. Register the ability when the Abilities API is initialized
// Using abilities_api_init ensures the API is fully loaded
// 2. Register the ability when the Abilities API is initialized.
// Using `abilities_api_init` ensures the API is fully loaded.
add_action( 'abilities_api_init', 'my_plugin_register_abilities' );

function my_plugin_register_abilities() {
Expand All @@ -127,33 +127,24 @@ function my_plugin_register_abilities() {
) );
}

// 3. Later, you can retrieve and execute the ability
// 3. Later, you can retrieve and execute the ability.
add_action( 'admin_init', 'my_plugin_use_ability' );

function my_plugin_use_ability() {
$ability = wp_get_ability( 'my-plugin/get-site-title' );
if ( ! $ability ) {
// Ability not found.
return;
}

if ( $ability ) {
// Check permissions first - always use is_wp_error() to handle errors properly
$permission = $ability->check_permission();
if ( is_wp_error( $permission ) ) {
// Handle permission error
error_log( 'Permission error: ' . $permission->get_error_message() );
return;
} elseif ( $permission ) {
// Permission granted - safe to execute
$site_title = $ability->execute();
if ( is_wp_error( $site_title ) ) {
// Handle execution error
error_log( 'Execution error: ' . $site_title->get_error_message() );
} else {
// $site_title now holds the result of get_bloginfo('name')
// error_log( 'Site Title: ' . $site_title );
}
} else {
// Permission denied
error_log( 'Permission denied for ability execution' );
}
$site_title = $ability->execute();
if ( is_wp_error( $site_title ) ) {
// Handle execution error
error_log( 'Execution error: ' . $site_title->get_error_message() );
return;
}

// `$site_title` now holds the result of `get_bloginfo( 'name' )`.
echo 'Site Title: ' . esc_html( $site_title );
}
```
38 changes: 12 additions & 26 deletions docs/4.using-abilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,9 @@ if ( $ability ) {
}
```

## Checking Permissions (`$ability->check_permission()`)
## Checking Permissions (`$ability->check_permissions()`)

Before executing an ability, you can check if the current user has permission. The `check_permission()` method returns either `true`, `false`, or a `WP_Error` object, so you must use `is_wp_error()` to handle errors properly:

```php
// Method signature:
// check_permission( $input = null )
```
You can check if the current user has permissions to execute the ability, also without executing it. The `check_permissions()` method returns either `true`, `false`, or a `WP_Error` object. `true` means permission is granted, `false` means the user simply lacks permission, and a `WP_Error` return value typically indicates a failure in the permission check process (such as an internal error or misconfiguration). You must use `is_wp_error()` to handle errors properly and distinguish between permission denial and actual errors:

```php
$ability = wp_get_ability( 'my-plugin/update-option' );
Expand All @@ -142,26 +137,17 @@ if ( $ability ) {
);

// Check permission before execution - always use is_wp_error() first
$permission = $ability->check_permission( $input );
if ( is_wp_error( $permission ) ) {
// Handle permission check error (validation, callback error, etc.)
echo 'Permission check failed: ' . $permission->get_error_message();
} elseif ( $permission ) {
// Permission granted - safe to execute
$result = $ability->execute( $input );
if ( is_wp_error( $result ) ) {
// Handle execution error
echo 'Execution error: ' . $result->get_error_message();
} else {
// Use $result
if ( $result['success'] ) {
echo 'Option updated successfully!';
echo 'Previous value: ' . $result['previous_value'];
}
}
$has_permissions = $ability->check_permissions( $input );
if ( true === $has_permissions ) {
// Permissions granted – safe to execute.
echo 'You have permissions to execute this ability.';
} else {
// Permission denied
echo 'You do not have permission to execute this ability.';
// Don't leak permission errors to unauthenticated users.
if ( is_wp_error( $has_permissions ) ) {
error_log( 'Permissions check failed: ' . $has_permissions->get_error_message() );
}

echo 'You do not have permissions to execute this ability.';
}
}
```
Expand Down
12 changes: 6 additions & 6 deletions includes/abilities-api/class-wp-ability.php
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ protected function validate_input( $input = null ) {
* @param mixed $input Optional. The input data for permission checking. Default `null`.
* @return bool|\WP_Error Whether the ability has the necessary permission.
*/
public function check_permission( $input = null ) {
public function check_permissions( $input = null ) {
$is_valid = $this->validate_input( $input );
if ( is_wp_error( $is_valid ) ) {
return $is_valid;
Expand All @@ -335,17 +335,17 @@ public function check_permission( $input = null ) {
*
* The input is validated against the input schema before it is passed to to permission callback.
*
* @deprecated N.E.X.T Use check_permission() instead.
* @see WP_Ability::check_permission()
* @deprecated N.E.X.T Use check_permissions() instead.
* @see WP_Ability::check_permissions()
*
* @since 0.1.0
*
* @param mixed $input Optional. The input data for permission checking. Default `null`.
* @return bool|\WP_Error Whether the ability has the necessary permission.
*/
public function has_permission( $input = null ) {
_deprecated_function( __METHOD__, 'N.E.X.T', 'WP_Ability::check_permission()' );
return $this->check_permission( $input );
_deprecated_function( __METHOD__, 'N.E.X.T', 'WP_Ability::check_permissions()' );
return $this->check_permissions( $input );
}

/**
Expand Down Expand Up @@ -412,7 +412,7 @@ protected function validate_output( $output ) {
* @return mixed|\WP_Error The result of the ability execution, or WP_Error on failure.
*/
public function execute( $input = null ) {
$has_permissions = $this->check_permission( $input );
$has_permissions = $this->check_permissions( $input );
if ( true !== $has_permissions ) {
if ( is_wp_error( $has_permissions ) ) {
if ( 'ability_invalid_input' === $has_permissions->get_error_code() ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public function run_ability_permissions_check( $request ) {
}

$input = $this->get_input_from_request( $request );
if ( ! $ability->check_permission( $input ) ) {
if ( ! $ability->check_permissions( $input ) ) {
return new \WP_Error(
'rest_ability_cannot_execute',
__( 'Sorry, you are not allowed to execute this ability.' ),
Expand Down
10 changes: 5 additions & 5 deletions tests/unit/abilities-api/wpRegisterAbility.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public function test_register_valid_ability(): void {
$this->assertSame( self::$test_ability_args['output_schema'], $result->get_output_schema() );
$this->assertSame( self::$test_ability_args['meta'], $result->get_meta() );
$this->assertTrue(
$result->check_permission(
$result->check_permissions(
array(
'a' => 2,
'b' => 3,
Expand Down Expand Up @@ -164,7 +164,7 @@ public function test_register_ability_no_permissions(): void {
$result = wp_register_ability( self::$test_ability_name, self::$test_ability_args );

$this->assertFalse(
$result->check_permission(
$result->check_permissions(
array(
'a' => 2,
'b' => 3,
Expand Down Expand Up @@ -289,7 +289,7 @@ public function test_permission_callback_no_input_schema_match(): void {

$result = wp_register_ability( self::$test_ability_name, self::$test_ability_args );

$actual = $result->check_permission(
$actual = $result->check_permissions(
array(
'a' => 2,
'b' => 3,
Expand Down Expand Up @@ -346,7 +346,7 @@ public function test_permission_callback_receives_input(): void {

// Test with a > b (should be allowed)
$this->assertTrue(
$result->check_permission(
$result->check_permissions(
array(
'a' => 5,
'b' => 3,
Expand All @@ -363,7 +363,7 @@ public function test_permission_callback_receives_input(): void {

// Test with a < b (should be denied)
$this->assertFalse(
$result->check_permission(
$result->check_permissions(
array(
'a' => 2,
'b' => 8,
Expand Down