Skip to content

Commit d49294c

Browse files
authored
Compound Documents (#10)
* Added copyright * Formatting * Compound Documents
1 parent 1af1605 commit d49294c

12 files changed

+267
-81
lines changed

src/Document/Document.php

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
namespace JsonApiPhp\JsonApi\Document;
1616

17+
use JsonApiPhp\JsonApi\Document\Resource\IdentifiableResource;
18+
use JsonApiPhp\JsonApi\Document\Resource\ResourceObject;
1719
use JsonApiPhp\JsonApi\HasLinksAndMeta;
1820

1921
final class Document implements \JsonSerializable
@@ -23,11 +25,13 @@ final class Document implements \JsonSerializable
2325

2426
use HasLinksAndMeta;
2527

26-
protected $data;
27-
protected $errors;
28-
protected $meta;
29-
protected $jsonapi;
30-
protected $links;
28+
private $data;
29+
private $errors;
30+
private $meta;
31+
private $jsonapi;
32+
private $links;
33+
private $included;
34+
private $sparse = false;
3135

3236
/**
3337
* Use named constructors instead
@@ -50,14 +54,14 @@ public static function fromErrors(Error ...$errors): self
5054
return $doc;
5155
}
5256

53-
public static function fromData(PrimaryDataInterface $data): self
57+
public static function fromResource(IdentifiableResource $data): self
5458
{
5559
$doc = new self;
5660
$doc->data = $data;
5761
return $doc;
5862
}
5963

60-
public static function fromDataItems(PrimaryDataItemInterface ...$data): self
64+
public static function fromResources(IdentifiableResource ...$data): self
6165
{
6266
$doc = new self;
6367
$doc->data = $data;
@@ -74,19 +78,68 @@ public function setApiMeta(array $meta): void
7478
$this->jsonapi['meta'] = $meta;
7579
}
7680

81+
public function setIncluded(IdentifiableResource ...$included)
82+
{
83+
$this->included = $included;
84+
}
85+
86+
public function setSparse()
87+
{
88+
$this->sparse = true;
89+
}
90+
7791
public function jsonSerialize()
7892
{
93+
if ($this->included && !$this->sparse) {
94+
foreach ($this->included as $resource) {
95+
if ($this->hasLinkTo($resource)) {
96+
continue;
97+
}
98+
throw new \LogicException("Full linkage is required for $resource");
99+
}
100+
}
79101
return array_filter(
80102
[
81-
'data' => $this->data,
82-
'errors' => $this->errors,
83-
'meta' => $this->meta,
103+
'data' => $this->data,
104+
'errors' => $this->errors,
105+
'meta' => $this->meta,
84106
'jsonapi' => $this->jsonapi,
85-
'links' => $this->links,
107+
'links' => $this->links,
108+
'included' => $this->included,
86109
],
87110
function ($v) {
88111
return null !== $v;
89112
}
90113
);
91114
}
115+
116+
private function hasLinkTo(IdentifiableResource $resource): bool
117+
{
118+
if (!$this->data) {
119+
return false;
120+
}
121+
122+
foreach ($this->toDataItems() as $my_resource) {
123+
if ($my_resource instanceof ResourceObject) {
124+
if ($my_resource->hasRelationTo($resource)) {
125+
return true;
126+
}
127+
}
128+
}
129+
return false;
130+
}
131+
132+
/**
133+
* @return IdentifiableResource[]
134+
*/
135+
private function toDataItems(): array
136+
{
137+
if ($this->data instanceof IdentifiableResource) {
138+
return [$this->data];
139+
} elseif (is_array($this->data)) {
140+
return $this->data;
141+
} else {
142+
return [];
143+
}
144+
}
92145
}

src/Document/PrimaryDataInterface.php

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/Document/PrimaryDataItemInterface.php

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
/**
3+
*
4+
* * This file is part of JSON:API implementation for PHP.
5+
* *
6+
* * (c) Alexey Karapetov <[email protected]>
7+
* *
8+
* * For the full copyright and license information, please view the LICENSE
9+
* * file that was distributed with this source code.
10+
*
11+
*/
12+
13+
namespace JsonApiPhp\JsonApi\Document\Resource;
14+
15+
abstract class IdentifiableResource implements \JsonSerializable
16+
{
17+
protected $id;
18+
protected $type;
19+
20+
public function isEqualTo(IdentifiableResource $that): bool
21+
{
22+
return $this->type === $that->type && $this->id === $that->id;
23+
}
24+
25+
public function __toString()
26+
{
27+
return "$this->type:$this->id";
28+
}
29+
}

src/Document/Resource/NullDataInterface.php renamed to src/Document/Resource/NullData.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@
1414

1515
namespace JsonApiPhp\JsonApi\Document\Resource;
1616

