*/ abstract public function get_input_schema(); /** * Get the JSON Schema for ability output. * * @since 2.5.2 * @return array */ abstract public function get_output_schema(); /** * Execute the ability. * * @param array $input Validated input data. * @since 2.5.2 * @return array|\WP_Error */ abstract public function execute( $input ); /** * Check whether this ability is enabled based on its option gate. * * Returns false when the ability has a gate key and the corresponding * option is falsy. Used by the registrar to skip registration of * disabled abilities so they don't appear in MCP listings. * * @since 2.6.0 * @return bool */ public function is_enabled() { if ( ! empty( $this->gated ) && ! get_option( $this->gated, true ) ) { return false; } return true; } /** * Permission callback. * * Delegates to current_user_can() with the configured capability. * * @since 2.5.2 * @return bool */ public function permission_callback() { if ( ! get_option( 'srfm_abilities_api', false ) ) { return false; } if ( ! $this->is_enabled() ) { return false; } return current_user_can( $this->capability ); } /** * Check if this ability meets the minimum capability policy. * * Prevents third-party abilities registered via srfm_register_abilities * from downgrading the required capability below manage_options. * * @since 2.5.2 * @return bool */ public function meets_capability_policy() { return self::MIN_CAPABILITY === $this->capability; } /** * Get ability annotations. * * Returns MCP-compatible annotations for readonly, destructive, idempotent, * priority, and openWorldHint flags. Subclasses should override to customize. * * @since 2.5.2 * @return array */ public function get_annotations() { return [ 'readonly' => false, 'destructive' => false, 'idempotent' => false, 'priority' => 2.0, 'openWorldHint' => false, ]; } /** * Execution wrapper with pre/post hooks. * * @param array $input Validated input data. * @since 2.5.2 * @return array|\WP_Error */ public function execute_wrapper( $input ) { /** * Fires before an ability is executed. * * @param string $id Ability ID. * @param array $input Input data. * @since 2.5.2 */ do_action( 'srfm_before_ability_execute', $this->id, $input ); $output = $this->execute( $input ); /** * Fires after an ability is executed. * * @param string $id Ability ID. * @param array $input Input data. * @param array|\WP_Error $output Output data. * @since 2.5.2 */ do_action( 'srfm_after_ability_execute', $this->id, $input, $output ); return $output; } /** * Register this ability with the WordPress Abilities API. * * @since 2.5.2 * @return void */ public function register() { if ( ! function_exists( 'wp_register_ability' ) ) { return; } $annotations = $this->get_annotations(); // wp_register_ability() is a WP 6.9+ Abilities API function. It is only reached // after the function_exists() guard above (and via the wp_abilities_api_init hook), // so it is inert on WP 6.4-6.8. Plugin Check's static WP-version check cannot see the // runtime guard, so it reports a false positive here. wp_register_ability( $this->id, [ 'label' => $this->label, 'description' => $this->description, 'category' => $this->category, 'input_schema' => $this->get_input_schema(), 'output_schema' => $this->get_output_schema(), 'permission_callback' => [ $this, 'permission_callback' ], 'execute_callback' => [ $this, 'execute_wrapper' ], 'meta' => [ 'show_in_rest' => true, 'annotations' => $annotations, 'mcp' => [ 'public' => false, ], ], ] ); } /** * Get the ability ID. * * @since 2.5.2 * @return string */ public function get_id() { return $this->id; } }