diff --git a/src/Response/Elasticsearch.php b/src/Response/Elasticsearch.php index 51a77a02b..4f33aced2 100644 --- a/src/Response/Elasticsearch.php +++ b/src/Response/Elasticsearch.php @@ -10,7 +10,7 @@ * Elasticsearch B.V licenses this file to you under the MIT License. * See the LICENSE file in the project root for more information. */ -declare(strict_types = 1); +declare(strict_types=1); namespace Elastic\Elasticsearch\Response; @@ -36,11 +36,10 @@ */ class Elasticsearch implements ElasticsearchInterface, ResponseInterface, ArrayAccess { - const HEADER_CHECK = 'X-Elastic-Product'; - const PRODUCT_NAME = 'Elasticsearch'; - use ProductCheckTrait; use MessageResponseTrait; + public const HEADER_CHECK = 'X-Elastic-Product'; + public const PRODUCT_NAME = 'Elasticsearch'; protected array $asArray; protected object $asObject; @@ -67,6 +66,10 @@ public function setResponse(ResponseInterface $response, bool $throwException = // Check for Serverless response $this->serverless = $this->isServerlessResponse($response); $this->response = $response; + + unset($this->asArray, $this->asObject); + $this->asString = ''; + $status = $response->getStatusCode(); if ($throwException && $status > 399 && $status < 500) { $error = new ClientResponseException( @@ -104,14 +107,14 @@ public function isServerless(): bool */ public function asBool(): bool { - return $this->response->getStatusCode() >=200 && $this->response->getStatusCode() < 300; + return $this->response->getStatusCode() >= 200 && $this->response->getStatusCode() < 300; } /** * Converts the body content to array, if possible. * Otherwise, it throws an UnknownContentTypeException * if Content-Type is not specified or unknown. - * + * * @throws UnknownContentTypeException */ public function asArray(): array @@ -147,7 +150,7 @@ public function asArray(): array * Converts the body content to object, if possible. * Otherwise, it throws an UnknownContentTypeException * if Content-Type is not specified or unknown. - * + * * @throws UnknownContentTypeException */ public function asObject(): object @@ -197,7 +200,7 @@ public function __toString(): string /** * Access the body content as object properties - * + * * @see https://www.php.net/manual/en/language.oop5.overloading.php#object.get */ public function __get($name) @@ -207,17 +210,17 @@ public function __get($name) /** * ArrayAccess interface - * + * * @see https://www.php.net/manual/en/class.arrayaccess.php */ public function offsetExists($offset): bool { return isset($this->asArray()[$offset]); } - + /** * ArrayAccess interface - * + * * @see https://www.php.net/manual/en/class.arrayaccess.php * * @return mixed @@ -230,7 +233,7 @@ public function offsetGet($offset) /** * ArrayAccess interface - * + * * @see https://www.php.net/manual/en/class.arrayaccess.php */ public function offsetSet($offset, $value): void @@ -240,7 +243,7 @@ public function offsetSet($offset, $value): void /** * ArrayAccess interface - * + * * @see https://www.php.net/manual/en/class.arrayaccess.php */ public function offsetUnset($offset): void @@ -251,11 +254,11 @@ public function offsetUnset($offset): void /** * Map the response body to an object of a specific class * by default the class is the PHP standard one (stdClass) - * + * * This mapping works only for ES|QL results (with columns and values) * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/esql.html - * - * @return object[] + * + * @return object[] */ public function mapTo(string $class = stdClass::class): array { @@ -264,13 +267,13 @@ public function mapTo(string $class = stdClass::class): array throw new UnknownContentTypeException(sprintf( "The response is not a valid ES|QL result. I cannot mapTo(\"%s\")", $class - )); + )); } $iterator = []; $ncol = count($response['columns']); foreach ($response['values'] as $value) { - $obj = new $class; - for ($i=0; $i < $ncol; $i++) { + $obj = new $class(); + for ($i = 0; $i < $ncol; $i++) { $field = Utility::formatVariableName($response['columns'][$i]['name']); if ($class !== stdClass::class && !property_exists($obj, $field)) { continue; @@ -306,4 +309,4 @@ public function mapTo(string $class = stdClass::class): array } return $iterator; } -} \ No newline at end of file +} diff --git a/tests/Response/ElasticsearchTest.php b/tests/Response/ElasticsearchTest.php index dd48f4acb..63207ddff 100644 --- a/tests/Response/ElasticsearchTest.php +++ b/tests/Response/ElasticsearchTest.php @@ -10,7 +10,7 @@ * Elasticsearch B.V licenses this file to you under the MIT License. * See the LICENSE file in the project root for more information. */ -declare(strict_types = 1); +declare(strict_types=1); namespace Elastic\Elasticsearch\Tests\Response; @@ -26,6 +26,7 @@ use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseInterface; use stdClass; + class ElasticsearchTest extends TestCase { protected Psr17Factory $psr17Factory; @@ -38,7 +39,7 @@ public function setUp(): void { $this->psr17Factory = new Psr17Factory(); $this->elasticsearch = new Elasticsearch(); - + $this->response200 = $this->psr17Factory->createResponse(200) ->withHeader('X-Elastic-Product', 'Elasticsearch') ->withHeader('Content-Type', 'application/json'); @@ -52,7 +53,7 @@ public function setUp(): void ->withHeader('Content-Type', 'application/json'); } - public function testAsArray() + public function testAsArray(): void { $array = ['foo' => 'bar']; $body = $this->psr17Factory->createStream(json_encode($array)); @@ -60,7 +61,7 @@ public function testAsArray() $this->assertEquals($array, $this->elasticsearch->asArray()); } - public function testAsString() + public function testAsString(): void { $json = json_encode(['foo' => 'bar']); $body = $this->psr17Factory->createStream($json); @@ -68,7 +69,7 @@ public function testAsString() $this->assertEquals($json, $this->elasticsearch->asString()); } - public function testAsObject() + public function testAsObject(): void { $json = json_encode(['foo' => 'bar']); $body = $this->psr17Factory->createStream($json); @@ -78,25 +79,22 @@ public function testAsObject() $this->assertEquals('bar', $obj->foo); } - public function testAsBoolIsTrueWith200() + public function testAsBoolIsTrueWith200(): void { $this->elasticsearch->setResponse($this->response200); $this->assertTrue($this->elasticsearch->asBool()); } - public function testAsBoolIsFalseWith400() + public function testAsBoolIsFalseWith400(): void { - try { - $this->elasticsearch->setResponse($this->response400); - } catch (ClientResponseException $e) { - $this->assertFalse($this->elasticsearch->asBool()); - } + $this->elasticsearch->setResponse($this->response400, false); + $this->assertFalse($this->elasticsearch->asBool()); } /** * @covers Elastic\Elasticsearch\Response\Elasticsearch::__toString() */ - public function testSerializeAsString() + public function testSerializeAsString(): void { $json = json_encode(['foo' => 'bar']); $body = $this->psr17Factory->createStream($json); @@ -107,12 +105,12 @@ public function testSerializeAsString() /** * @doesNotPerformAssertions */ - public function testSetResponse() + public function testSetResponse(): void { $this->elasticsearch->setResponse($this->response200); } - public function testSetResponseFromUnknownSourceThrowProductCheckException() + public function testSetResponseFromUnknownSourceThrowProductCheckException(): void { $response = $this->psr17Factory->createResponse(200) ->withHeader('Content-Type', 'application/json'); @@ -121,13 +119,13 @@ public function testSetResponseFromUnknownSourceThrowProductCheckException() $this->elasticsearch->setResponse($response); } - public function testSetResponseWith400ThrowException() + public function testSetResponseWith400ThrowException(): void { $this->expectException(ClientResponseException::class); $this->elasticsearch->setResponse($this->response400); } - public function testSetResponseWith500ThrowException() + public function testSetResponseWith500ThrowException(): void { $this->expectException(ServerResponseException::class); $this->elasticsearch->setResponse($this->response500); @@ -136,15 +134,15 @@ public function testSetResponseWith500ThrowException() /** * @doesNotPerformAssertions */ - public function testSetResponseWith400AndThrowFalseDoesNotThrowException() + public function testSetResponseWith400AndThrowFalseDoesNotThrowException(): void { $this->elasticsearch->setResponse($this->response400, false); } - /** - * @doesNotPerformAssertions - */ - public function testSetResponseWith500AndThrowFalseDoesNotThrowException() + /** + * @doesNotPerformAssertions + */ + public function testSetResponseWith500AndThrowFalseDoesNotThrowException(): void { $this->elasticsearch->setResponse($this->response500, false); } @@ -152,7 +150,7 @@ public function testSetResponseWith500AndThrowFalseDoesNotThrowException() /** * @covers Elastic\Elasticsearch\Response\Elasticsearch::offsetGet */ - public function testAccessAsArray() + public function testAccessAsArray(): void { $array = ['foo' => 'bar']; $body = $this->psr17Factory->createStream(json_encode($array)); @@ -164,7 +162,7 @@ public function testAccessAsArray() /** * @covers Elastic\Elasticsearch\Response\Elasticsearch::offsetExists */ - public function testIsSetArrayAccess() + public function testIsSetArrayAccess(): void { $array = ['foo' => 'bar']; $body = $this->psr17Factory->createStream(json_encode($array)); @@ -176,7 +174,7 @@ public function testIsSetArrayAccess() /** * @covers Elastic\Elasticsearch\Response\Elasticsearch::offsetSet */ - public function testSetArrayAccessThrowException() + public function testSetArrayAccessThrowException(): void { $array = ['foo' => 'bar']; $body = $this->psr17Factory->createStream(json_encode($array)); @@ -189,7 +187,7 @@ public function testSetArrayAccessThrowException() /** * @covers Elastic\Elasticsearch\Response\Elasticsearch::offsetSet */ - public function testUnsetArrayAccessThrowException() + public function testUnsetArrayAccessThrowException(): void { $array = ['foo' => 'bar']; $body = $this->psr17Factory->createStream(json_encode($array)); @@ -202,7 +200,7 @@ public function testUnsetArrayAccessThrowException() /** * @covers Elastic\Elasticsearch\Response\Elasticsearch::__get() */ - public function testAccessAsObject() + public function testAccessAsObject(): void { $array = ['foo' => 'bar']; $body = $this->psr17Factory->createStream(json_encode($array)); @@ -211,7 +209,7 @@ public function testAccessAsObject() $this->assertEquals($array['foo'], $this->elasticsearch->foo); } - public function testWithStatusForPsr7Version1And2Compatibility() + public function testWithStatusForPsr7Version1And2Compatibility(): void { $this->elasticsearch->setResponse($this->response200); @@ -219,7 +217,7 @@ public function testWithStatusForPsr7Version1And2Compatibility() $this->assertEquals(400, $this->elasticsearch->getStatusCode()); } - public function testMapToStdClassAsDefault() + public function testMapToStdClassAsDefault(): void { $array = [ 'columns' => [ @@ -244,7 +242,7 @@ public function testMapToStdClassAsDefault() $this->assertEquals(DateTime::class, get_class($iterator[1]->b)); } - public function testMapToStdClass() + public function testMapToStdClass(): void { $array = [ 'columns' => [ @@ -265,7 +263,7 @@ public function testMapToStdClass() $this->assertEquals(stdClass::class, get_class($iterator[1])); } - public function testMapToWithoutEsqlResponseWillThrowException() + public function testMapToWithoutEsqlResponseWillThrowException(): void { $array = ['foo' => 'bar']; $body = $this->psr17Factory->createStream(json_encode($array)); @@ -275,7 +273,7 @@ public function testMapToWithoutEsqlResponseWillThrowException() $iterator = $this->elasticsearch->mapTo(); } - public function testMapToCustomClass() + public function testMapToCustomClass(): void { $array = [ 'columns' => [ @@ -299,12 +297,12 @@ public function testMapToCustomClass() $this->assertEquals('', $iterator[0]->c); } - public function testIsServerlessFalseByDefault() + public function testIsServerlessFalseByDefault(): void { $this->assertFalse($this->elasticsearch->isServerless()); } - public function testIsServerlessTrueWithServerlessResponse() + public function testIsServerlessTrueWithServerlessResponse(): void { $this->elasticsearch->setResponse( $this->response200->withHeader(Client::API_VERSION_HEADER, Client::API_VERSION) @@ -312,9 +310,20 @@ public function testIsServerlessTrueWithServerlessResponse() $this->assertTrue($this->elasticsearch->isServerless()); } - public function testIsServerlessFalseIfNotServerlessResponse() + public function testIsServerlessFalseIfNotServerlessResponse(): void { $this->elasticsearch->setResponse($this->response200); $this->assertFalse($this->elasticsearch->isServerless()); } -} \ No newline at end of file + + public function testCacheIsClearedOnSetResponse(): void + { + $firstBody = $this->psr17Factory->createStream(json_encode(['foo' => 'bar'])); + $this->elasticsearch->setResponse($this->response200->withBody($firstBody)); + $this->assertSame('bar', $this->elasticsearch->asArray()['foo']); + + $secondBody = $this->psr17Factory->createStream(json_encode(['foo' => 'baz'])); + $this->elasticsearch->setResponse($this->response200->withBody($secondBody)); + $this->assertSame('baz', $this->elasticsearch->asArray()['foo']); + } +}