Skip to content

Commit 13b2676

Browse files
committed
Version 1.0
1 parent c43c2d0 commit 13b2676

23 files changed

+621
-285
lines changed

src/Document.php

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515
use JsonApiPhp\JsonApi\Document\LinksTrait;
1616
use JsonApiPhp\JsonApi\Document\Meta;
1717
use JsonApiPhp\JsonApi\Document\MetaTrait;
18-
use JsonApiPhp\JsonApi\Document\Resource\ResourceInterface;
18+
use JsonApiPhp\JsonApi\Document\PrimaryData\MultiIdentifierData;
19+
use JsonApiPhp\JsonApi\Document\PrimaryData\MultiResourceData;
20+
use JsonApiPhp\JsonApi\Document\PrimaryData\NullData;
21+
use JsonApiPhp\JsonApi\Document\PrimaryData\PrimaryDataInterface;
22+
use JsonApiPhp\JsonApi\Document\PrimaryData\SingleIdentifierData;
23+
use JsonApiPhp\JsonApi\Document\PrimaryData\SingleResourceData;
24+
use JsonApiPhp\JsonApi\Document\Resource\ResourceIdentifier;
1925
use JsonApiPhp\JsonApi\Document\Resource\ResourceObject;
2026

2127
class Document implements \JsonSerializable
@@ -26,11 +32,23 @@ class Document implements \JsonSerializable
2632
use LinksTrait;
2733
use MetaTrait;
2834

35+
/**
36+
* @var PrimaryDataInterface
37+
*/
2938
private $data;
39+
40+
/**
41+
* @var Error[]
42+
*/
3043
private $errors;
44+
3145
private $api;
46+
47+
/**
48+
* @var ResourceObject[]
49+
*/
3250
private $included;
33-
private $is_sparse = false;
51+
private $sparse = false;
3452

3553
private function __construct()
3654
{
@@ -50,17 +68,38 @@ public static function fromErrors(Error ...$errors): self
5068
return $doc;
5169
}
5270

53-
public static function fromResource(ResourceInterface $data): self
71+
public static function fromResource(ResourceObject $resource): self
72+
{
73+
$doc = new self;
74+
$doc->data = new SingleResourceData($resource);
75+
return $doc;
76+
}
77+
78+
public static function fromResources(ResourceObject ...$resources): self
79+
{
80+
$doc = new self;
81+
$doc->data = new MultiResourceData(...$resources);
82+
return $doc;
83+
}
84+
85+
public static function fromIdentifier(ResourceIdentifier $identifier)
86+
{
87+
$doc = new self;
88+
$doc->data = new SingleIdentifierData($identifier);
89+
return $doc;
90+
}
91+
92+
public static function fromIdentifiers(ResourceIdentifier... $identifiers)
5493
{
5594
$doc = new self;
56-
$doc->data = $data;
95+
$doc->data = new MultiIdentifierData(...$identifiers);
5796
return $doc;
5897
}
5998

60-
public static function fromResources(ResourceInterface ...$data): self
99+
public static function nullDocument()
61100
{
62101
$doc = new self;
63-
$doc->data = $data;
102+
$doc->data = new NullData();
64103
return $doc;
65104
}
66105

@@ -69,19 +108,27 @@ public function setApiVersion(string $version = self::DEFAULT_API_VERSION)
69108
$this->api['version'] = $version;
70109
}
71110

72-
public function setApiMeta(array $meta)
111+
public function setApiMeta(Meta $meta)
73112
{
74113
$this->api['meta'] = $meta;
75114
}
76115

77-
public function setIncluded(ResourceObject ...$included)
116+
public function setIncluded(ResourceObject ...$resources)
78117
{
79-
$this->included = $included;
118+
if (null === $this->data) {
119+
throw new \LogicException('Document with no data cannot contain included resources');
120+
}
121+
foreach ($resources as $resource) {
122+
if (isset($this->included[(string) $resource->toIdentifier()])) {
123+
throw new \LogicException("Resource {$resource->toIdentifier()} is already included");
124+
}
125+
$this->included[(string) $resource->toIdentifier()] = $resource;
126+
}
80127
}
81128

82129
public function markSparse()
83130
{
84-
$this->is_sparse = true;
131+
$this->sparse = true;
85132
}
86133

