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 @@ +