17-
use JsonApiPhp\JsonApi\Document\PrimaryDataInterface;
18-
19-
final class NullDataInterface implements PrimaryDataInterface
17+
final class NullData extends IdentifiableResource
2018
{
19+
public function isEqualTo(IdentifiableResource $that): bool
20+
{
21+
return false;
22+
}
23+
2124
public function jsonSerialize()
2225
{
2326
return null;

src/Document/Resource/Relationship/Linkage.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
namespace JsonApiPhp\JsonApi\Document\Resource\Relationship;
1616

17+
use JsonApiPhp\JsonApi\Document\Resource\IdentifiableResource;
1718
use JsonApiPhp\JsonApi\Document\Resource\ResourceId;
1819

1920
final class Linkage implements \JsonSerializable
@@ -50,6 +51,18 @@ public static function fromManyResourceIds(ResourceId ...$data): self
5051
return $linkage;
5152
}
5253

54+
public function isLinkedTo(IdentifiableResource $resource): bool
55+
{
56+
if ($this->data) {
57+
foreach ((array)$this->data as $my_resource) {
58+
if ($resource->isEqualTo($my_resource)) {
59+
return true;
60+
}
61+
}
62+
}
63+
return false;
64+
}
65+
5366
public function jsonSerialize()
5467
{
5568
return $this->data;

src/Document/Resource/Relationship/Relationship.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414

1515
namespace JsonApiPhp\JsonApi\Document\Resource\Relationship;
1616

17+
use JsonApiPhp\JsonApi\Document\Resource\IdentifiableResource;
1718
use JsonApiPhp\JsonApi\HasLinksAndMeta;
1819

1920
final class Relationship implements \JsonSerializable
2021
{
2122
use HasLinksAndMeta;
2223

23-
private $data;
24+
/**
25+
* @var Linkage
26+
*/
27+
private $linkage = null;
2428
private $meta;
2529
private $links;
2630

@@ -49,18 +53,23 @@ public static function fromRelatedLink(string $link, array $meta = null): self
4953
return $r;
5054
}
5155

52-
public static function fromLinkage(Linkage $data): self
56+
public static function fromLinkage(Linkage $linkage): self
5357
{
5458
$r = new self;
55-
$r->data = $data;
59+
$r->linkage = $linkage;
5660
return $r;
5761
}
5862

63+
public function isLinkedTo(IdentifiableResource $resource): bool
64+
{
65+
return ($this->linkage && $this->linkage->isLinkedTo($resource));
66+
}
67+
5968
public function jsonSerialize()
6069
{
6170
return array_filter(
6271
[
63-
'data' => $this->data,
72+
'data' => $this->linkage,
6473
'links' => $this->links,
6574
'meta' => $this->meta,
6675
],

src/Document/Resource/ResourceId.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,12 @@
1414

1515
namespace JsonApiPhp\JsonApi\Document\Resource;
1616

17-
use JsonApiPhp\JsonApi\Document\PrimaryDataInterface;
18-
use JsonApiPhp\JsonApi\Document\PrimaryDataItemInterface;
1917
use JsonApiPhp\JsonApi\HasMeta;
2018

21-
final class ResourceId implements PrimaryDataInterface, PrimaryDataItemInterface
19+
final class ResourceId extends IdentifiableResource
2220
{
2321
use HasMeta;
2422

25-
private $type;
26-
private $id;
2723
private $meta;
2824

2925
public function __construct(string $type, string $id = null, array $meta = [])

src/Document/Resource/ResourceObject.php

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,13 @@
1414

1515
namespace JsonApiPhp\JsonApi\Document\Resource;
1616

17-
use JsonApiPhp\JsonApi\Document\PrimaryDataInterface;
18-
use JsonApiPhp\JsonApi\Document\PrimaryDataItemInterface;
1917
use JsonApiPhp\JsonApi\Document\Resource\Relationship\Relationship;
2018
use JsonApiPhp\JsonApi\HasLinksAndMeta;
2119

22-
final class ResourceObject implements PrimaryDataInterface, PrimaryDataItemInterface
20+
final class ResourceObject extends IdentifiableResource
2321
{
2422
use HasLinksAndMeta;
2523

26-
private $id;
27-
private $type;
2824
private $meta;
2925
private $links;
3026
private $attributes;
@@ -55,16 +51,34 @@ public function setRelationship(string $name, Relationship $relationship): void
5551
$this->relationships[$name] = $relationship;
5652
}
5753

54+
public function hasRelationTo(IdentifiableResource $resource): bool
55+
{
56+
if ($this->relationships) {
57+
/** @var Relationship $relationship */
58+
foreach ($this->relationships as $relationship) {
59+
if ($relationship->isLinkedTo($resource)) {
60+
return true;
61+
}
62+
}
63+
}
64+
return false;
65+
}
66+
67+
public function toId(): ResourceId
68+
{
69+
return new ResourceId($this->type, $this->id);
70+
}
71+
5872
public function jsonSerialize()
5973
{
6074
return array_filter(
6175
[
62-
'type' => $this->type,
63-
'id' => $this->id,
64-
'attributes' => $this->attributes,
76+
'type' => $this->type,
77+
'id' => $this->id,
78+
'attributes' => $this->attributes,
6579
'relationships' => $this->relationships,
66-
'links' => $this->links,
67-
'meta' => $this->meta,
80+
'links' => $this->links,
81+
'meta' => $this->meta,
6882
],
6983
function ($v) {
7084
return null !== $v;

0 commit comments

Comments
 (0)