[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> abilities-api.php (summary)

Abilities API: core functions for registering and managing abilities. The Abilities API provides a unified, extensible framework for registering and executing discrete capabilities within WordPress. An "ability" is a self-contained unit of functionality with defined inputs, outputs, permissions, and execution logic.

File Size: 894 lines (40 kb)
Included or required:0 times
Referenced: 0 times
Includes or requires: 0 files

Defines 11 functions

  wp_register_ability()
  wp_unregister_ability()
  wp_has_ability()
  wp_get_ability()
  wp_get_abilities()
  _wp_get_abilities_match_meta()
  wp_register_ability_category()
  wp_unregister_ability_category()
  wp_has_ability_category()
  wp_get_ability_category()
  wp_get_ability_categories()

Functions
Functions that are not part of a class:

wp_register_ability( string $name, array $args )   X-Ref
Registers a new ability using the Abilities API. It requires three steps:

1. Hook into the `wp_abilities_api_init` action.
2. Call `wp_register_ability()` with a namespaced name and configuration.
3. Provide an `execute_callback`. For permission checks, set `required_capabilities`,
`permission_callback`, or both.

Example:

function my_plugin_register_abilities(): void {
wp_register_ability(
'my-plugin/analyze-text',
array(
'label'                 => __( 'Analyze Text', 'my-plugin' ),
'description'           => __( 'Performs sentiment analysis on provided text.', 'my-plugin' ),
'category'              => 'text-processing',
'input_schema'          => array(
'type'        => 'string',
'description' => __( 'The text to be analyzed.', 'my-plugin' ),
'minLength'   => 10,
),
'output_schema'         => array(
'type'        => 'string',
'enum'        => array( 'positive', 'negative', 'neutral' ),
'description' => __( 'The sentiment result: positive, negative, or neutral.', 'my-plugin' ),
),
'execute_callback'      => 'my_plugin_analyze_text',
'required_capabilities' => array( 'edit_posts' ),
'permission_callback'   => 'my_plugin_can_analyze_text',
'meta'                  => array(
'annotations' => array(
'readonly' => true,
),
'public'      => true,
),
)
);
}
add_action( 'wp_abilities_api_init', 'my_plugin_register_abilities' );

The `text-processing` category must be registered first with
`wp_register_ability_category()`, or the registration fails.

On failure, this function returns `null` and calls `_doing_it_wrong()` with the reason.
By default, the resulting notice is displayed when `WP_DEBUG` is enabled.

### Naming Conventions

Ability names must follow these rules:

- Include exactly one namespace and one ability name, separated by a single slash
(e.g., `my-plugin/my-ability`). Nested namespaces are not supported.
- Use only lowercase alphanumeric characters, dashes, and forward slashes.
- Use descriptive, action-oriented names (e.g., `process-payment`, `generate-report`).

### Categories

Abilities can be organized into categories. If no category is provided, the ability is
assigned to the built-in `uncategorized` category. Custom categories must be registered
before the abilities that reference them:

function my_plugin_register_categories(): void {
wp_register_ability_category(
'text-processing',
array(
'label'       => __( 'Text Processing', 'my-plugin' ),
'description' => __( 'Abilities for analyzing and transforming text.', 'my-plugin' ),
)
);
}
add_action( 'wp_abilities_api_categories_init', 'my_plugin_register_categories' );

### Input and Output Schemas

Schemas define the expected structure, type, and constraints for ability inputs
and outputs using JSON Schema syntax. They serve two critical purposes: automatic
validation of data passed to and returned from abilities, and self-documenting
API contracts for developers.

WordPress implements a validator based on a subset of the JSON Schema Version 4
specification (https://json-schema.org/specification-links.html#draft-4).
For details on supported JSON Schema properties and syntax, see the
related WordPress REST API Schema documentation:
https://developer.wordpress.org/rest-api/extending-the-rest-api/schema/#json-schema-basics

An input schema is required when passing non-null input. Without one, only `null`
input is accepted and callbacks receive no arguments. When input is `null`, a
top-level `default` in the input schema is applied before validation.

An output schema is optional. When omitted, output schema validation is skipped.
Define one to document and validate the result returned by the ability:

'input_schema'  => array(
'type'        => 'string',
'description' => __( 'The text to be analyzed.', 'my-plugin' ),
'minLength'   => 10,
),
'output_schema' => array(
'type'        => 'string',
'enum'        => array( 'positive', 'negative', 'neutral' ),
'description' => __( 'The sentiment result: positive, negative, or neutral.', 'my-plugin' ),
),

### Callbacks

#### Execute Callback

The execute callback performs the ability's core functionality. It receives
the normalized, validated input when an input schema is defined, and no arguments
otherwise. It returns either a result or `WP_Error` on failure. Exceptions thrown
by execute or permission callbacks are caught and converted to a `WP_Error`.

function my_plugin_analyze_text( string $input ): string|WP_Error {
$score = My_Plugin::perform_sentiment_analysis( $input );
if ( is_wp_error( $score ) ) {
return $score;
}
return My_Plugin::interpret_sentiment_score( $score );
}

#### Required Capabilities and Permission Callback

Declare only the minimum capabilities required for every execution in
`required_capabilities`. Check additional capabilities that depend on the input
in `permission_callback`. Declaring capabilities needed only for particular inputs
can cause discovery to hide an ability the current user is allowed to execute
with other inputs.

Each required capability is checked with `current_user_can()` before the
permission callback runs. The callback is optional when the list is non-empty.
For an ability that everyone may execute, use `__return_true` as the callback
with no required capabilities.

The permission callback determines whether the ability can be executed.
It receives the same input as the execute callback and must return a
boolean or `WP_Error`. Common use cases include checking user capabilities,
validating API keys, or verifying system state. In the example above, every
execution requires `edit_posts`, and the callback only adds the check that
depends on the input:

function my_plugin_can_analyze_text( string $input ): bool|WP_Error {
// Only administrators can analyze long texts.
if ( mb_strlen( $input ) > 5000 ) {
return current_user_can( 'manage_options' );
}
return true;
}

### Execution Lifecycle

Call `WP_Ability::execute()` to normalize and validate input, check permissions,
invoke the execute callback, and validate output. It returns the result or a
`WP_Error` on failure. Custom ability classes can override this behavior.

Hooks run in this order, and processing stops at the first failure:

1. `wp_ability_invoked` action, with the raw input.
2. `wp_pre_execute_ability` filter, which can short-circuit the rest of execution.
3. `wp_ability_normalize_input`, `wp_ability_validate_input`, and
`wp_ability_permission_result` filters. The input validation filter runs only
when a non-empty input schema is defined.
4. `wp_before_execute_ability` action.
5. `wp_ability_execute_result` and `wp_ability_validate_output` filters.
6. `wp_after_execute_ability` action.

### Client Exposure

Exposure flags do not grant execution permission.

Set the high-level `public` flag to make an ability available to clients
such as the REST API, MCP, or AI agents:

'meta' => array(
'public' => true,
),

The `public` flag seeds the default for each per-channel flag. For the REST
API it seeds `show_in_rest`, which lets the ability be invoked via HTTP
requests. Set a per-channel flag directly to override that default. For
example, keep a public ability out of the REST API:

'meta' => array(
'public'       => true,
'show_in_rest' => false,
),

return: WP_Ability|null The registered ability instance on success, `null` on failure.
param: string               $name The name of the ability. Must be a namespaced string containing
param: array<string, mixed> $args {

wp_unregister_ability( string $name )   X-Ref
Unregisters an ability from the Abilities API.

Removes a previously registered ability from the global registry. Use this to
disable abilities provided by other plugins or when an ability is no longer needed.

Can be called at any time after the ability has been registered.

Example:

if ( wp_has_ability( 'other-plugin/some-ability' ) ) {
wp_unregister_ability( 'other-plugin/some-ability' );
}

return: WP_Ability|null The unregistered ability instance on success, `null` on failure.
param: string $name The name of the ability to unregister, including namespace prefix

wp_has_ability( string $name )   X-Ref
Checks if an ability is registered.

Use this for conditional logic and feature detection before attempting to
retrieve or use an ability.

Example:

// Displays different UI based on available abilities.
if ( wp_has_ability( 'premium-plugin/advanced-export' ) ) {
echo 'Export with Premium Features';
} else {
echo 'Basic Export';
}

return: bool `true` if the ability is registered, `false` otherwise.
param: string $name The name of the ability to check, including namespace prefix

wp_get_ability( string $name )   X-Ref
Retrieves a registered ability.

Returns the ability instance for inspection or use. The instance provides access
to the ability's configuration, metadata, and execution methods.

Example:

// Prints information about a registered ability.
$ability = wp_get_ability( 'my-plugin/export-data' );
if ( $ability ) {
echo $ability->get_label() . ': ' . $ability->get_description();
}

return: WP_Ability|null The registered ability instance, or `null` if not registered.
param: string $name The name of the ability, including namespace prefix

wp_get_abilities( array $args = array()   X-Ref
Retrieves registered abilities, optionally filtered by the given arguments.

When called without arguments, returns all registered abilities. When called
with an $args array, returns only abilities that match every specified condition.
In both cases, the callbacks and filters below can change the result.

Filtering pipeline (executed in order):

1. Declarative filters (`category`, `namespace`, `meta`, `has_required_capabilities`) —
per-item, AND logic between arg types.
2. `item_include_callback` — per-item, caller-scoped. Return true to include, false to exclude.
3. `wp_get_abilities_item_include` filter — per-item, ecosystem-scoped. Plugins can enforce
inclusion rules for abilities that passed the declarative filters.
4. `result_callback` — on the full matched array, caller-scoped. Sort, slice, or reshape.
5. `wp_get_abilities_result` filter — on the full array, ecosystem-scoped.

Steps 1–3 run inside a single loop over the registry — no extra iteration.

Examples:

// All abilities.
$abilities = wp_get_abilities();

// Filter by category.
$abilities = wp_get_abilities( array( 'category' => 'content' ) );

// Filter by namespace.
$abilities = wp_get_abilities( array( 'namespace' => 'woocommerce' ) );

// Filter by meta.
$abilities = wp_get_abilities( array( 'meta' => array( 'show_in_rest' => true ) ) );

// Abilities whose declared minimum capabilities the current user has.
// Input-dependent permission checks still run when executing an ability.
$abilities = wp_get_abilities( array( 'has_required_capabilities' => true ) );

// Combine filters (AND logic between arg types).
$abilities = wp_get_abilities( array(
'category'  => 'content',
'namespace' => 'core',
'meta'      => array( 'show_in_rest' => true ),
) );

// Caller-scoped per-item callback.
$abilities = wp_get_abilities( array(
'item_include_callback' => function ( WP_Ability $ability ) {
return current_user_can( 'manage_options' );
},
) );

// Caller-scoped result callback (sort + paginate).
$abilities = wp_get_abilities( array(
'result_callback' => function ( array $abilities ) {
uasort( $abilities, fn( $a, $b ) => strcasecmp( $a->get_label(), $b->get_label() ) );
return array_slice( $abilities, 0, 10, true );
},
) );

The pipeline always runs, even when called with no arguments. This ensures that the
`wp_get_abilities_result` filter always fires, giving plugins a reliable place to
enforce universal shaping rules.
For raw, unfiltered registry data that bypasses the filter pipeline entirely, use
{@see WP_Abilities_Registry::get_all_registered()} directly.

return: WP_Ability[] An array of registered WP_Ability instances, keyed by ability name
param: array $args {

_wp_get_abilities_match_meta( array $meta, array $conditions )   X-Ref
Checks whether an ability's meta array matches a set of required key/value conditions.

All conditions must match (AND logic). Supports nested arrays for structured meta,
e.g. `array( 'mcp' => array( 'public' => true ) )`. Every condition key must exist,
and non-array values are compared strictly, including their types. Extra meta keys
are allowed at any level.

return: bool True if all conditions match, false otherwise.
param: array $meta       The ability's meta array.
param: array $conditions The required key/value conditions to match against.

wp_register_ability_category( string $slug, array $args )   X-Ref
Registers a new ability category.

Ability categories provide a way to organize and group related abilities for better
discoverability and management. Custom categories must be registered before abilities
that reference them. Abilities that omit a category are assigned to the built-in
`uncategorized` category, which is intended as an escape hatch for simple or transitional
registrations.

Ability categories must be registered on the `wp_abilities_api_categories_init` action hook.

Example:

function my_plugin_register_categories() {
wp_register_ability_category(
'content-management',
array(
'label'       => __( 'Content Management', 'my-plugin' ),
'description' => __( 'Abilities for managing and organizing content.', 'my-plugin' ),
)
);
}
add_action( 'wp_abilities_api_categories_init', 'my_plugin_register_categories' );

On failure, this function returns `null` and calls `_doing_it_wrong()` with the reason.
By default, the resulting notice is displayed when `WP_DEBUG` is enabled.

return: WP_Ability_Category|null The registered ability category instance on success, `null` on failure.
param: string               $slug The unique slug for the ability category. Must contain lowercase
param: array<string, mixed> $args {

wp_unregister_ability_category( string $slug )   X-Ref
Unregisters an ability category.

Removes a previously registered ability category from the global registry. Use this to
disable ability categories that are no longer needed.

Can be called at any time after the ability category has been registered.

Example:

if ( wp_has_ability_category( 'deprecated-category' ) ) {
wp_unregister_ability_category( 'deprecated-category' );
}

return: WP_Ability_Category|null The unregistered ability category instance on success, `null` on failure.
param: string $slug The slug of the ability category to unregister.

wp_has_ability_category( string $slug )   X-Ref
Checks if an ability category is registered.

Use this for conditional logic and feature detection before attempting to
retrieve or use an ability category.

Example:

// Displays different UI based on available ability categories.
if ( wp_has_ability_category( 'premium-features' ) ) {
echo 'Premium Features Available';
} else {
echo 'Standard Features';
}

return: bool `true` if the ability category is registered, `false` otherwise.
param: string $slug The slug of the ability category to check.

wp_get_ability_category( string $slug )   X-Ref
Retrieves a registered ability category.

Returns the ability category instance for inspection or use. The instance provides access
to the ability category's configuration and metadata.

Example:

// Prints information about a registered ability category.
$ability_category = wp_get_ability_category( 'content-management' );
if ( $ability_category ) {
echo $ability_category->get_label() . ': ' . $ability_category->get_description();
}

return: WP_Ability_Category|null The ability category instance, or `null` if not registered.
param: string $slug The slug of the ability category.

wp_get_ability_categories()   X-Ref
Retrieves all registered ability categories.

Returns an array of all ability category instances currently registered in the system.
Use this for discovery, debugging, or building administrative interfaces.

Example:

// Prints information about all available ability categories.
$ability_categories = wp_get_ability_categories();
foreach ( $ability_categories as $ability_category ) {
echo $ability_category->get_label() . ': ' . $ability_category->get_description() . "\n";
}

return: WP_Ability_Category[] An array of registered ability category instances,



Generated : Tue Nov 3 08:20:36 2026 Cross-referenced by PHPXref