Skip to content

Fix bug in request details filter, and update preprocess response #595

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

Merged
merged 2 commits into from
Jun 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions docs/extending/query.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,17 +165,26 @@ The `image_url` property defines an image URL that represents the query in the U

### preprocess_response: callable

If you need to pre-process the response in some way before the output variables are extracted, provide a `preprocess_response` function. The function will receive the deserialized response.
If you need to pre-process the response in some way before the output schema is applied, provide a `preprocess_response` function. The function will receive the deserialized response and an array of `$request_details` which describes the HTTP request that was just executed. The function should return an associative array that will be passed to the output schema for extraction.

If you need to use an input variable in the pre-processing logic, first set it via the `request_headers` property and then access it via `$request_details['options']['headers']`.

#### Example

```php
'preprocess_response' => function( mixed $response_data, array $input_variables ): array {
$some_computed_property = compute_property( $response_data['foo']['bar'] ?? '' );
'request_headers' => function( array $input_variables ): array {
return [
'X-Record-ID' => $input_variables['record_id'],
];
},
'preprocess_response' => function( mixed $response_data, array $request_details ): array {
$record_id = $request_details['options']['headers']['X-Record-ID'] ?? '';

return array_merge(
$response_data,
[ 'computed_property' => $some_computed_property ]
return array_filter(
$response_data['data'] ?? [],
static function( mixed $record ) use ( $record_id ): bool {
return $record['id'] === $record_id;
}
);
},
```
Expand Down
6 changes: 3 additions & 3 deletions inc/Config/Query/HttpQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,10 @@ public static function get_config_schema(): array {
* shape needs significant transformation.
*
* @param mixed $response_data The raw deserialized response data.
* @param array $input_variables The input variables for this query.
* @param array $request_details The request details.
* @return mixed Preprocessed response data.
*/
public function preprocess_response( mixed $response_data, array $input_variables ): mixed {
return $this->get_or_call_from_config( 'preprocess_response', $response_data, $input_variables ) ?? $response_data;
public function preprocess_response( mixed $response_data, array $request_details ): mixed {
return $this->get_or_call_from_config( 'preprocess_response', $response_data, $request_details ) ?? $response_data;
}
}
2 changes: 1 addition & 1 deletion inc/Config/Query/HttpQueryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ public function get_endpoint( array $input_variables ): string;
public function get_request_method(): string;
public function get_request_headers( array $input_variables ): array|WP_Error;
public function get_request_body( array $input_variables ): array|null;
public function preprocess_response( mixed $response_data, array $input_variables ): mixed;
public function preprocess_response( mixed $response_data, array $request_details ): mixed;
}
12 changes: 7 additions & 5 deletions inc/Config/QueryRunner/QueryRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ protected function get_request_details( HttpQueryInterface $query, array $input_
$user = $parsed_url['user'] ?? '';
$path = $parsed_url['path'] ?? '';

$query = ! empty( $parsed_url['query'] ?? '' ) ? '?' . $parsed_url['query'] : '';
$query_params = ! empty( $parsed_url['query'] ?? '' ) ? '?' . $parsed_url['query'] : '';
$port = ! empty( $parsed_url['port'] ?? '' ) ? ':' . $parsed_url['port'] : '';
$pass = ! empty( $parsed_url['pass'] ?? '' ) ? ':' . $parsed_url['pass'] : '';
$pass = ( $user || $pass ) ? $pass . '@' : '';
Expand All @@ -106,7 +106,7 @@ protected function get_request_details( HttpQueryInterface $query, array $input_
RequestOptions::JSON => $body,
],
'origin' => $origin,
'uri' => sprintf( '%s%s%s', $origin, $path, $query ),
'uri' => sprintf( '%s%s%s', $origin, $path, $query_params ),
];

