Skip to content

Commit

Permalink
Allow the hypermedia parser to be set manually, this provides support…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
Jmeyering committed Oct 21, 2016
1 parent 87632c9 commit 7f15c0b
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 17 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
13 changes: 13 additions & 0 deletions spec/ExplorerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions spec/Hypermedia/ParserSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down
41 changes: 38 additions & 3 deletions src/Explorer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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());
}

/**
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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.
*
Expand Down
30 changes: 16 additions & 14 deletions src/Hypermedia/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace HalExplorer\Hypermedia;

use HalExplorer\Hypermedia\ParserInterface;
use Psr\Http\Message\ResponseInterface;

/**
Expand All @@ -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?
*
Expand Down Expand Up @@ -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());
}
}
131 changes: 131 additions & 0 deletions src/Hypermedia/ParserInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php

namespace HalExplorer\Hypermedia;

use Psr\Http\Message\ResponseInterface;

/**
* The ParserInterface provides the necessary methods for fetching linked,
* embedded, or curie information from a {@see ResponseInterface} object.
*
* @author Jared Meyering
*
*/
interface ParserInterface
{
/**
* Does the ResponseInterface have any links?
*
* @param ResponseInterface $response
*
* @return boolean
*/
public function hasLinks(ResponseInterface $response);

/**
* Return the collection of links on the response.
*
* @param ResponseInterface $response
*
* @return \stdClass|null
*/
public function getLinks(ResponseInterface $response);

/**
* Informs the user if a particular link exists on a response
*
* @param ResponseInterface $response The response containing the links.
* @param string $id The identifier of the link to find
*
* @return boolean
*/
public function hasLink(ResponseInterface $response, $id);

/**
* Return a single link that is set on the response null if not present.
* handles curie annotated link names as well as ordinary link names.
*
* @param ResponseInterface $response The response containing the links.
* @param string $id The identifier of the link to fetch
*
* @return \stdClass|null
*/
public function getLink(ResponseInterface $response, $id);

/**
* Informs the user if the response has embedded resources
*
* @param ResponseInterface $response
*
* @return boolean
*/
public function hasEmbeds(ResponseInterface $response);

/**
* Return all the embeds if they exist
*
* @param ResponseInterface $response The response containing the Embeds.
*
* @return \stdClass|null
*/
public function getEmbeds(ResponseInterface $response);

/**
* Informs the user if a particular embed exists on a response
*
* @param ResponseInterface $response The response containing the embeds.
* @param string $id The identifier of the embed to find
*
* @return boolean
*/
public function hasEmbed(ResponseInterface $response, $id);

/**
* Return a single embed that is set on the response null if not present.
*
* @param ResponseInterface $response The response containing the embeds.
* @param string $id The identifier of the embed to fetch
*
* @return \stdClass|null
*/
public function getEmbed(ResponseInterface $response, $id);


/**
* Does the ResponseInterface have any curies?
*
* @param ResponseInterface $response
*
* @return boolean
*/
public function hasCuries(ResponseInterface $response);

/**
* Retreive the curies for this request
*
* @param ResponseInterface $response
*
* @return array Because curies are represented as an array of objects.
*/
public function getCuries(ResponseInterface $response);

/**
* Informs the user if a particular curie exists on a response
*
* @param ResponseInterface $response The response containing the curies.
* @param string $name The name of the curie to find
*
* @return boolean
*/
public function hasCurie(ResponseInterface $response, $name);

/**
* Retreive a single curie by name
*
* @param ResponseInterface $response The response with the curies
* @param string $name The name value of the curie to fetch
*
* @return \stdClass|null
*/
public function getCurie(ResponseInterface $response, $name);
}

0 comments on commit 7f15c0b

Please sign in to comment.