diff --git a/src/Concerns/GuzzleAware.php b/src/Concerns/GuzzleAware.php new file mode 100644 index 0000000..7626873 --- /dev/null +++ b/src/Concerns/GuzzleAware.php @@ -0,0 +1,56 @@ +<?php + +namespace Cerbero\JsonParser\Concerns; + +use Cerbero\JsonParser\Exceptions\SourceException; +use GuzzleHttp\Client; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\UriInterface; + +/** + * The Guzzle-aware trait. + * + */ +trait GuzzleAware +{ + /** + * Abort if Guzzle is not loaded + * + * @return void + * @throws SourceException + */ + protected function requireGuzzle(): void + { + if (!class_exists(Client::class)) { + throw SourceException::requireGuzzle(); + } + } + + /** + * Retrieve the JSON response of the given URL + * + * @param UriInterface|string $url + * @return ResponseInterface + */ + protected function getJson(UriInterface|string $url): ResponseInterface + { + return (new Client())->get($url, [ + 'headers' => [ + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + ], + ]); + } + + /** + * Retrieve the JSON response of the given request + * + * @param RequestInterface $request + * @return ResponseInterface + */ + protected function sendRequest(RequestInterface $request): ResponseInterface + { + return (new Client())->sendRequest($request); + } +} diff --git a/src/Sources/AnySource.php b/src/Sources/AnySource.php index 4d04d97..aea27eb 100644 --- a/src/Sources/AnySource.php +++ b/src/Sources/AnySource.php @@ -26,6 +26,7 @@ class AnySource extends Source JsonResource::class, LaravelClientResponse::class, Psr7Message::class, + Psr7Request::class, Psr7Stream::class, ]; diff --git a/src/Sources/Endpoint.php b/src/Sources/Endpoint.php index 109bbcf..34d7b8e 100644 --- a/src/Sources/Endpoint.php +++ b/src/Sources/Endpoint.php @@ -3,19 +3,20 @@ namespace Cerbero\JsonParser\Sources; use Cerbero\JsonParser\Concerns\DetectsEndpoints; -use Cerbero\JsonParser\Exceptions\SourceException; -use GuzzleHttp\Client; +use Cerbero\JsonParser\Concerns\GuzzleAware; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\UriInterface; use Traversable; /** * The endpoint source. * - * @property-read string $source + * @property-read UriInterface|string $source */ class Endpoint extends Source { use DetectsEndpoints; + use GuzzleAware; /** * The endpoint response. @@ -28,33 +29,17 @@ class Endpoint extends Source * Retrieve the JSON fragments * * @return Traversable<int, string> + * @throws \Cerbero\JsonParser\Exceptions\SourceException */ public function getIterator(): Traversable { - if (!$this->guzzleIsLoaded()) { - throw SourceException::requireGuzzle(); - } + $this->requireGuzzle(); - $this->response = (new Client())->get($this->source, [ - 'headers' => [ - 'Accept' => 'application/json', - 'Content-Type' => 'application/json', - ], - ]); + $this->response = $this->getJson($this->source); return new Psr7Message($this->response, $this->config); } - /** - * Determine whether the Guzzle client is loaded - * - * @return bool - */ - protected function guzzleIsLoaded(): bool - { - return class_exists(Client::class); - } - /** * Determine whether the JSON source can be handled * @@ -62,7 +47,8 @@ class Endpoint extends Source */ public function matches(): bool { - return is_string($this->source) && $this->isEndpoint($this->source); + // @phpstan-ignore-next-line + return (is_string($this->source) || $this->source instanceof UriInterface) && $this->isEndpoint($this->source); } /** diff --git a/src/Sources/Psr7Message.php b/src/Sources/Psr7Message.php index 7707c71..2471240 100644 --- a/src/Sources/Psr7Message.php +++ b/src/Sources/Psr7Message.php @@ -3,6 +3,7 @@ namespace Cerbero\JsonParser\Sources; use Psr\Http\Message\MessageInterface; +use Psr\Http\Message\RequestInterface; use Traversable; /** @@ -29,7 +30,7 @@ class Psr7Message extends Source */ public function matches(): bool { - return $this->source instanceof MessageInterface; + return $this->source instanceof MessageInterface && !$this->source instanceof RequestInterface; } /** diff --git a/src/Sources/Psr7Request.php b/src/Sources/Psr7Request.php new file mode 100644 index 0000000..0340b96 --- /dev/null +++ b/src/Sources/Psr7Request.php @@ -0,0 +1,60 @@ +<?php + +namespace Cerbero\JsonParser\Sources; + +use Cerbero\JsonParser\Concerns\GuzzleAware; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; +use Traversable; + +/** + * The PSR-7 request source. + * + * @property-read RequestInterface $source + */ +class Psr7Request extends Source +{ + use GuzzleAware; + + /** + * The endpoint response. + * + * @var ResponseInterface|null + */ + protected ?ResponseInterface $response; + + /** + * Retrieve the JSON fragments + * + * @return Traversable<int, string> + * @throws \Cerbero\JsonParser\Exceptions\SourceException + */ + public function getIterator(): Traversable + { + $this->requireGuzzle(); + + $this->response = $this->sendRequest($this->source); + + return new Psr7Message($this->response, $this->config); + } + + /** + * Determine whether the JSON source can be handled + * + * @return bool + */ + public function matches(): bool + { + return $this->source instanceof RequestInterface; + } + + /** + * Retrieve the calculated size of the JSON source + * + * @return int|null + */ + protected function calculateSize(): ?int + { + return $this->response?->getBody()->getSize(); + } +}