$is_valid = true; } /** * Filters the input validation result for an ability. * * Allows developers to add custom validation logic on top of the default * JSON Schema validation. If default validation already failed, the filter * receives the WP_Error object and can add additional error information or * override it. If default validation passed, the filter can add additional * validation checks and return a WP_Error if those checks fail. * * @since 7.1.0 * * @param true|WP_Error $is_valid The validation result from default validation. * @param mixed $input The input data being validated. * @param string $ability_name The name of the ability. */ $validity = apply_filters( 'wp_ability_validate_input', $is_valid, $input, $this->name ); if ( false === $validity ) { return new WP_Error( 'ability_invalid_input', __( 'Invalid input.' ) ); } if ( is_wp_error( $validity ) && $validity->has_errors() ) { return $validity; } return true; } /** * Invokes a callable, ensuring the input is passed through only if the input schema is defined. * * @since 6.9.0 * * @param callable $callback The callable to invoke. * @param mixed $input Optional. The input data for the ability. Default `null`. * @return mixed The result of the callable execution, or a `WP_Error` if the callback threw. */ protected function invoke_callback( callable $callback, $input = null ) { $args = array(); if ( ! empty( $this->get_input_schema() ) ) { $args[] = $input; } try { return $callback( ...$args ); } catch ( Throwable $e ) { return new WP_Error( 'ability_callback_exception', sprintf( /* translators: 1: Ability name, 2: Exception message. */ __( 'Ability "%1$s" callback threw an exception: %2$s' ), $this->name, esc_html( $e->getMessage() ) ) ); } } /** * Checks whether the ability has the necessary permissions. * * Please note that input is not automatically validated against the input schema. * Use `validate_input()` method to validate input before calling this method if needed. * * The {@see 'wp_ability_permission_result'} filter fires after the registered * `permission_callback` returns, allowing plugins to override the result. * * @since 6.9.0 * @since 7.1.0 Added the `wp_ability_permission_result` filter. * * @see validate_input() * * @param mixed $input Optional. The valid input data for permission checking. Default `null`. * @return bool|WP_Error Whether the ability has the necessary permission. */ public function check_permissions( $input = null ) { if ( ! is_callable( $this->permission_callback ) ) { return new WP_Error( 'ability_invalid_permission_callback', /* translators: %s ability name. */ sprintf( __( 'Ability "%s" does not have a valid permission callback.' ), $this->name ) ); } $permission = $this->invoke_callback( $this->permission_callback, $input ); /** * Filters the result of an ability's permission check. * * Fires after the registered `permission_callback` returns. Plugins can use this to layer * additional authorization rules on top of the ability's own permission logic — for example, * multi-factor authorization gates or temporary permission elevation for trusted contexts. * * Filters can return `true` to grant, `false` to deny, or a `WP_Error` to deny with a specific * error code and message. The filter receives whatever the `permission_callback` produced. * Any other return value is coerced to `false`. * * @since 7.1.0 * * @param bool|WP_Error $permission The permission result returned by `permission_callback`. * @param string $ability_name The name of the ability. * @param mixed $input The input data for the permission check. * @param WP_Ability $ability The ability instance. */ $result = apply_filters( 'wp_ability_permission_result', $permission, $this->name, $input, $this ); if ( ! is_bool( $result ) && ! is_wp_error( $result ) ) { $result = false; } return $result; } /** * Executes the ability callback. * * The {@see 'wp_ability_execute_result'} filter fires before this method returns, allowing * plugins to transform the result produced by the registered `execute_callback`. * * @since 6.9.0 * @since 7.1.0 Added the `wp_ability_execute_result` filter. * * @param mixed $input Optional. The input data for the ability. Default `null`. * @return mixed|WP_Error The result of the ability execution, or WP_Error on failure. */ protected function do_execute( $input = null ) { if ( ! is_callable( $this->execute_callback ) ) { $result = new WP_Error( 'ability_invalid_execute_callback', /* translators: %s ability name. */ sprintf( __( 'Ability "%s" does not have a valid execute callback.' ), $this->name ) ); } else { $result = $this->invoke_callback( $this->execute_callback, $input ); } /** * Filters the result returned by an ability's execute callback. * * Fires after the registered execute callback runs. Plugins can use this to transform the * result — response formatting, stripping internal metadata, content safety filtering, * response enrichment, or recovering from a failure by returning a successful value. * * The filter receives whatever the registered callback produced, including a `WP_Error` * if execution failed. Filters may pass the `WP_Error` through unchanged, override it with * a recovered result, or convert a successful result into a `WP_Error`. * * @since 7.1.0 * * @param mixed $result The result returned by the registered `execute_callback`, * or a `WP_Error` if execution failed. * @param string $ability_name The name of the ability. * @param mixed $input The normalized input data. * @param WP_Ability $ability The ability instance. */ return apply_filters( 'wp_ability_execute_result', $result, $this->name, $input, $this ); } /** * Validates output data against the output schema. * * @since 6.9.0 * * @param mixed $output The output data to validate. * @return true|WP_Error Returns true if valid, or a WP_Error object if validation fails. */ protected function validate_output( $output ) { $output_schema = $this->get_output_schema(); if ( empty( $output_schema ) ) { $is_valid = true; } else { $valid_output = rest_validate_value_from_schema( $output, $output_schema, 'output' ); if ( is_wp_error( $valid_output ) ) { $is_valid = new WP_Error( 'ability_invalid_output', sprintf( /* translators: %1$s ability name, %2$s error message. */ __( 'Ability "%1$s" has invalid output. Reason: %2$s' ), $this->name, $valid_output->get_error_message() ) ); } else { $is_valid = true; } } /** * Filters the output validation result for an ability. * * Allows developers to add custom validation logic on top of the default * JSON Schema validation. If default validation already failed, the filter * receives the WP_Error object and can add additional error information or * override it. If default validation passed, the filter can add additional * validation checks and return a WP_Error if those checks fail. * * @since 7.1.0 * * @param true|WP_Error $is_valid The validation result from default validation. * @param mixed $output The output data being validated. * @param string $ability_name The name of the ability. */ $validity = apply_filters( 'wp_ability_validate_output', $is_valid, $output, $this->name ); if ( false === $validity ) { return new WP_Error( 'ability_invalid_output', __( 'Invalid output.' ) ); } if ( is_wp_error( $validity ) && $validity->has_errors() ) { return $validity; } return true; } /** * Executes the ability after input validation and running a permission check. * Before returning the return value, it also validates the output. * * @since 6.9.0 * @since 7.1.0 Added the `wp_ability_invoked` action. * @since 7.1.0 Added the `wp_pre_execute_ability` filter. * * @param mixed $input Optional. The input data for the ability. Default `null`. * @return mixed|WP_Error The result of the ability execution, or WP_Error on failure. */ public function execute( $input = null ) { /** * Fires when an ability is invoked, before any processing takes place. * * This action fires for every call regardless of outcome (validation failure, * permission denial, short-circuit, or successful execution), and before input * normalization so the raw input is captured as-is. * * @since 7.1.0 * * @param string $ability_name The name of the ability. * @param mixed $input The raw input data for the ability, before normalization. * @param WP_Ability $ability The ability instance. */ do_action( 'wp_ability_invoked', $this->name, $input, $this ); $pre_execute_sentinel = new WP_Filter_Sentinel(); /** * Filters whether to short-circuit ability execution. * * Returning a value other than the received default bypasses the rest of `execute()` — * input normalization, input validation, permission checks, the registered execute callback, * output validation, and the surrounding actions — and the value is returned to the caller * as-is. Useful for cached responses, rate limiting, maintenance mode, and test mocking. * * To continue with normal execution, return `$pre` unchanged. This preserves any value * (including `null`, `false`, or arbitrary objects) as a valid short-circuit result. * * Because validation is bypassed, callers that short-circuit are responsible for the * integrity of any value they consume from `$input`. * * @since 7.1.0 * * @param mixed $pre The pre-computed result. Return this value unchanged to continue execution. * Default `WP_Filter_Sentinel` instance unique to this invocation. * @param string $ability_name The name of the ability. * @param mixed $input The raw input passed to `execute()`. * @param WP_Ability $ability The ability instance. */ $pre = apply_filters( 'wp_pre_execute_ability', $pre_execute_sentinel, $this->name, $input, $this ); if ( $pre !== $pre_execute_sentinel ) { return $pre; } $input = $this->normalize_input( $input ); if ( is_wp_error( $input ) ) { return $input; } $is_valid = $this->validate_input( $input ); if ( is_wp_error( $is_valid ) ) { return $is_valid; } $has_permissions = $this->check_permissions( $input ); if ( true !== $has_permissions ) { if ( is_wp_error( $has_permissions ) ) { // Don't leak the permission check error to someone without the correct perms. _doing_it_wrong( __METHOD__, esc_html( $has_permissions->get_error_message() ), '6.9.0' ); } return new WP_Error( 'ability_invalid_permissions', /* translators: %s ability name. */ sprintf( __( 'Ability "%s" does not have necessary permission.' ), $this->name ) ); } /** * Fires before an ability gets executed, after input validation and permissions check. * * @since 6.9.0 * @since 7.1.0 Added the `$ability` parameter. * * @param string $ability_name The name of the ability. * @param mixed $input The input data for the ability. * @param WP_Ability $ability The ability instance. */ do_action( 'wp_before_execute_ability', $this->name, $input, $this ); $result = $this->do_execute( $input ); if ( is_wp_error( $result ) ) { return $result; } $is_valid = $this->validate_output( $result ); if ( is_wp_error( $is_valid ) ) { return $is_valid; } /** * Fires immediately after an ability finished executing. * * @since 6.9.0 * @since 7.1.0 Added the `$ability` parameter. * * @param string $ability_name The name of the ability. * @param mixed $input The input data for the ability. * @param mixed $result The result of the ability execution. * @param WP_Ability $ability The ability instance. */ do_action( 'wp_after_execute_ability', $this->name, $input, $result, $this ); return $result; } /** * Wakeup magic method. * * @since 6.9.0 * @throws LogicException If the ability object is unserialized. * This is a security hardening measure to prevent unserialization of the ability. */ public function __wakeup(): void { throw new LogicException( __CLASS__ . ' should never be unserialized.' ); } /** * Sleep magic method. * * @since 6.9.0 * @throws LogicException If the ability object is serialized. * This is a security hardening measure to prevent serialization of the ability. */ public function __sleep(): array { throw new LogicException( __CLASS__ . ' should never be serialized.' ); } } Page not found – My Blog
Small totara tree on ridge above Long Point

Page not found

The page you are looking for doesn't exist, or it has been moved. Please try searching using the form below.