<?php
/** Normalizes GET/DELETE Ability query input before WordPress executes it. */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WordPress 6.9 and 7.0 validate query input for the permission check without
 * sanitizing it. WP_REST_Abilities_V1_Run_Controller::execute_ability() then
 * passes the raw query strings to the callback. Apply the Ability schema to the
 * request itself so the permission callback and execution receive identical,
 * typed input. POST JSON input is already typed and remains untouched.
 *
 * @param mixed           $response Existing short-circuit response.
 * @param array           $handler  Matched REST route handler.
 * @param WP_REST_Request $request  Current request.
 * @return mixed
 */
function wpagent_companion_normalize_ability_query_input( $response, $handler, $request ) {
	if ( ! $request instanceof WP_REST_Request || ! in_array( $request->get_method(), array( 'GET', 'DELETE' ), true ) ) {
		return $response;
	}
	$route = $request->get_route();
	if ( ! is_string( $route ) || ! preg_match( '#^/wp-abilities/v1/abilities/(?P<name>wp-agent/[a-zA-Z0-9\-/]+)/run/?$#', $route, $matches ) ) {
		return $response;
	}
	$name = $matches['name'];
	$ability = wpagent_companion_get_registered_ability( $name );
	if ( ! $ability || ! method_exists( $ability, 'get_input_schema' ) || ! method_exists( $ability, 'normalize_input' ) ) {
		return $response;
	}
	$query = $request->get_query_params();
	if ( ! array_key_exists( 'input', $query ) ) {
		return $response;
	}
	$input  = $ability->normalize_input( $query['input'] );
	$schema = $ability->get_input_schema();
	if ( empty( $schema ) ) {
		return $response;
	}
	$valid = rest_validate_value_from_schema( $input, $schema, 'input' );
	if ( is_wp_error( $valid ) ) {
		$valid->add_data( array( 'status' => 400 ) );
		return $valid;
	}
	$input = rest_sanitize_value_from_schema( $input, $schema, 'input' );
	if ( is_wp_error( $input ) ) {
		$input->add_data( array( 'status' => 400 ) );
		return $input;
	}
	$query['input'] = $input;
	$request->set_query_params( $query );
	return $response;
}
add_filter( 'rest_request_before_callbacks', 'wpagent_companion_normalize_ability_query_input', 5, 3 );
