-
Notifications
You must be signed in to change notification settings - Fork 34
feat!: make permission_callback arg required
#73
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
Changes from 4 commits
b99744c
4d7ba35
b08da61
c99eaae
00d5099
a1b27ab
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 |
|---|---|---|
|
|
@@ -73,9 +73,9 @@ class WP_Ability { | |
| * The optional ability permission callback. | ||
| * | ||
| * @since 0.1.0 | ||
| * @var ?callable( mixed $input= ): (bool|\WP_Error) | ||
| * @var callable( mixed $input= ): (bool|\WP_Error) | ||
| */ | ||
| protected $permission_callback = null; | ||
| protected $permission_callback; | ||
|
|
||
| /** | ||
| * The optional ability metadata. | ||
|
|
@@ -143,15 +143,16 @@ public function __construct( string $name, array $args ) { | |
| * @phpstan-return array{ | ||
| * label: string, | ||
| * description: string, | ||
| * execute_callback: callable( mixed $input= ): (mixed|\WP_Error), | ||
| * permission_callback: callable( mixed $input= ): (bool|\WP_Error), | ||
| * input_schema?: array<string,mixed>, | ||
| * output_schema?: array<string,mixed>, | ||
| * execute_callback: callable( mixed $input= ): (mixed|\WP_Error), | ||
| * permission_callback?: ?callable( mixed $input= ): (bool|\WP_Error), | ||
| * meta?: array<string,mixed>, | ||
| * ...<string, mixed>, | ||
| * } $args | ||
| */ | ||
| protected function prepare_properties( array $args ): array { | ||
| // Required args must be present and of the correct type. | ||
| if ( empty( $args['label'] ) || ! is_string( $args['label'] ) ) { | ||
| throw new \InvalidArgumentException( | ||
| esc_html__( 'The ability properties must contain a `label` string.' ) | ||
|
|
@@ -164,27 +165,28 @@ protected function prepare_properties( array $args ): array { | |
| ); | ||
| } | ||
|
|
||
| if ( isset( $args['input_schema'] ) && ! is_array( $args['input_schema'] ) ) { | ||
| if ( empty( $args['execute_callback'] ) || ! is_callable( $args['execute_callback'] ) ) { | ||
| throw new \InvalidArgumentException( | ||
| esc_html__( 'The ability properties should provide a valid `input_schema` definition.' ) | ||
| esc_html__( 'The ability properties must contain a valid `execute_callback` function.' ) | ||
| ); | ||
| } | ||
|
|
||
| if ( isset( $args['output_schema'] ) && ! is_array( $args['output_schema'] ) ) { | ||
| if ( empty( $args['permission_callback'] ) || ! is_callable( $args['permission_callback'] ) ) { | ||
| throw new \InvalidArgumentException( | ||
| esc_html__( 'The ability properties should provide a valid `output_schema` definition.' ) | ||
| esc_html__( 'The ability properties must provide a valid `permission_callback` function.' ) | ||
| ); | ||
| } | ||
|
|
||
| if ( empty( $args['execute_callback'] ) || ! is_callable( $args['execute_callback'] ) ) { | ||
| // Optional args only need to be of the correct type if they are present. | ||
| if ( isset( $args['input_schema'] ) && ! is_array( $args['input_schema'] ) ) { | ||
| throw new \InvalidArgumentException( | ||
| esc_html__( 'The ability properties must contain a valid `execute_callback` function.' ) | ||
| esc_html__( 'The ability properties should provide a valid `input_schema` definition.' ) | ||
| ); | ||
| } | ||
|
|
||
| if ( isset( $args['permission_callback'] ) && ! is_callable( $args['permission_callback'] ) ) { | ||
| if ( isset( $args['output_schema'] ) && ! is_array( $args['output_schema'] ) ) { | ||
| throw new \InvalidArgumentException( | ||
| esc_html__( 'The ability properties should provide a valid `permission_callback` function.' ) | ||
| esc_html__( 'The ability properties should provide a valid `output_schema` definition.' ) | ||
| ); | ||
| } | ||
|
|
||
|
|
@@ -278,6 +280,7 @@ protected function validate_input( $input = null ) { | |
| if ( null === $input ) { | ||
| return true; | ||
| } | ||
|
|
||
| return new \WP_Error( | ||
| 'ability_missing_input_schema', | ||
| sprintf( | ||
|
|
@@ -306,8 +309,8 @@ protected function validate_input( $input = null ) { | |
|
|
||
| /** | ||
| * Checks whether the ability has the necessary permissions. | ||
| * If the permission callback is not set, the default behavior is to allow access | ||
| * when the input provided passes validation. | ||
| * | ||
| * The input is validated against the input schema before it is passed to to permission callback. | ||
| * | ||
| * @since 0.1.0 | ||
| * | ||
|
|
@@ -320,14 +323,6 @@ public function has_permission( $input = null ) { | |
| return $is_valid; | ||
| } | ||
|
|
||
| if ( ! is_callable( $this->permission_callback ) ) { | ||
| return true; | ||
| } | ||
|
|
||
| if ( empty( $this->get_input_schema() ) ) { | ||
| return call_user_func( $this->permission_callback ); | ||
| } | ||
|
Comment on lines
327
to
329
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 is handled by 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. The point is that, if there is no schema, then we don't pass any input. What we agreed upon was that if someone wants to explicitly pass 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. Previously, I considered adding a method for calling these callbacks, but it felt like more code than necessary. However, having a method could help document this expected behavior better. 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.
Can you clarify? If I understood you correctly that behavior is what this change enforces. Previously diff, if there was no input schema, then any With this diff, both no (If you're referring to our internal ability to differentiate between 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. I'm not sure I follow, so let me explain it in a different way:
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. Okay now I'm sure we're not following each other, because that's literally the initial comment I left here explaining why I removed this conditional here, except you're using it to (seemingly) justify the opposite of what I am 😭 I'll add the unit tests for the above edge cases, if that doesn't clear things up (for either of us), i'll revert here and open a separate bug report that follows up #61 . 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. Works for me. 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. The key here is that it needs to be impossible to pass unvalidated input through to
Is it necessary? No. Is it a good measure for defensive coding and clarifying the importance of this to someone new working on this code in the future? Yes, I think so. IMO we should just keep it. It doesn't hurt. 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. Can we bring it back here as discussed? if ( empty( $this->get_input_schema() ) ) {
return call_user_func( $this->permission_callback );
}That's the only remaining item to approve and land this PR. 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. I addressed it with 00d5099. |
||
|
|
||
| return call_user_func( $this->permission_callback, $input ); | ||
gziolo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
|
|
||
justlevine marked this conversation as resolved.
Show resolved
Hide resolved
|
Uh oh!
There was an error while loading. Please reload this page.