From 7f15c0bb3dbc9698ca4c21ac29bed202c80f59e1 Mon Sep 17 00:00:00 2001 From: Jared Meyering Date: Thu, 20 Oct 2016 22:50:18 -0500 Subject: [PATCH] Allow the hypermedia parser to be set manually, this provides support for custom use cases where HAL api's don't completely follow the specification but are close enough that this library would still be helpful. Fixes #10 --- CHANGELOG.md | 9 ++ spec/ExplorerSpec.php | 13 +++ spec/Hypermedia/ParserSpec.php | 6 ++ src/Explorer.php | 41 ++++++++- src/Hypermedia/Parser.php | 30 ++++--- src/Hypermedia/ParserInterface.php | 131 +++++++++++++++++++++++++++++ 6 files changed, 213 insertions(+), 17 deletions(-) create mode 100644 src/Hypermedia/ParserInterface.php diff --git a/CHANGELOG.md b/CHANGELOG.md index c257a9b..9fbce14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # CHANGELOG +## 1.5.0 +* Allow the hypermedia parser to be set manually, this provides support for +custom use cases where HAL API's don't completely follow the specification +but are close enough that this library would still be helpful. +Added ParserInterface to facilitate this. + +## 1.4.0 +* Allow for parsing absolute URL's correctly within makeRequest. + ## 1.3.0 * Add the `patchUpdateRelation` method to the explorer to support partial object updates. diff --git a/spec/ExplorerSpec.php b/spec/ExplorerSpec.php index a36586f..cef2685 100644 --- a/spec/ExplorerSpec.php +++ b/spec/ExplorerSpec.php @@ -6,6 +6,7 @@ use Prophecy\Argument; use Psr\Http\Message\ResponseInterface; use HalExplorer\ClientAdapters\AdapterInterface; +use HalExplorer\Hypermedia\ParserInterface; use HalExplorer\Exceptions\LinkNotFoundException; class ExplorerSpec extends ObjectBehavior @@ -25,6 +26,18 @@ function it_should_set_and_retreive_a_client_adapter(AdapterInterface $clientAda $this->getAdapter()->shouldBeEqualTo($clientAdapter); } + function it_should_return_the_default_parser_if_none_was_set(ParserInterface $parser) + { + $this->getParser()->shouldReturnAnInstanceOf("\HalExplorer\Hypermedia\Parser"); + + } + + function it_should_set_and_retreive_a_parser(ParserInterface $parser) + { + $this->setParser($parser); + $this->getParser()->shouldBeEqualTo($parser); + } + function it_should_set_and_retreive_a_base_url() { $this->setBaseUrl($this->baseUrl); diff --git a/spec/Hypermedia/ParserSpec.php b/spec/Hypermedia/ParserSpec.php index 1c4e6c6..b0137da 100644 --- a/spec/Hypermedia/ParserSpec.php +++ b/spec/Hypermedia/ParserSpec.php @@ -5,9 +5,15 @@ use PhpSpec\ObjectBehavior; use Prophecy\Argument; use Psr\Http\Message\ResponseInterface; +use HalExplorer\Hypermedia\Parser; class ParserSpec extends ObjectBehavior { + function it_should_implement_the_abstract_parser(Parser $parser) + { + $this->shouldImplement("\HalExplorer\Hypermedia\ParserInterface"); + } + function it_should_know_if_a_response_has_links_or_not(ResponseInterface $response) { $response->getBody()->willReturn(file_get_contents(__DIR__ . "/../fixtures/halResponse.json")); diff --git a/src/Explorer.php b/src/Explorer.php index 024867d..d0a407f 100644 --- a/src/Explorer.php +++ b/src/Explorer.php @@ -5,6 +5,7 @@ use HalExplorer\ClientAdapters\AdapterInterface; use HalExplorer\Exceptions\LinkNotFoundException; use HalExplorer\Exceptions\DeprecatedLinkException; +use HalExplorer\Hypermedia\ParserInterface; use HalExplorer\Hypermedia\Parser as HypermediaParser; use HalExplorer\Hypermedia\UriTemplate; use Psr\Http\Message\ResponseInterface; @@ -47,6 +48,13 @@ class Explorer */ protected $adapter; + /** + * The parser that will process all HAL links, embeds, and curies. + * + * @var ParserInterface + */ + protected $parser; + /** * How to add default values to the currently established * @@ -127,9 +135,8 @@ public function makeRequest($method, $uri, array $options = []) */ public function getParsedBody(ResponseInterface $response) { - $parser = new HypermediaParser(); - return $parser->parseJsonBody($response); + return json_decode($response->getBody()); } /** @@ -232,7 +239,7 @@ public function deleteRelation(ResponseInterface $response, $id, array $options */ protected function followLink($method, ResponseInterface $response, $id, array $options = []) { - $hypermediaParser = new HypermediaParser(); + $hypermediaParser = $this->getParser(); $link = $hypermediaParser->getLink($response, $id); if ($link === null) { @@ -299,6 +306,34 @@ public function setAdapter($adapter) return $this; } + /** + * Set the hypermedia parser + * + * @param $parser ParserInterface + * + * @return self + */ + public function setParser(ParserInterface $parser) { + $this->parser = $parser; + + return $this; + } + + /** + * Retrieve the set parser on the explorer, or return the default parser. + * + * @return ParserInterface + */ + public function getParser() { + $parser = $this->parser; + if (is_null($this->parser)) { + $parser = new HypermediaParser(); + } + + return $parser; + } + + /** * Modify the existing defaults array. To meet your needs. * diff --git a/src/Hypermedia/Parser.php b/src/Hypermedia/Parser.php index b16ed68..b4f0b5b 100644 --- a/src/Hypermedia/Parser.php +++ b/src/Hypermedia/Parser.php @@ -2,6 +2,7 @@ namespace HalExplorer\Hypermedia; +use HalExplorer\Hypermedia\ParserInterface; use Psr\Http\Message\ResponseInterface; /** @@ -10,26 +11,15 @@ * This class assumes a response actually implements the * {@link https://tools.ietf.org/html/draft-kelly-json-hal-07 HAL Spec} * correctly. Malformed/Incorrectly imeplemented responses be warned. + * If you need non-standard functionality, you can implement the + * {@see ParserInterface} for your own use cases. * * @author Jared Meyering * */ -class Parser +class Parser implements ParserInterface { - /** - * Parses a json message body and returns the result - * - * @param ResponseInterface $response - * - * @return \stdClass|array stdClass if a single response, array of stdClass - * for a collection - */ - public function parseJsonBody(ResponseInterface $response) - { - return json_decode($response->getBody()); - } - /** * Does the ResponseInterface have any links? * @@ -243,4 +233,16 @@ protected function getResponseProperty(ResponseInterface $response, $id) null; } + /** + * Parses a json message body and returns the result + * + * @param ResponseInterface $response + * + * @return \stdClass|array stdClass if a single response, array of stdClass + * for a collection + */ + protected function parseJsonBody(ResponseInterface $response) + { + return json_decode($response->getBody()); + } } diff --git a/src/Hypermedia/ParserInterface.php b/src/Hypermedia/ParserInterface.php new file mode 100644 index 0000000..58d2326 --- /dev/null +++ b/src/Hypermedia/ParserInterface.php @@ -0,0 +1,131 @@ +