87134
public function jsonSerialize()
@@ -94,7 +141,7 @@ public function jsonSerialize()
94141
'meta' => $this->meta,
95142
'jsonapi' => $this->api,
96143
'links' => $this->links,
97-
'included' => $this->included,
144+
'included' => $this->included ? array_values($this->included) : null,
98145
],
99146
function ($v) {
100147
return null !== $v;
@@ -104,47 +151,19 @@ function ($v) {
104151

105152
private function enforceFullLinkage()
106153
{
107-
if ($this->is_sparse || empty($this->included)) {
154+
if ($this->sparse || empty($this->included)) {
108155
return;
109156
}
110-
foreach ($this->included as $included_resource) {
111-
if ($this->hasLinkTo($included_resource) || $this->anotherIncludedResourceIdentifies($included_resource)) {
157+
foreach ($this->included as $included) {
158+
if ($this->data->hasLinkTo($included)) {
112159
continue;
113160
}
114-
throw new \LogicException("Full linkage is required for $included_resource");
115-
}
116-
}
117-
118-
private function anotherIncludedResourceIdentifies(ResourceObject $resource): bool
119-
{
120-
/** @var ResourceObject $included_resource */
121-
foreach ($this->included as $included_resource) {
122-
if ($included_resource !== $resource && $included_resource->identifies($resource)) {
123-
return true;
124-
}
125-
}
126-
return false;
127-
}
128-
129-
private function hasLinkTo(ResourceObject $resource): bool
130-
{
131-
/** @var ResourceInterface $my_resource */
132-
foreach ($this->toResources() as $my_resource) {
133-
if ($my_resource->identifies($resource)) {
134-
return true;
135-
}
136-
}
137-
return false;
138-
}
139-
140-
private function toResources(): \Iterator
141-
{
142-
if ($this->data instanceof ResourceInterface) {
143-
yield $this->data;
144-
} elseif (is_array($this->data)) {
145-
foreach ($this->data as $datum) {
146-
yield $datum;
161+
foreach ($this->included as $anotherIncluded) {
162+
if ($anotherIncluded->identifies($included)) {
163+
continue 2;
164+
}
147165
}
166+
throw new \LogicException("Full linkage is required for {$included->toIdentifier()}");
148167
}
149168
}
150169
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
/**
3+
* This file is part of JSON:API implementation for PHP.
4+
*
5+
* (c) Alexey Karapetov <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
declare(strict_types=1);
11+
12+
namespace JsonApiPhp\JsonApi\Document\PrimaryData;
13+
14+
use JsonApiPhp\JsonApi\Document\Resource\ResourceIdentifier;
15+
use JsonApiPhp\JsonApi\Document\Resource\ResourceObject;
16+
17+
final class MultiIdentifierData implements PrimaryDataInterface
18+
{
19+
private $identifiers;
20+
21+
public function __construct(ResourceIdentifier ...$identifiers)
22+
{
23+
$this->identifiers = $identifiers;
24+
}
25+
26+
public function hasLinkTo(ResourceObject $resource): bool
27+
{
28+
foreach ($this->identifiers as $identifier) {
29+
if ($identifier->identifies($resource)) {
30+
return true;
31+
}
32+
}
33+
return false;
34+
}
35+
36+
public function jsonSerialize()
37+
{
38+
return $this->identifiers;
39+
}
40+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
/**
3+
* This file is part of JSON:API implementation for PHP.
4+
*
5+
* (c) Alexey Karapetov <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
declare(strict_types=1);
11+
12+
namespace JsonApiPhp\JsonApi\Document\PrimaryData;
13+
14+
use JsonApiPhp\JsonApi\Document\Resource\ResourceObject;
15+
16+
final class MultiResourceData implements PrimaryDataInterface
17+
{
18+
private $resources;
19+
20+
public function __construct(ResourceObject ...$resources)
21+
{
22+
$this->resources = $resources;
23+
}
24+
25+
public function hasLinkTo(ResourceObject $resource): bool
26+
{
27+
foreach ($this->resources as $myResource) {
28+
if ($myResource->identifies($resource)) {
29+
return true;
30+
}
31+
}
32+
return false;
33+
}
34+
35+
public function jsonSerialize()
36+
{
37+
return $this->resources;
38+
}
39+
}

src/Document/PrimaryData/NullData.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
/**
3+
* This file is part of JSON:API implementation for PHP.
4+
*
5+
* (c) Alexey Karapetov <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
declare(strict_types=1);
11+
12+
namespace JsonApiPhp\JsonApi\Document\PrimaryData;
13+
14+
use JsonApiPhp\JsonApi\Document\Resource\ResourceObject;
15+
16+
final class NullData implements PrimaryDataInterface
17+
{
18+
public function hasLinkTo(ResourceObject $resource): bool
19+
{
20+
return false;
21+
}
22+
23+
public function jsonSerialize()
24+
{
25+
return null;
26+
}
27+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
/**
3+
* This file is part of JSON:API implementation for PHP.
4+
*
5+
* (c) Alexey Karapetov <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
declare(strict_types=1);
11+
12+
namespace JsonApiPhp\JsonApi\Document\PrimaryData;
13+
14+
use JsonApiPhp\JsonApi\Document\Resource\ResourceObject;
15+
16+
interface PrimaryDataInterface extends \JsonSerializable
17+
{
18+
public function hasLinkTo(ResourceObject $resource): bool;
19+
20+
public function jsonSerialize();
21+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
/**
3+
* This file is part of JSON:API implementation for PHP.
4+
*
5+
* (c) Alexey Karapetov <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
declare(strict_types=1);
11+
12+
namespace JsonApiPhp\JsonApi\Document\PrimaryData;
13+
14+
use JsonApiPhp\JsonApi\Document\Resource\ResourceIdentifier;
15+
use JsonApiPhp\JsonApi\Document\Resource\ResourceObject;
16+
17+
final class SingleIdentifierData implements PrimaryDataInterface
18+
{
19+
private $identifier;
20+
21+
public function __construct(ResourceIdentifier $identifier)
22+
{
23+
$this->identifier = $identifier;
24+
}
25+
26+
public function hasLinkTo(ResourceObject $resource): bool
27+
{
28+
return $this->identifier->identifies($resource);
29+
}
30+
31+
public function jsonSerialize()
32+
{
33+
return $this->identifier;
34+
}
35+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
/**
3+
* This file is part of JSON:API implementation for PHP.
4+
*
5+
* (c) Alexey Karapetov <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
declare(strict_types=1);
11+
12+
namespace JsonApiPhp\JsonApi\Document\PrimaryData;
13+
14+
use JsonApiPhp\JsonApi\Document\Resource\ResourceObject;
15+
16+
final class SingleResourceData implements PrimaryDataInterface
17+
{
18+
private $resource;
19+
20+
public function __construct(ResourceObject $resource)
21+
{
22+
$this->resource = $resource;
23+
}
24+
25+
public function hasLinkTo(ResourceObject $resource): bool
26+
{
27+
return $this->resource->identifies($resource);
28+
}
29+
30+
public function jsonSerialize()
31+
{
32+
return $this->resource;
33+
}
34+
}

0 commit comments

Comments
 (0)