Skip to content

Commit c2c3913

Browse files
committedMay 21, 2021
Initial commit
0 parents  commit c2c3913

32 files changed

+1899
-0
lines changed
 

‎.gitattributes

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Path-based git attributes
2+
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
3+
4+
# Ignore all test and documentation with "export-ignore".
5+
/.gitattributes export-ignore
6+
/.gitignore export-ignore
7+
/phpunit.xml.dist export-ignore
8+
/tests export-ignore
9+
/phpcs.xml export-ignore
10+
/phpstan.neon export-ignore
11+
/.github export-ignore

‎.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/vendor
2+
/build
3+
/.idea
4+
/composer.lock
5+
/auth.json
6+
/.phpunit.result.cache

‎CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Changelog
2+
3+
## v1.0.0 - 2021-XX-XX
4+
5+
- initial release

‎LICENSE

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
MIT License
2+
3+
Copyright (c) 2020-2021 dogado GmbH
4+
Copyright (c) 2020 Chris Döhring
5+
Copyright (c) 2017 eos new media GmbH & Co. KG
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in all
15+
copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
SOFTWARE.

‎README.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Abstract client side php implementation of the JSON:API protocol.
2+
3+
## Installation
4+
5+
```sh
6+
composer require dogado/json-api-client
7+
```
8+
9+
It's recommended to install `guzzlehttp/guzzle` version `^7.0` as http-client and `http-interop/http-factory-guzzle` for [PSR-17](https://www.php-fig.org/psr/psr-17/) compatible factories.
10+
11+
```sh
12+
composer require guzzlehttp/guzzle http-interop/http-factory-guzzle
13+
```
14+
15+
You can also use any other HTTP client which implements [PSR-18](https://www.php-fig.org/psr/psr-18/).
16+
17+
## Usage
18+
19+
First you should read the docs of [dogado/json-api-common](https://github.com/dogado-group/json-api-common/tree/main/docs) where all basic structures will be explained.
20+
21+
Your API client is an instance of `Dogado\JsonApi\Client\JsonApiClient`, which requires a [PSR-18](https://www.php-fig.org/psr/psr-18/) HTTP client (`Psr\Http\Client\ClientInterface`) to execute requests.
22+
23+
```php
24+
use Dogado\JsonApi\Client\JsonApiClient;
25+
use Dogado\JsonApi\Client\Factory\RequestFactory;
26+
use Dogado\JsonApi\Client\Validator\ResponseValidator;
27+
28+
$client = new JsonApiClient(
29+
$httpClient, // instance of Psr\Http\Client\ClientInterface
30+
$psrRequestFactory, // instance of Psr\Http\Message\RequestFactoryInterface
31+
$streamFactory, // instance of Psr\Http\Message\StreamFactoryInterface
32+
$serializer, // instance of Dogado\JsonApi\Serializer\DocumentSerializerInterface
33+
$responseFactory, // instance of Dogado\JsonApi\Client\Response\ResponseFactoryInterface
34+
);
35+
36+
$baseUrl = new Uri('http://example.com/api');
37+
$requestFactory = new RequestFactory($baseUrl);
38+
39+
$request = $requestFactory->createGetRequest(new Uri('/myResource/1')); // will fetch the resource at http://example.com/api/myResource/1
40+
$response = $client->execute($request);
41+
42+
// OPTIONAL: Validate the response to match your needs. See the ResponseValidator class for all assertion methods
43+
(new ResponseValidator())->assertResourcesMatchTypeAndContainIds($response, 'myResource');
44+
45+
$document = $response->document();
46+
$myResource = $document->data()->first(); // the resource fetched by this request
47+
$myIncludedResources = $document->included()->all(); // the included resources fetched with the include parameter
48+
```
49+
50+
### Action Pattern
51+
52+
In most cases it's easier to capsule request scenarios into single classes since every request has its own requirements.
53+
In this package this is called `Action`. To make things easier, we already defined an `AbstractAction` class under the
54+
`Dogado\JsonApi\Client\Action` namespace. An example how to create such an action can be found
55+
[in the tests](./tests/Action/DummyAction.php).
56+
57+
When fetching resources in actions it's also very common to filter, paginate and sort. To define these options within Actions,
58+
there are multiple Traits you can use, defined in the same namespace as the `AbstractAction` class.
59+
60+
## Credits
61+
62+
- [Chris Döhring](https://github.com/chris-doehring)
63+
- [Philipp Marien](https://github.com/pmarien)
64+
- [eosnewmedia team](https://github.com/eosnewmedia)
65+
66+
This package contains code taken from [enm/json-api-client](https://github.com/eosnewmedia/JSON-API-Client).
67+
68+
## License
69+
70+
The MIT License (MIT). Please see [License File](LICENSE) for more information.

‎composer.json

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"name": "dogado/json-api-client",
3+
"description": "Abstract client side php implementation of the JSON:API protocol.",
4+
"keywords": [
5+
"dogado",
6+
"json api"
7+
],
8+
"type": "library",
9+
"license": "MIT",
10+
"homepage": "https://github.com/dogado-group/json-api-client",
11+
"require": {
12+
"php": "^7.4 || ^8.0",
13+
"ext-json": "*",
14+
"dogado/json-api-common": "0.*",
15+
"illuminate/support": "^7.0 || ^8.0",
16+
"psr/http-factory": "^1.0",
17+
"psr/http-client": "^1.0"
18+
},
19+
"require-dev": {
20+
"phpunit/phpunit": "^9.0",
21+
"fakerphp/faker": "^1.10",
22+
"phpstan/phpstan": "^0.12.49",
23+
"http-interop/http-factory-guzzle": "^1.0",
24+
"squizlabs/php_codesniffer": "^3.5"
25+
},
26+
"autoload": {
27+
"psr-4": {
28+
"Dogado\\JsonApi\\Client\\": "src"
29+
}
30+
},
31+
"autoload-dev": {
32+
"psr-4": {
33+
"Dogado\\JsonApi\\Client\\Tests\\": "tests"
34+
}
35+
},
36+
"scripts": {
37+
"test": [
38+
"@unit",
39+
"@stan",
40+
"@cs"
41+
],
42+
"unit": "phpunit",
43+
"coverage": "phpunit --log-junit build/logs/unitreport.xml --coverage-html build/coverage",
44+
"stan": "phpstan analyse",
45+
"cs": "phpcs --standard=phpcs.xml"
46+
},
47+
"minimum-stability": "dev",
48+
"prefer-stable": true,
49+
"suggest": {
50+
"guzzlehttp/guzzle": "As a PSR-18 compatible HTTP client (version >=7.0).",
51+
"http-interop/http-factory-guzzle": "For PSR-17 compatible factories."
52+
}
53+
}

‎phpcs.xml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0"?>
2+
<ruleset name="PHP_CodeSniffer">
3+
<description>Custom ruleset Based on PSR12</description>
4+
<file>src</file>
5+
<!-- Rule to be referenced (`PSR12`) -->
6+
<rule ref="PSR12" />
7+
<!-- All files must have "\n" line endings -->
8+
<rule ref="Generic.Files.LineEndings" />
9+
<!-- Specify extensions (.php) -->
10+
<arg name="extensions" value="php" />
11+
<!--Color the result output -->
12+
<arg name="colors" /> <!--Display progress (-p)-->
13+
<!--Display violation rules in error information (-s)-->
14+
<arg value="ps" />
15+
</ruleset>

‎phpstan.neon

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
level: 8
3+
paths:
4+
- src
5+
checkMissingIterableValueType: false

‎phpunit.xml.dist

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
4+
bootstrap="vendor/autoload.php"
5+
executionOrder="depends,defects"
6+
beStrictAboutOutputDuringTests="true"
7+
beStrictAboutTodoAnnotatedTests="true"
8+
failOnRisky="true"
9+
failOnWarning="true"
10+
verbose="true">
11+
<testsuites>
12+
<testsuite name="default">
13+
<directory suffix="Test.php">tests</directory>
14+
</testsuite>
15+
</testsuites>
16+
17+
<coverage processUncoveredFiles="true">
18+
<include>
19+
<directory suffix=".php">src</directory>
20+
</include>
21+
</coverage>
22+
</phpunit>

‎src/Action/AbstractAction.php

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Dogado\JsonApi\Client\Action;
6+
7+
use Dogado\JsonApi\Client\Factory\RequestFactoryInterface;
8+
use Dogado\JsonApi\Client\JsonApiClient;
9+
use Dogado\JsonApi\Client\Validator\ResponseValidator;
10+
use Dogado\JsonApi\Model\Request\RequestInterface;
11+
use Dogado\JsonApi\Model\Response\ResponseInterface;
12+
use Psr\Http\Message\UriFactoryInterface;
13+
use Throwable;
14+
15+
abstract class AbstractAction implements ActionInterface
16+
{
17+
protected JsonApiClient $client;
18+
protected RequestFactoryInterface $requestFactory;
19+
protected UriFactoryInterface $uriFactory;
20+
protected ResponseValidator $responseValidator;
21+
22+
/** @var callable[] */
23+
protected array $preExecutionCallStack = [];
24+
25+
public function __construct(
26+
JsonApiClient $client,
27+
RequestFactoryInterface $requestFactory,
28+
UriFactoryInterface $uriFactory,
29+
ResponseValidator $responseValidator
30+
) {
31+
$this->client = $client;
32+
$this->requestFactory = $requestFactory;
33+
$this->uriFactory = $uriFactory;
34+
$this->responseValidator = $responseValidator;
35+
}
36+
37+
abstract public function execute(): ResponseInterface;
38+
39+
protected function beforeSend(string $id, callable $function): self
40+
{
41+
if (!array_key_exists($id, $this->preExecutionCallStack)) {
42+
$this->preExecutionCallStack[$id] = $function;
43+
}
44+
45+
return $this;
46+
}
47+
48+
/**
49+
* @throws Throwable
50+
*/
51+
protected function send(RequestInterface $request): ResponseInterface
52+
{
53+
foreach ($this->preExecutionCallStack as $method) {
54+
$method($request);
55+
}
56+
57+
return $this->client->execute($request);
58+
}
59+
}

‎src/Action/ActionInterface.php

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Dogado\JsonApi\Client\Action;
6+
7+
use Dogado\JsonApi\Model\Response\ResponseInterface;
8+
9+
interface ActionInterface
10+
{
11+
public function execute(): ResponseInterface;
12+
}

‎src/Action/FiltersResource.php

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Dogado\JsonApi\Client\Action;
6+
7+
use Dogado\JsonApi\Model\Request\RequestInterface;
8+
9+
trait FiltersResource
10+
{
11+
protected array $filter = [];
12+
13+
/**
14+
* @param string|array $filterOrKey
15+
* @param mixed $value
16+
* @return $this
17+
*/
18+
public function filter($filterOrKey, $value = null): self
19+
{
20+
$this->beforeSend('filter', function (RequestInterface $request) {
21+
$this->applyFilter($request);
22+
});
23+
if (is_array($filterOrKey)) {
24+
$this->filter = array_merge($this->filter, $filterOrKey);
25+
return $this;
26+
}
27+
28+
$this->filter[$filterOrKey] = $value;
29+
return $this;
30+
}
31+
32+
protected function applyFilter(RequestInterface $request): self
33+
{
34+
foreach ($this->filter as $key => $value) {
35+
$request->filter()->set($key, $value);
36+
}
37+
38+
return $this;
39+
}
40+
}

‎src/Action/PaginatesResource.php

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Dogado\JsonApi\Client\Action;
6+
7+
use Dogado\JsonApi\Model\Request\RequestInterface;
8+
9+
trait PaginatesResource
10+
{
11+
protected array $pagination = [];
12+
13+
/**
14+
* @param string|array $paginationOrKey
15+
* @param mixed $value
16+
*/
17+
public function pagination($paginationOrKey, $value = null): self
18+
{
19+
$this->beforeSend('paginate', function (RequestInterface $request) {
20+
$this->applyPagination($request);
21+
});
22+
23+
if (is_array($paginationOrKey)) {
24+
$this->pagination = array_merge($this->pagination, $paginationOrKey);
25+
return $this;
26+
}
27+
28+
$this->pagination[$paginationOrKey] = $value;
29+
return $this;
30+
}
31+
32+
protected function applyPagination(RequestInterface $request): self
33+
{
34+
foreach ($this->pagination as $key => $value) {
35+
$request->pagination()->set($key, $value);
36+
}
37+
38+
return $this;
39+
}
40+
}

0 commit comments

Comments
 (0)
Please sign in to comment.