Skip to content

Commit

Permalink
Merge pull request #79 from swisnl/feature/parser-factories
Browse files Browse the repository at this point in the history
Add factory methods for DocumentClient, ResponseParser and DocumentParser
  • Loading branch information
JaZo authored Sep 25, 2020
2 parents 1357cac + 5d03da0 commit aa0a821
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 57 deletions.
23 changes: 10 additions & 13 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,20 @@ php artisan vendor:publish --provider="Swis\JsonApi\Client\Providers\ServiceProv

## Getting started

You can simply require the [DocumentClient](#documentclient) as a dependency and use it in your class.
Alternatively, you can create a repository based on `\Swis\JsonApi\Client\Repository` and use that as a dependency:
You can simply create an instance of [DocumentClient](#documentclient) and use it in your class.
Alternatively, you can create a [repository](#repository).

``` php
use Swis\JsonApi\Client\Repository
use Swis\JsonApi\Client\DocumentClient;

class BlogRepository extends Repository
{
protected $endpoint = 'blogs';
}
$client = DocumentClient::create();
$document = $client->get('https://cms.contentacms.io/api/recipes');

$repository = app(BlogRepository::class);
$document = $repository->all();
if ($document->hasErrors()) {
// do something with errors
} else {
$blogs = $document->getData();
/** @var \Swis\JsonApi\Client\Collection&\Swis\JsonApi\Client\Item[] $collection */
$collection = $document->getData();

foreach ($collection as $item) {
// Do stuff with the items
}
```

Expand Down
14 changes: 14 additions & 0 deletions src/DocumentClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

namespace Swis\JsonApi\Client;

use Psr\Http\Client\ClientInterface as HttpClientInterface;
use Psr\Http\Message\ResponseInterface;
use Swis\JsonApi\Client\Interfaces\ClientInterface;
use Swis\JsonApi\Client\Interfaces\DocumentClientInterface;
use Swis\JsonApi\Client\Interfaces\DocumentInterface;
use Swis\JsonApi\Client\Interfaces\ItemDocumentInterface;
use Swis\JsonApi\Client\Interfaces\ResponseParserInterface;
use Swis\JsonApi\Client\Interfaces\TypeMapperInterface;
use Swis\JsonApi\Client\Parsers\ResponseParser;

class DocumentClient implements DocumentClientInterface
{
Expand All @@ -31,6 +34,17 @@ public function __construct(ClientInterface $client, ResponseParserInterface $pa
$this->parser = $parser;
}

/**
* @param \Swis\JsonApi\Client\Interfaces\TypeMapperInterface|null $typeMapper
* @param \Psr\Http\Client\ClientInterface|null $client
*
* @return static
*/
public static function create(TypeMapperInterface $typeMapper = null, HttpClientInterface $client = null): self
{
return new static(new Client($client), ResponseParser::create($typeMapper));
}

/**
* @return string
*/
Expand Down
25 changes: 25 additions & 0 deletions src/Parsers/DocumentParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
use Swis\JsonApi\Client\Interfaces\ItemInterface;
use Swis\JsonApi\Client\Interfaces\ManyRelationInterface;
use Swis\JsonApi\Client\Interfaces\OneRelationInterface;
use Swis\JsonApi\Client\Interfaces\TypeMapperInterface;
use Swis\JsonApi\Client\ItemDocument;
use Swis\JsonApi\Client\TypeMapper;

class DocumentParser implements DocumentParserInterface
{
Expand Down Expand Up @@ -69,6 +71,29 @@ public function __construct(
$this->metaParser = $metaParser;
}

/**
* @param \Swis\JsonApi\Client\Interfaces\TypeMapperInterface|null $typeMapper
*
* @return static
*/
public static function create(TypeMapperInterface $typeMapper = null): self
{
$metaParser = new MetaParser();
$linksParser = new LinksParser($metaParser);
$itemParser = new ItemParser($typeMapper ?? new TypeMapper(), $linksParser, $metaParser);

return new static(
$itemParser,
new CollectionParser($itemParser),
new ErrorCollectionParser(
new ErrorParser($linksParser, $metaParser)
),
$linksParser,
new JsonapiParser($metaParser),
$metaParser
);
}

/**
* @param string $json
*
Expand Down
11 changes: 11 additions & 0 deletions src/Parsers/ResponseParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Swis\JsonApi\Client\Interfaces\DocumentInterface;
use Swis\JsonApi\Client\Interfaces\DocumentParserInterface;
use Swis\JsonApi\Client\Interfaces\ResponseParserInterface;
use Swis\JsonApi\Client\Interfaces\TypeMapperInterface;
use Swis\JsonApi\Client\InvalidResponseDocument;

class ResponseParser implements ResponseParserInterface
Expand All @@ -24,6 +25,16 @@ public function __construct(DocumentParserInterface $parser)
$this->parser = $parser;
}

/**
* @param \Swis\JsonApi\Client\Interfaces\TypeMapperInterface|null $typeMapper
*
* @return static
*/
public static function create(TypeMapperInterface $typeMapper = null): self
{
return new static(DocumentParser::create($typeMapper));
}

/**
* @param \Psr\Http\Message\ResponseInterface $response
*
Expand Down
8 changes: 8 additions & 0 deletions tests/DocumentClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@

class DocumentClientTest extends AbstractTest
{
/**
* @test
*/
public function it_can_create_an_instance_using_a_factory_method()
{
$this->assertInstanceOf(DocumentClient::class, DocumentClient::create());
}

/**
* @test
*/
Expand Down
73 changes: 29 additions & 44 deletions tests/Parsers/DocumentParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,28 @@
use Swis\JsonApi\Client\Link;
use Swis\JsonApi\Client\Links;
use Swis\JsonApi\Client\Meta;
use Swis\JsonApi\Client\Parsers\CollectionParser;
use Swis\JsonApi\Client\Parsers\DocumentParser;
use Swis\JsonApi\Client\Parsers\ErrorCollectionParser;
use Swis\JsonApi\Client\Parsers\ErrorParser;
use Swis\JsonApi\Client\Parsers\ItemParser;
use Swis\JsonApi\Client\Parsers\JsonapiParser;
use Swis\JsonApi\Client\Parsers\LinksParser;
use Swis\JsonApi\Client\Parsers\MetaParser;
use Swis\JsonApi\Client\Tests\AbstractTest;
use Swis\JsonApi\Client\Tests\Mocks\Items\ChildItem;
use Swis\JsonApi\Client\Tests\Mocks\Items\MasterItem;
use Swis\JsonApi\Client\TypeMapper;

class DocumentParserTest extends AbstractTest
{
/**
* @test
*/
public function it_can_create_an_instance_using_a_factory_method()
{
$this->assertInstanceOf(DocumentParser::class, DocumentParser::create());
}

/**
* @test
*/
public function it_converts_jsondocument_to_document()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();
$document = $parser->parse(
json_encode(
[
Expand All @@ -51,7 +52,7 @@ public function it_converts_jsondocument_to_document()
*/
public function it_throws_when_json_is_not_valid()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$this->expectException(ValidationException::class);
$this->expectExceptionMessage('Unable to parse JSON data: Malformed UTF-8 characters, possibly incorrectly encoded');
Expand All @@ -67,7 +68,7 @@ public function it_throws_when_json_is_not_valid()
*/
public function it_throws_when_json_is_not_a_jsonapi_document(string $invalidJson)
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$this->expectException(ValidationException::class);
$this->expectExceptionMessage(sprintf('Document MUST be an object, "%s" given.', gettype(json_decode($invalidJson, false))));
Expand All @@ -92,7 +93,7 @@ public function provideInvalidJson(): array
*/
public function it_throws_when_data_errors_and_meta_are_missing()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$this->expectException(ValidationException::class);
$this->expectExceptionMessage('Document MUST contain at least one of the following properties: `data`, `errors`, `meta`.');
Expand All @@ -105,7 +106,7 @@ public function it_throws_when_data_errors_and_meta_are_missing()
*/
public function it_throws_when_both_data_and_errors_are_present()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$this->expectException(ValidationException::class);
$this->expectExceptionMessage('The properties `data` and `errors` MUST NOT coexist in Document.');
Expand All @@ -118,7 +119,7 @@ public function it_throws_when_both_data_and_errors_are_present()
*/
public function it_throws_when_included_is_present_but_data_is_not()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$this->expectException(ValidationException::class);
$this->expectExceptionMessage('If Document does not contain a `data` property, the `included` property MUST NOT be present either.');
Expand All @@ -134,7 +135,7 @@ public function it_throws_when_included_is_present_but_data_is_not()
*/
public function it_throws_when_data_is_not_an_array_object_or_null($invalidData)
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$this->expectException(ValidationException::class);
$this->expectExceptionMessage(sprintf('Document property "data" MUST be null, an array or an object, "%s" given.', gettype(json_decode($invalidData, false)->data)));
Expand All @@ -160,7 +161,7 @@ public function provideInvalidData(): array
*/
public function it_throws_when_included_is_not_an_array($invalidIncluded)
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$this->expectException(ValidationException::class);
$this->expectExceptionMessage(sprintf('Document property "included" MUST be an array, "%s" given.', gettype(json_decode($invalidIncluded, false)->included)));
Expand All @@ -185,7 +186,7 @@ public function provideInvalidIncluded(): array
*/
public function it_throws_when_it_finds_duplicate_resources()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$this->expectException(ValidationException::class);
$this->expectExceptionMessage('Resources MUST be unique based on their `type` and `id`, 1 duplicate(s) found.');
Expand Down Expand Up @@ -221,7 +222,7 @@ public function it_throws_when_it_finds_duplicate_resources()
*/
public function it_parses_a_resource_document()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();
$document = $parser->parse(
json_encode(
[
Expand All @@ -247,7 +248,7 @@ public function it_parses_a_resource_document()
*/
public function it_parses_a_resource_collection_document()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();
$document = $parser->parse(
json_encode(
[
Expand Down Expand Up @@ -276,7 +277,7 @@ public function it_parses_a_resource_collection_document()
*/
public function it_parses_a_document_without_data()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();
$document = $parser->parse(
json_encode(
[
Expand All @@ -295,7 +296,7 @@ public function it_parses_a_document_without_data()
*/
public function it_parses_included()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();
$document = $parser->parse(
json_encode(
[
Expand Down Expand Up @@ -328,7 +329,7 @@ public function it_links_singular_relations_to_items_from_included()
$typeMapper = new TypeMapper();
$typeMapper->setMapping('master', MasterItem::class);
$typeMapper->setMapping('child', ChildItem::class);
$parser = $this->getDocumentParser($typeMapper);
$parser = DocumentParser::create($typeMapper);

$document = $parser->parse(
json_encode(
Expand Down Expand Up @@ -374,7 +375,7 @@ public function it_does_not_link_empty_singular_relations()
$typeMapper = new TypeMapper();
$typeMapper->setMapping('master', MasterItem::class);
$typeMapper->setMapping('child', ChildItem::class);
$parser = $this->getDocumentParser($typeMapper);
$parser = DocumentParser::create($typeMapper);

$document = $parser->parse(
json_encode(
Expand Down Expand Up @@ -417,7 +418,7 @@ public function it_links_plural_relations_to_items_from_included()
$typeMapper = new TypeMapper();
$typeMapper->setMapping('master', MasterItem::class);
$typeMapper->setMapping('child', ChildItem::class);
$parser = $this->getDocumentParser($typeMapper);
$parser = DocumentParser::create($typeMapper);

$document = $parser->parse(
json_encode(
Expand Down Expand Up @@ -478,7 +479,7 @@ public function it_does_not_link_empty_plural_relations()
$typeMapper = new TypeMapper();
$typeMapper->setMapping('master', MasterItem::class);
$typeMapper->setMapping('child', ChildItem::class);
$parser = $this->getDocumentParser($typeMapper);
$parser = DocumentParser::create($typeMapper);

$document = $parser->parse(
json_encode(
Expand Down Expand Up @@ -527,7 +528,7 @@ public function it_does_not_link_empty_plural_relations()
*/
public function it_parses_links()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$document = $parser->parse(
json_encode(
Expand All @@ -550,7 +551,7 @@ public function it_parses_links()
*/
public function it_parses_errors()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$document = $parser->parse(
json_encode(
Expand All @@ -575,7 +576,7 @@ public function it_parses_errors()
*/
public function it_parses_meta()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$document = $parser->parse(
json_encode(
Expand All @@ -598,7 +599,7 @@ public function it_parses_meta()
*/
public function it_parses_jsonapi()
{
$parser = $this->getDocumentParser();
$parser = DocumentParser::create();

$document = $parser->parse(
json_encode(
Expand All @@ -615,20 +616,4 @@ public function it_parses_jsonapi()

static::assertEquals(new Jsonapi('1.0'), $document->getJsonapi());
}

private function getDocumentParser(TypeMapper $typeMapper = null): DocumentParser
{
$metaParser = new MetaParser();
$linksParser = new LinksParser($metaParser);
$itemParser = new ItemParser($typeMapper ?? new TypeMapper(), $linksParser, $metaParser);

return new DocumentParser(
$itemParser,
new CollectionParser($itemParser),
new ErrorCollectionParser(new ErrorParser($linksParser, $metaParser)),
$linksParser,
new JsonapiParser($metaParser),
$metaParser
);
}
}
Loading

0 comments on commit aa0a821

Please sign in to comment.