Skip to content

Commit bc1bbfc

Browse files
authored
V2 (#77)
1 parent 29265dc commit bc1bbfc

File tree

100 files changed

+2205
-1980
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+2205
-1980
lines changed

.php_cs.dist

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
$finder = PhpCsFixer\Finder::create()
33
->files()
44
->name('*.php')
5+
->in(__DIR__ . '/examples')
56
->in(__DIR__ . '/src')
67
->in(__DIR__ . '/test');
78
return PhpCsFixer\Config::create()
@@ -42,6 +43,7 @@ return PhpCsFixer\Config::create()
4243
'psr0' => true,
4344
'short_scalar_cast' => true,
4445
'single_blank_line_before_namespace' => true,
46+
'single_quote' => true,
4547
'standardize_not_equals' => true,
4648
'strict_comparison' => true,
4749
'ternary_operator_spaces' => true,

.travis.yml

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
language: php
22
php:
3-
- '7.1'
43
- '7.2'
54

65
before_script:
76
- composer install
8-
- mkdir -p build/logs
7+
- mkdir build/logs -p
98

109
script:
1110
- vendor/bin/php-cs-fixer fix -v --dry-run

CHANGELOG.md

+2-15
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
66

77
## [Unreleased]
88

9-
## [1.0.2] - 2018-02-21
10-
### Added
11-
- This changelog
12-
13-
### Removed
14-
- Removed doc2test dependency
15-
16-
## [1.0.1] - 2017-10-27
17-
### Changed
18-
- Exceptions precision. Using DomainException instead of LogicException
19-
20-
## [1.0.0] - 2017-10-24
9+
## [2.0.0-rc.0] - 2018-02-26
2110
Initial stable release
2211

23-
[Unreleased]: https://github.com/json-api-php/json-api/compare/1.0.2...HEAD
24-
[1.0.2]: https://github.com/json-api-php/json-api/compare/1.0.1...1.0.2
25-
[1.0.1]: https://github.com/json-api-php/json-api/compare/1.0.0...1.0.1
12+
[Unreleased]: https://github.com/json-api-php/json-api/compare/2.0.0-rc.0...HEAD

CONTRIBUTING.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@ Thank you for you interest! Here are some key guidelines.
55
We want to follow the latest actual [PSR](http://www.php-fig.org/psr/) standards.
66

77
## Tests are the documentation
8-
The use cases and library's API must be expressed in a form of tests. We use PHPUnit, but it does not mean all tests
9-
are expected to be unit tests. No logic must be written without a supporting test.
8+
The use cases and library's API must be expressed as tests. No logic must be written without a supporting test.

README.md

+53-28
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
# Implementation of [JSON API](http://jsonapi.org) in PHP 7
2-
This library is an attempt to express business rules of JSON API specification in a set of PHP 7 classes.
1+
# [JSON API](http://jsonapi.org) spec implemented in PHP 7. Immutable
32

4-
A simple example to illustrate the general idea. This JSON representation from
5-
[the documentation](http://jsonapi.org/format/#document-resource-objects)
6-
<!-- name=my_json -->
3+
**This is v2 of the implementation. For v1 click [here](/json-api-php/json-api/tree/v2).**
4+
5+
The goal of this library is to ensure strict validity of JSON API documents being produced.
6+
7+
JSON:
78
```json
89
{
910
"data": {
@@ -27,32 +28,56 @@ A simple example to illustrate the general idea. This JSON representation from
2728
}
2829
}
2930
```
30-
can be built with the following php code:
31-
<!-- assert=output expect=my_json -->
31+
PHP:
3232
```php
3333
<?php
34-
use \JsonApiPhp\JsonApi\Document;
35-
use \JsonApiPhp\JsonApi\Document\Resource\{
36-
Linkage\SingleLinkage, Relationship, ResourceIdentifier, ResourceObject
37-
};
34+
use JsonApiPhp\JsonApi\Attribute;
35+
use JsonApiPhp\JsonApi\DataDocument;
36+
use JsonApiPhp\JsonApi\Link\RelatedLink;
37+
use JsonApiPhp\JsonApi\Link\SelfLink;
38+
use JsonApiPhp\JsonApi\Link\Url;
39+
use JsonApiPhp\JsonApi\Relationship;
40+
use JsonApiPhp\JsonApi\ResourceIdentifier;
41+
use JsonApiPhp\JsonApi\ResourceObject;
42+
use JsonApiPhp\JsonApi\SingleLinkage;
3843

39-
$author = Relationship::fromLinkage(new SingleLinkage(new ResourceIdentifier('people', '9')));
40-
$author->setLink('self', '/articles/1/relationships/author');
41-
$author->setLink('related', '/articles/1/author');
42-
$articles = new ResourceObject('articles', '1');
43-
$articles->setRelationship('author', $author);
44-
$articles->setAttribute('title', 'Rails is Omakase');
45-
echo json_encode(Document::fromResource($articles), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
44+
echo json_encode(
45+
new DataDocument(
46+
new ResourceObject(
47+
'articles',
48+
'1',
49+
new Attribute('title', 'Rails is Omakase'),
50+
new Relationship(
51+
'author',
52+
new SingleLinkage(new ResourceIdentifier('author', '9')),
53+
new SelfLink(new Url('/articles/1/relationships/author')),
54+
new RelatedLink(new Url('/articles/1/author'))
55+
)
56+
)
57+
),
58+
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
59+
);
4660
```
61+
## Installation
62+
`composer require json-api-php/json-api`
4763

48-
Please refer to [the tests](./test) for the full API documentation:
49-
* [Documents](./test/Document/DocumentTest.php). Creating documents with primary data, errors, and meta.
50-
Adding links and API version to a document.
51-
* [Compound Documents](./test/Document/CompoundDocumentTest.php). Resource linkage.
52-
* [Errors](./test/Document/ErrorTest.php)
53-
* [Resources](./test/Document/Resource/ResourceTest.php)
54-
* [Relationships](./test/Document/Resource/Relationship/RelationshipTest.php)
55-
* [Linkage](./test/Document/Resource/Relationship/LinkageTest.php)
64+
## Documentation
5665

57-
## Installation
58-
With [composer](https://getcomposer.org/): `json-api-php/json-api`.
66+
First, take a look at the examples. All of them are runnable.
67+
- [Simple Document](./examples/simple_doc.php) (the same as above)
68+
- [Extensive Compound Document](./examples/compound_doc.php)
69+
70+
The library API and use-cases are expressed in comprehensive suite of tests.
71+
- Data Documents (containing primary data)
72+
- [with a single Resource Object](./test/DataDocument/SingleResourceObjectTest.php)
73+
- [with a single Resource Identifier](./test/DataDocument/SingleResourceIdentifierTest.php)
74+
- [with null data](./test/DataDocument/NullDataTest.php)
75+
- [with multiple Resource Objects](./test/DataDocument/ManyResourceObjectsTest.php)
76+
- [with multiple Resource Identifiers](./test/DataDocument/ManyResourceIdentifiersTest.php)
77+
- [Compound Documents](./test/CompoundDocumentTest.php)
78+
- [Error Documents](./test/ErrorDocumentTest.php)
79+
- [Meta Documents (containing neither data nor errors)](./test/MetaDocumentTest.php)
80+
- [Pagination links](./test/PaginationLinksTest.php)
81+
- [Link Objects](./test/LinkObjectTest.php)
82+
- [JSON API Object](./test/JsonApiTest.php)
83+
- [Meta Objects](./test/MetaTest.php)

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
}
1212
],
1313
"require": {
14-
"php": ">=7.1"
14+
"php": ">=7.2"
1515
},
1616
"require-dev": {
1717
"phpunit/phpunit": "^6.0",

examples/compound_doc.php

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php declare(strict_types=1);
2+
use JsonApiPhp\JsonApi\Attribute;
3+
use JsonApiPhp\JsonApi\CompoundDocument;
4+
use JsonApiPhp\JsonApi\Included;
5+
use JsonApiPhp\JsonApi\Link\LastLink;
6+
use JsonApiPhp\JsonApi\Link\NextLink;
7+
use JsonApiPhp\JsonApi\Link\RelatedLink;
8+
use JsonApiPhp\JsonApi\Link\SelfLink;
9+
use JsonApiPhp\JsonApi\Link\Url;
10+
use JsonApiPhp\JsonApi\MultiLinkage;
11+
use JsonApiPhp\JsonApi\Relationship;
12+
use JsonApiPhp\JsonApi\ResourceIdentifier;
13+
use JsonApiPhp\JsonApi\ResourceObject;
14+
use JsonApiPhp\JsonApi\ResourceObjectSet;
15+
use JsonApiPhp\JsonApi\SingleLinkage;
16+
17+
require_once __DIR__.'/../vendor/autoload.php';
18+
19+
$dan = new ResourceObject(
20+
'people',
21+
'9',
22+
new Attribute('first-name', 'Dan'),
23+
new Attribute('last-name', 'Gebhardt'),
24+
new Attribute('twitter', 'dgeb'),
25+
new SelfLink(new Url('http://example.com/people/9'))
26+
);
27+
28+
$comment05 = new ResourceObject(
29+
'comments',
30+
'5',
31+
new Attribute('body', 'First!'),
32+
new SelfLink(new Url('http://example.com/comments/5')),
33+
new Relationship('author', new SingleLinkage(new ResourceIdentifier('people', '2')))
34+
35+
);
36+
$comment12 = new ResourceObject(
37+
'comments',
38+
'12',
39+
new Attribute('body', 'I like XML better'),
40+
new SelfLink(new Url('http://example.com/comments/12')),
41+
new Relationship('author', new SingleLinkage($dan->identifier()))
42+
);
43+
44+
$document = new CompoundDocument(
45+
new ResourceObjectSet(
46+
new ResourceObject(
47+
'articles',
48+
'1',
49+
new Attribute('title', 'JSON API paints my bikeshed!'),
50+
new SelfLink(new Url('http://example.com/articles/1')),
51+
new Relationship(
52+
'author',
53+
new SingleLinkage($dan->identifier()),
54+
new SelfLink(new Url('http://example.com/articles/1/relationships/author')),
55+
new RelatedLink(new Url('http://example.com/articles/1/author'))
56+
),
57+
new Relationship(
58+
'comments',
59+
new MultiLinkage(
60+
$comment05->identifier(),
61+
$comment12->identifier()
62+
),
63+
new SelfLink(new Url('http://example.com/articles/1/relationships/comments')),
64+
new RelatedLink(new Url('http://example.com/articles/1/comments'))
65+
)
66+
)
67+
),
68+
new Included($dan, $comment05, $comment12),
69+
new SelfLink(new Url('http://example.com/articles')),
70+
new NextLink(new Url('http://example.com/articles?page[offset]=2')),
71+
new LastLink(new Url('http://example.com/articles?page[offset]=10'))
72+
);
73+
74+
echo json_encode($document, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);

examples/simple_doc.php

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php declare(strict_types=1);
2+
require_once __DIR__.'/../vendor/autoload.php';
3+
4+
use JsonApiPhp\JsonApi\Attribute;
5+
use JsonApiPhp\JsonApi\DataDocument;
6+
use JsonApiPhp\JsonApi\Link\RelatedLink;
7+
use JsonApiPhp\JsonApi\Link\SelfLink;
8+
use JsonApiPhp\JsonApi\Link\Url;
9+
use JsonApiPhp\JsonApi\Relationship;
10+
use JsonApiPhp\JsonApi\ResourceIdentifier;
11+
use JsonApiPhp\JsonApi\ResourceObject;
12+
use JsonApiPhp\JsonApi\SingleLinkage;
13+
14+
echo json_encode(
15+
new DataDocument(
16+
new ResourceObject(
17+
'articles',
18+
'1',
19+
new Attribute('title', 'Rails is Omakase'),
20+
new Relationship(
21+
'author',
22+
new SingleLinkage(new ResourceIdentifier('author', '9')),
23+
new SelfLink(new Url('/articles/1/relationships/author')),
24+
new RelatedLink(new Url('/articles/1/author'))
25+
)
26+
)
27+
),
28+
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
29+
);

src/Attachable.php

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace JsonApiPhp\JsonApi;
4+
5+
/**
6+
* @internal
7+
*/
8+
interface Attachable
9+
{
10+
public function attachTo(object $o);
11+
}

src/AttachableValue.php

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace JsonApiPhp\JsonApi;
4+
5+
/**
6+
* @internal
7+
*/
8+
class AttachableValue extends JsonSerializableValue implements Attachable
9+
{
10+
private $key;
11+
12+
public function __construct(string $key, $value)
13+
{
14+
parent::__construct($value);
15+
$this->key = $key;
16+
}
17+
18+
public function attachTo(object $o)
19+
{
20+
$o->{$this->key} = $this;
21+
}
22+
}

src/Attribute.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace JsonApiPhp\JsonApi;
4+
5+
use JsonApiPhp\JsonApi\PrimaryData\ResourceField;
6+
7+
final class Attribute extends ResourceField
8+
{
9+
public function attachTo(object $o)
10+
{
11+
parent::attachTo(child($o, 'attributes'));
12+
}
13+
}

src/CompoundDocument.php

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace JsonApiPhp\JsonApi;
4+
5+
use JsonApiPhp\JsonApi\PrimaryData\PrimaryData;
6+
7+
final class CompoundDocument extends JsonSerializableValue
8+
{
9+
public function __construct(PrimaryData $data, Included $included, DataDocumentMember ...$members)
10+
{
11+
foreach ($included as $resource) {
12+
if ($data->identifies($resource)) {
13+
continue;
14+
}
15+
foreach ($included as $anotherResource) {
16+
if ($anotherResource->identifies($resource)) {
17+
continue 2;
18+
}
19+
}
20+
throw new \DomainException('Full linkage required for '.json_encode($resource->identifier()));
21+
}
22+
parent::__construct(combine($data, $included, ...$members));
23+
}
24+
}

src/DataDocument.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace JsonApiPhp\JsonApi;
4+
5+
use JsonApiPhp\JsonApi\PrimaryData\PrimaryData;
6+
7+
final class DataDocument extends JsonSerializableValue
8+
{
9+
public function __construct(PrimaryData $data, DataDocumentMember ...$members)
10+
{
11+
parent::__construct(combine($data, ...$members));
12+
}
13+
}

src/DataDocumentMember.php

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace JsonApiPhp\JsonApi;
4+
5+
/**
6+
* @internal
7+
*/
8+
interface DataDocumentMember extends DocumentMember
9+
{
10+
}

0 commit comments

Comments
 (0)