wp_get_abilities( array $args = array() ): WP_Ability[]
- Since
- 6.9.0, 7.1.0
- Source
wp-includes/abilities-api.php:498
Description
When called without arguments, returns all registered abilities. When called with an $args array, returns only abilities that match every specified condition.
Filtering pipeline (executed in order):
- Declarative filters (
category,namespace,meta) — per-item, AND logic between arg types. item_include_callback— per-item, caller-scoped. Return true to include, false to exclude.wp_get_abilities_item_includefilter — per-item, ecosystem-scoped. Plugins can enforce universal inclusion rules regardless of what the caller passed.result_callback— on the full matched array, caller-scoped. Sort, slice, or reshape.wp_get_abilities_resultfilter — on the full array, ecosystem-scoped.
Steps 1–3 run inside a single loop over the registry — no extra iteration.
Examples:
// All abilities (unchanged behaviour).
$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 ) ) );
// 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 ) {
usort( $abilities, fn( $a, $b ) => strcasecmp( $a->get_label(), $b->get_label() ) );
return array_slice( $abilities, 0, 10 );
},
) ); The pipeline always runs, even when called with no arguments. This ensures that the wp_get_abilities_item_include and wp_get_abilities_result filters always fire, giving plugins a reliable place to enforce universal inclusion or shaping rules.
For raw, unfiltered registry data that bypasses the filter pipeline entirely, use WP_Abilities_Registry::get_all_registered() directly.
Compatibility
- WordPress
- since 7.1.0
- PHP
- 7.4–8.6-dev
- 6.7.7
- 6.8.8
- 6.9.7
- 7.0.4
- 7.1.0
Present in 3 of the 5 tracked releases, added in 7.1.0, and compiles on PHP 7.4 through 8.6-dev.
Parameters
$argsarrayoptional- Arguments to filter the returned abilities. Default empty array (returns all).Default:
array()$categorystringFilter by category slug. Only abilities whose category exactly matches the given slug are included.$namespacestringFilter by ability namespace prefix. Pass the namespace without a trailing slash, e.g.'woocommerce'matches'woocommerce/create-order'.$metaarrayFilter by meta key/value pairs. All conditions must match (AND logic). Supports nested arrays for structured meta, e.g.array( 'mcp' => array( 'public' => true ) ).$item_include_callbackcallableOptional. A callback invoked per ability after declarative filters. Receives a WP_Ability instance, returns bool. Return true to include, false to exclude.$result_callbackcallableOptional. A callback invoked once on the full matched array. Receives WP_Ability[], must return WP_Ability[]. Use for sorting, slicing, or reshaping the result.
Return value
WP_Ability[]- An array of registered WP_Ability instances matching the given args, keyed by ability name. Returns an empty array if no abilities are registered, the registry is unavailable, or no abilities match the given args.
Performance profile
How much work a call to wp_get_abilities() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.
- Cost class
- Light
- Scaling
- Scales with input
- Instructions
- 7–76
- Plugin surface
- 2 hooks
- Called by
- 1
Touches nothing outside its own arguments.
The body loops, so the work grows with what you pass in.
Executed per call on PHP 8.5, depending on the branch taken. The body compiles to 124.
Third-party callbacks on 'wp_get_abilities_item_include', 'wp_get_abilities_result' run inside this call, and their cost is not bounded by anything here.
1 place in core call this, so the cost is paid more often than your own code shows.
What it touches
- hookthird-party callbacks
apply_filters()called directly
What one call costs · 13 distinct outcomes
One number would be a lie: the work depends on which branch runs. These are every distinct cost wp_get_abilities() can have, taken from its control-flow graph on PHP 8.5.
| When | Instructions | Calls it makes |
|---|---|---|
$registry === null | 7 | ::WP_Abilities_Registry() |
$registry !== null && !isset($args) && $result_callback === null | 41–53 | ::WP_Abilities_Registry(), ->get_all_registered(), apply_filters() |
$registry !== null && !isset($args) && $result_callback !== null | 46–58 | ::WP_Abilities_Registry(), ->get_all_registered(), call_user_func(), apply_filters() |
$registry !== null && $result_callback === null | 46–59 | ::WP_Abilities_Registry(), ->get_all_registered(), is_callable(), apply_filters() |
$registry !== null && $result_callback === null | 50–59 | ::WP_Abilities_Registry(), ->get_all_registered(), rtrim(), apply_filters() |
$registry !== null && $result_callback !== null | 51–64 | ::WP_Abilities_Registry(), ->get_all_registered(), is_callable(), call_user_func(), apply_filters() |
$registry !== null && isset($args) && $result_callback === null | 51–65 | ::WP_Abilities_Registry(), ->get_all_registered(), is_callable(), is_callable(), apply_filters() |
$registry !== null && $result_callback !== null | 55–64 | ::WP_Abilities_Registry(), ->get_all_registered(), rtrim(), call_user_func(), apply_filters() |
$registry !== null && $result_callback === null | 55–65 | ::WP_Abilities_Registry(), ->get_all_registered(), rtrim(), is_callable(), apply_filters() |
$registry !== null && isset($args) && $result_callback !== null | 56–70 | ::WP_Abilities_Registry(), ->get_all_registered(), is_callable(), is_callable(), call_user_func(), apply_filters() |
$registry !== null && $result_callback !== null | 60–70 | ::WP_Abilities_Registry(), ->get_all_registered(), rtrim(), is_callable(), call_user_func(), apply_filters() |
$registry !== null && isset($args) && $result_callback === null | 60–71 | ::WP_Abilities_Registry(), ->get_all_registered(), rtrim(), is_callable(), is_callable(), apply_filters() |
1 further outcome, up to 76 instructions
$registry !== null && isset($args) && $result_callback !== null | 65–76 | ::WP_Abilities_Registry(), ->get_all_registered(), rtrim(), is_callable(), is_callable(), call_user_func(), apply_filters() |
Across PHP versions
| PHP | Compiled | Executed | Branches | Notes |
|---|---|---|---|---|
| 8.6-dev | 124 | 7–76 | 22 | |
| 8.5 | 124 | 7–76 | 22 | |
| 8.4 | 124 | 7–76 | 22 | 3 fewer instructions than PHP 8.3 |
| 8.3 | 127 | 7–76 | 22 | |
| 8.2 | 127 | 7–76 | 22 | |
| 8.1 | 127 | 7–76 | 22 | 5 fewer instructions than PHP 7.4 |
| 7.4 | 132 | 7–81 | 22 |
An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.
Hooks and filters fired · 2
2 hooks fire while wp_get_abilities() runs, in this order:
- apply_filters( wp_get_abilities_item_include )filterline 549 (+51 into the body)
Filters whether an individual ability should be included in the result set.
- apply_filters( wp_get_abilities_result )filterline 572 (+74 into the body)
Filters the full list of matched abilities after all per-item filtering is complete.
Uses · 4
- str_starts_with()Polyfill for `str_starts_with()` function added in PHP 8.0.
- _wp_get_abilities_match_meta()Checks whether an ability's meta array matches a set of required key/value conditions.
- apply_filters()Calls the callback functions that have been added to a filter hook.
- WP_Abilities_Registry::get_instance()Utility method to retrieve the main instance of the registry class.
Used by · 1
- WP_REST_Abilities_V1_List_Controller::get_items()Retrieves all abilities.
Source code
function wp_get_abilities( array $args = array() ): array { $registry = WP_Abilities_Registry::get_instance(); if ( null === $registry ) { return array(); } $abilities = $registry->get_all_registered(); $category = isset( $args['category'] ) && is_string( $args['category'] ) ? $args['category'] : ''; $namespace = isset( $args['namespace'] ) && is_string( $args['namespace'] ) ? rtrim( $args['namespace'], '/' ) . '/' : ''; $meta = isset( $args['meta'] ) && is_array( $args['meta'] ) ? $args['meta'] : array(); $item_include_callback = isset( $args['item_include_callback'] ) && is_callable( $args['item_include_callback'] ) ? $args['item_include_callback'] : null; $result_callback = isset( $args['result_callback'] ) && is_callable( $args['result_callback'] ) ? $args['result_callback'] : null; $matched = array(); foreach ( $abilities as $name => $ability ) { // Step 1a: Filter by category. if ( '' !== $category && $ability->get_category() !== $category ) { continue; } // Step 1b: Filter by namespace prefix. if ( '' !== $namespace && ! str_starts_with( $ability->get_name(), $namespace ) ) { continue; } // Step 1c: Filter by meta key/value pairs (AND logic, supports nested arrays). if ( ! empty( $meta ) && ! _wp_get_abilities_match_meta( $ability->get_meta(), $meta ) ) { continue; } // Step 2: Caller-scoped per-item callback. $include = true; if ( null !== $item_include_callback ) { $include = (bool) call_user_func( $item_include_callback, $ability ); } /** * Filters whether an individual ability should be included in the result set. * * Fires after the declarative filters and the caller-scoped item_include_callback. * Plugins can use this to enforce universal inclusion rules regardless of * what the caller passed in $args. * * @since 7.1.0 * * @param bool $include Whether to include the ability. Default true (after declarative filters pass). * @param WP_Ability $ability The ability instance being evaluated. * @param array $args The full $args array passed to wp_get_abilities(). */ $include = (bool) apply_filters( 'wp_get_abilities_item_include', $include, $ability, $args ); if ( $include ) { $matched[ $name ] = $ability; } } // Step 4: Caller-scoped result callback. if ( null !== $result_callback ) { $matched = (array) call_user_func( $result_callback, $matched ); } /** * Filters the full list of matched abilities after all per-item filtering is complete. * * Fires after the caller-scoped result_callback. Plugins can use this to sort, * paginate, or reshape the final result set universally. * * @since 7.1.0 * * @param WP_Ability[] $matched The matched abilities after all filtering. * @param array $args The full $args array passed to wp_get_abilities(). */ return (array) apply_filters( 'wp_get_abilities_result', $matched, $args );}Changelog
Introduced in 6.9.0. One change between 6.9.7 and 7.1.0.
Signature, return type and hooks compared across 3 parsed releases.
$args added.verified against source$args parameter for filtering support.from the docblockAbout this page
- Parsed data
- Generated from the wordpress-develop 7.1.0 tag, from
src/wp-includes/abilities-api.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it. - Corrections
- Something wrong on this page? Report it and it gets fixed in the next regeneration.