-
Notifications
You must be signed in to change notification settings - Fork 5
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
Add optional raw response processing to query context #24
Changes from 13 commits
82bf4f5
66dcee6
5089e70
10de8e4
9764d9e
d59a147
f3c637d
2471cb0
f9c9fa7
9385d43
b524fc3
8367021
f6f9771
84b05de
318afbf
8dd1472
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 |
---|---|---|
|
@@ -99,22 +99,23 @@ public function execute( array $input_variables ): array|WP_Error { | |
} | ||
|
||
// The body is a stream... if we need to read it in chunks, etc. we can do so here. | ||
$response_data = $response->getBody()->getContents(); | ||
$raw_response_data = $response->getBody()->getContents(); | ||
|
||
$is_collection = $this->query_context->output_variables['is_collection'] ?? false; | ||
|
||
if ( isset( $response_data['errors'][0]['message'] ) ) { | ||
if ( isset( $raw_response_data['errors'][0]['message'] ) ) { | ||
$logger = LoggerManager::instance(); | ||
$logger->warning( sprintf( 'Query error: %s', esc_html( $response_data['errors'][0]['message'] ) ) ); | ||
$logger->warning( sprintf( 'Query error: %s', esc_html( $raw_response_data['errors'][0]['message'] ) ) ); | ||
} | ||
|
||
// Optionally process the raw response data using query context custom logic. | ||
$response_data = $this->query_context->process_response( $raw_response_data, $input_variables ); | ||
|
||
// This method always returns an array, even if it's a single item. This | ||
// ensures a consistent response shape. The requestor is expected to inspect | ||
// is_collection and unwrap if necessary. | ||
$results = $this->map_fields( $response_data, $is_collection ); | ||
$results = $this->map_fields( $response_data ); | ||
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. Removing arg |
||
|
||
return [ | ||
'is_collection' => $is_collection, | ||
'is_collection' => $this->query_context->is_collection(), | ||
'metadata' => $this->query_context->get_metadata( $response, $results ), | ||
'results' => $results, | ||
]; | ||
|
@@ -126,6 +127,12 @@ private function get_field_value( array|string $field_value, string $default_val | |
: ( $field_value[0] ?? $default_value ); | ||
|
||
switch ( $field_type ) { | ||
case 'base64': | ||
return base64_decode( $field_value_single ); | ||
|
||
case 'html': | ||
return $field_value_single; | ||
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. 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. escapin late :) |
||
|
||
case 'price': | ||
return sprintf( '$%s', number_format( $field_value_single, 2 ) ); | ||
|
||
|
@@ -136,15 +143,22 @@ private function get_field_value( array|string $field_value, string $default_val | |
return $field_value_single; | ||
} | ||
|
||
private function map_fields( $response_data, $is_collection = false ): array|null { | ||
/** | ||
* Map fields from the response data using the output variables defined by | ||
* the query. | ||
* | ||
* @param string|array|object|null $response_data The response data to map. Can be JSON string, PHP associative array, PHP object, or null. | ||
* @return array|null The mapped fields. | ||
*/ | ||
private function map_fields( string|array|object|null $response_data ): ?array { | ||
$root = $response_data; | ||
$output_variables = $this->query_context->output_variables; | ||
|
||
if ( ! empty( $output_variables['root_path'] ) ) { | ||
$json = new JsonObject( $root ); | ||
$root = $json->get( $output_variables['root_path'] ); | ||
} else { | ||
$root = $is_collection ? $root : [ $root ]; | ||
$root = $this->query_context->is_collection() ? $root : [ $root ]; | ||
} | ||
|
||
if ( empty( $root ) || empty( $output_variables['mappings'] ) ) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
<?php | ||
|
||
namespace RemoteDataBlocks\Tests\Config; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use RemoteDataBlocks\Config\QueryContext; | ||
use RemoteDataBlocks\Test\TestDatasource; | ||
use GuzzleHttp\Psr7\Response; | ||
|
||
class QueryContextTest extends TestCase { | ||
|
||
private $datasource; | ||
private $query_context; | ||
|
||
protected function setUp(): void { | ||
$this->datasource = new TestDatasource(); | ||
$this->query_context = new QueryContext( $this->datasource ); | ||
} | ||
|
||
public function testGetEndpoint() { | ||
$result = $this->query_context->get_endpoint( [] ); | ||
$this->assertEquals( 'https://example.com', $result ); | ||
} | ||
|
||
public function testGetImageUrl() { | ||
$result = $this->query_context->get_image_url(); | ||
$this->assertNull( $result ); | ||
} | ||
|
||
public function testGetMetadata() { | ||
$mock_response = new Response( 200, [ 'Age' => '60' ] ); | ||
$results = [ [ 'id' => 1 ], [ 'id' => 2 ] ]; | ||
|
||
$metadata = $this->query_context->get_metadata( $mock_response, $results ); | ||
|
||
$this->assertArrayHasKey( 'last_updated', $metadata ); | ||
$this->assertArrayHasKey( 'total_count', $metadata ); | ||
$this->assertEquals( 'Last updated', $metadata['last_updated']['name'] ); | ||
$this->assertEquals( 'string', $metadata['last_updated']['type'] ); | ||
$this->assertEquals( 'Total count', $metadata['total_count']['name'] ); | ||
$this->assertEquals( 'number', $metadata['total_count']['type'] ); | ||
$this->assertEquals( 2, $metadata['total_count']['value'] ); | ||
} | ||
|
||
public function testGetRequestMethod() { | ||
$this->assertEquals( 'GET', $this->query_context->get_request_method() ); | ||
} | ||
|
||
public function testGetRequestHeaders() { | ||
$result = $this->query_context->get_request_headers( [] ); | ||
$this->assertEquals( [ 'Content-Type' => 'application/json' ], $result ); | ||
} | ||
|
||
public function testGetRequestBody() { | ||
$this->assertNull( $this->query_context->get_request_body( [] ) ); | ||
} | ||
|
||
public function testGetQueryName() { | ||
$this->assertEquals( 'Query', $this->query_context->get_query_name() ); | ||
} | ||
|
||
public function testIsCollection() { | ||
$this->assertFalse( $this->query_context->is_collection() ); | ||
|
||
$this->query_context->output_variables['is_collection'] = true; | ||
$this->assertTrue( $this->query_context->is_collection() ); | ||
} | ||
|
||
public function testDefaultProcessResponse() { | ||
$raw_data = '{"key": "value"}'; | ||
$this->assertEquals( $raw_data, $this->query_context->process_response( $raw_data, [] ) ); | ||
} | ||
|
||
public function testCustomProcessResponse() { | ||
$custom_query_context = new class($this->datasource) extends QueryContext { | ||
public function process_response( string $raw_response_data, array $input_variables ): string { | ||
// Convert HTML to JSON | ||
$dom = new \DOMDocument(); | ||
$dom->loadHTML( $raw_response_data, LIBXML_NOERROR ); | ||
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase | ||
$title = $dom->getElementsByTagName( 'title' )->item( 0 )->nodeValue; | ||
$paragraphs = $dom->getElementsByTagName( 'p' ); | ||
$content = []; | ||
foreach ( $paragraphs as $p ) { | ||
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase | ||
$content[] = $p->nodeValue; | ||
} | ||
|
||
$data = [ | ||
'title' => $title, | ||
'content' => $content, | ||
]; | ||
|
||
return wp_json_encode( $data ); | ||
} | ||
}; | ||
|
||
$html_data = '<html><head><title>Test Page</title></head><body><p>Paragraph 1</p><p>Paragraph 2</p></body></html>'; | ||
$expected_json = '{"title":"Test Page","content":["Paragraph 1","Paragraph 2"]}'; | ||
|
||
$this->assertEquals( $expected_json, $custom_query_context->process_response( $html_data, [] ) ); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the use case for this
is_collection()
method override? Maybe the response needs to be inspected? In that case, it seems like it should get passed the$response_data
? Or removed