/**
Expand Down Expand Up @@ -253,7 +253,7 @@ public function execute( HttpQueryInterface $query, array $input_variables ): ar
}

// Preprocess the response data.
$response_data = $this->preprocess_response( $query, $raw_response_data['response_data'], $input_variables );
$response_data = $this->preprocess_response( $query, $raw_response_data['response_data'], $request_details );

// Determine if the response data is expected to be a collection.
$output_schema = $query->get_output_schema();
Expand Down Expand Up @@ -362,11 +362,13 @@ protected function deserialize_response( string $raw_response_data, array $input
/**
* Preprocess the response data before it is passed to the response parser.
*
* @param HttpQueryInterface $query The query.
* @param array $response_data The raw response data.
* @param array $request_details The request details.
* @return array Preprocessed response. The deserialized response data or (re-)serialized JSON.
*/
protected function preprocess_response( HttpQueryInterface $query, mixed $response_data, array $input_variables ): mixed {
return $query->preprocess_response( $response_data, $input_variables );
protected function preprocess_response( HttpQueryInterface $query, mixed $response_data, array $request_details ): mixed {
return $query->preprocess_response( $response_data, $request_details );
}

/**
Expand Down
3 changes: 1 addition & 2 deletions inc/Integrations/Google/Sheets/GoogleSheetsDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,8 @@ function ( $row, $index ) use ( $columns ) {
return $response_data;
}

public static function preprocess_get_response( array $response_data, array $input_variables ): array {
public static function preprocess_get_response( array $response_data, ?string $row_id = null ): array {
$selected_row = null;
$row_id = $input_variables['row_id'];

if ( isset( $response_data['values'] ) && is_array( $response_data['values'] ) ) {
$values = $response_data['values'];
Expand Down
39 changes: 10 additions & 29 deletions inc/Integrations/Google/Sheets/GoogleSheetsIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
class GoogleSheetsIntegration {
public static function init(): void {
add_action( 'init', [ __CLASS__, 'register_blocks' ], 10, 0 );
add_filter( 'remote_data_blocks_request_details', [ __CLASS__, 'enhance_request_details' ], 10, 3 );
}

public static function register_blocks(): void {
Expand Down Expand Up @@ -103,8 +102,14 @@ private static function get_query(
'endpoint' => $data_source->get_endpoint() . '/values/' . rawurlencode( $sheet['name'] ),
'input_schema' => $input_schema,
'output_schema' => $output_schema,
'preprocess_response' => function ( mixed $response_data, array $input_variables ): array {
return GoogleSheetsDataSource::preprocess_get_response( $response_data, $input_variables );
'request_headers' => function ( array $input_variables ) use ( $data_source ): array {
return array_merge(
$data_source->get_request_headers(),
[ 'X-Row-ID' => $input_variables['row_id'] ?? null ]
);
},
'preprocess_response' => function ( mixed $response_data, array $request_details ): array {
return GoogleSheetsDataSource::preprocess_get_response( $response_data, $request_details['options']['headers']['X-Row-ID'] ?? null );
},
] );
}
Expand All @@ -124,8 +129,8 @@ private static function get_list_query(
'endpoint' => $data_source->get_endpoint() . '/values/' . rawurlencode( $sheet['name'] ),
'input_schema' => [],
'output_schema' => $output_schema,
'preprocess_response' => function ( mixed $response_data ): array {
return GoogleSheetsDataSource::preprocess_list_response( $response_data );
'preprocess_response' => function ( mixed $response_data, array $request_details ): array {
return GoogleSheetsDataSource::preprocess_list_response( $response_data, $request_details );
},
] );
}
Expand Down Expand Up @@ -187,28 +192,4 @@ public static function get_block_registration_snippets( array $data_source_confi

return $snippets;
}

/**
* Due to the fact that we are using the same query for both the get and list queries, and
* only filtering out the results based on the input variables, the in-memory cache will not
* work as expected. This enhances the request details to include the input variables, so that
* the in-memory cache will be able to differenciate each request.
*
* @param array<string, mixed> $request_details The request details.
* @param string $_query The query being executed.
* @param array<string, mixed> $input_variables The input variables for the current request.
* @return array<string, array{
* method: string,
* options: array<string, mixed>,
* origin: string,
* uri: string,
* }>
*/
public static function enhance_request_details( array $request_details, string $_query, array $input_variables ): array {
if ( isset( $request_details['origin'] ) && 'https://sheets.googleapis.com' === $request_details['origin'] && ! empty( $input_variables ) ) {
$request_details['input_variables'] = $input_variables;
}

return $request_details;
}
}
2 changes: 1 addition & 1 deletion tests/inc/Mocks/MockQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static function create( array $config = [], ?ValidatorInterface $validato
], $validator ?? new MockValidator() );
}

public function preprocess_response( mixed $response_data, array $input_variables ): mixed {
public function preprocess_response( mixed $response_data, array $request_details ): mixed {
if ( null !== $this->response_data ) {
return $this->response_data;
}
Expand Down
Loading