-
Notifications
You must be signed in to change notification settings - Fork 16
dev: add wp_ability_args
filter [Proposal]
#74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# Using Action and Filter Hooks | ||
|
||
The Abilities API provides action and filter hooks that allow developers to customize and extend its functionality. Below are the available hooks: | ||
|
||
## Quick Links | ||
|
||
- [Actions](#actions) | ||
- [Filters](#filters) | ||
- [`wp_ability_args`](#wp_ability_args) | ||
|
||
## Actions | ||
|
||
There are currently **no Action hooks** provided by this version of the Abilities API. | ||
|
||
## Filters | ||
|
||
### `wp_ability_args` | ||
|
||
> [!IMPORTANT] | ||
> This filter is prefixed with `wp_` to avoid potential naming collisions. | ||
> Once merged into WordPress core, the prefix will likely be removed to preserve backward-compatibility. | ||
Allows modification of an Ability's args before they are validated and used to instantiate the Ability. | ||
|
||
```php | ||
apply_filters( 'wp_ability_args', array $args, string $ability_name ); | ||
``` | ||
|
||
#### Parameters | ||
|
||
- `$args` (`array<string,mixed>`): The arguments used to instantiate the ability. See [wp_register_ability()](./3.registering-abilities.md#wp_register_ability) for the full list of args. | ||
- `$ability_name` (`string`): The name of the ability, with its namespace. | ||
|
||
#### Example | ||
|
||
```php | ||
/** | ||
* Modify ability args before validation. | ||
* @param array<string,mixed> $args The arguments used to instantiate the ability. | ||
* @param string $ability_name The name of the ability, with its namespace. | ||
* @return array<string,mixed> The modified ability arguments. | ||
*/ | ||
function my_modify_ability_args( array $args, string $ability_name ): array { | ||
// Check if the ability name matches what you're looking for. | ||
if ( 'my-namespace/my-ability' !== $ability_name ) { | ||
return $args; | ||
} | ||
|
||
// Modify the args as needed. | ||
$args['label'] = __('My Custom Ability Label'); | ||
|
||
// You can use the old args to build new ones. | ||
$args['description'] = sprintf( | ||
/* translators: 1: Ability name 2: Previous description */ | ||
__('This is a custom description for the ability %s. Previously the description was %s', 'text-domain'), | ||
$ability_name, | ||
$args['description'] ?? 'N/A' | ||
); | ||
|
||
// Even if they're callbacks. | ||
$args['has_permissions' ] = static function ( $input = null ) use ( $args, $ability_name ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be |
||
$previous_check = is_callable( $args['has_permissions'] ) ? $args['has_permissions']( $input ) : true; | ||
|
||
// If we already failed, no need for stricter checks. | ||
if ( ! $previous_check || is_wp_error( $previous_check ) ) { | ||
return $previous_check; | ||
} | ||
|
||
return current_user_can( 'my_custom_ability_cap', $ability_name ); | ||
} | ||
|
||
return $args; | ||
} | ||
add_filter( 'wp_ability_args', 'my_modify_ability_args', 10, 2 ); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,6 +64,16 @@ final class WP_Abilities_Registry { | |
* } $args | ||
*/ | ||
public function register( string $name, array $args ): ?WP_Ability { | ||
/** | ||
* Filters the ability arguments before they are validated. | ||
* | ||
* @since n.e.x.t | ||
* | ||
* @param array<string,mixed> $args The arguments used to instantiate the ability. | ||
* @param string $name The name of the ability, with its namespace. | ||
*/ | ||
$args = apply_filters( 'wp_ability_args', $args, $name ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor note, this could get moved after all checks against There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My intent here is intentionally the opposite, since it allows changes/recoverability of the IMO (pseudocode): add_filter( 'register_ability_args',
// Or whatever prefixes/missing-namespaces are enforced by validation.
static fn ( &$args, $original_name ) => $args['name'] = sprintf( '!$#@#_%s', str_replace( '/', '_', $original_name ),
10, 2 ); should not be allowed since it means adapters/downstream cant reliably depend on the namespace/shape for their needs. Meanwhile, I'm believe that e.g.
should still be flexible enough for any downstream/back-compat considerations without making the expected shape of the Ability API unreliable, but I'm happy to evaluate other use cases (the only one I can think of is if a user intentionally registers a namespace wrong initially, but the immediate error they face should prevent that from ever shipping and thus preempting the need for a downstream filter) (PS: moving this to after the checks after a 6.9 merge is a nonbreaking change. moving it up to enforce name validation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed 🤦 too much task switching that even with the function in front of me I got our I'll move it down to after the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No worries, it's why additional eyes are helpful to the implementation from a different perspective 👍🏻 |
||
|
||
if ( ! preg_match( '/^[a-z0-9-]+\/[a-z0-9-]+$/', $name ) ) { | ||
_doing_it_wrong( | ||
__METHOD__, | ||
|
@@ -94,6 +104,8 @@ public function register( string $name, array $args ): ?WP_Ability { | |
); | ||
return null; | ||
} | ||
|
||
/** @var class-string<\WP_Ability> */ | ||
$ability_class = $args['ability_class'] ?? WP_Ability::class; | ||
unset( $args['ability_class'] ); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would go with the final name from the start to avoid the hassle.
register_ability_args
should be distinct enough.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
register_ability_args
is better thanability_args
I had in mind too as it aligns withregister_{post_type|taxonomy}
args.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm closely familiar with
register_block_type_args
, which was likely inspired by these you listed.