From ec78b3f5bf110a7ea6a9484223dffd253449b7eb Mon Sep 17 00:00:00 2001 From: Alexey Karapetov Date: Tue, 28 Mar 2017 17:16:52 -0700 Subject: [PATCH 1/3] Added copyright --- phpcs.xml.dist | 11 ++++++++ phpunit.xml.dist | 11 ++++++++ src/Document/Document.php | 15 +++++++++-- src/Document/Error.php | 11 ++++++++ src/Document/PrimaryData.php | 12 --------- src/Document/PrimaryDataInterface.php | 23 +++++++++++++++++ src/Document/PrimaryDataItem.php | 12 --------- src/Document/PrimaryDataItemInterface.php | 19 ++++++++++++++ src/Document/Resource/NullData.php | 14 ----------- src/Document/Resource/NullDataInterface.php | 25 +++++++++++++++++++ .../Resource/Relationship/Linkage.php | 11 ++++++++ .../Resource/Relationship/Relationship.php | 11 ++++++++ src/Document/Resource/ResourceId.php | 17 ++++++++++--- src/Document/Resource/ResourceObject.php | 17 ++++++++++--- src/HasLinks.php | 11 ++++++++ src/HasLinksAndMeta.php | 11 ++++++++ src/HasMeta.php | 11 ++++++++ test/Document/DocumentTest.php | 15 +++++++++-- test/Document/ErrorTest.php | 11 ++++++++ .../Resource/Relationship/LinkageTest.php | 11 ++++++++ .../Relationship/RelationshipTest.php | 11 ++++++++ test/Document/Resource/ResourceTest.php | 11 ++++++++ test/HasAssertEqualsAsJson.php | 11 ++++++++ test/IntegrationTest.php | 11 ++++++++ test/bootstrap.php | 11 ++++++++ 25 files changed, 286 insertions(+), 48 deletions(-) delete mode 100644 src/Document/PrimaryData.php create mode 100644 src/Document/PrimaryDataInterface.php delete mode 100644 src/Document/PrimaryDataItem.php create mode 100644 src/Document/PrimaryDataItemInterface.php delete mode 100644 src/Document/Resource/NullData.php create mode 100644 src/Document/Resource/NullDataInterface.php diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 1747b77..72f19e0 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -1,4 +1,15 @@ + + src test diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d6bfad2..30c608a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,4 +1,15 @@ + + + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Document; @@ -39,14 +50,14 @@ public static function fromErrors(Error ...$errors): self return $doc; } - public static function fromData(PrimaryData $data): self + public static function fromData(PrimaryDataInterface $data): self { $doc = new self; $doc->data = $data; return $doc; } - public static function fromDataItems(PrimaryDataItem ...$data): self + public static function fromDataItems(PrimaryDataItemInterface ...$data): self { $doc = new self; $doc->data = $data; diff --git a/src/Document/Error.php b/src/Document/Error.php index ec874a3..60d361d 100644 --- a/src/Document/Error.php +++ b/src/Document/Error.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Document; diff --git a/src/Document/PrimaryData.php b/src/Document/PrimaryData.php deleted file mode 100644 index c6b5198..0000000 --- a/src/Document/PrimaryData.php +++ /dev/null @@ -1,12 +0,0 @@ - + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + +declare(strict_types=1); + +namespace JsonApiPhp\JsonApi\Document; + +/** + * Primary data of a Single Resource Document + * @package F3\JsonApi\Resource + */ +interface PrimaryDataInterface extends \JsonSerializable +{ +} diff --git a/src/Document/PrimaryDataItem.php b/src/Document/PrimaryDataItem.php deleted file mode 100644 index b6c4e90..0000000 --- a/src/Document/PrimaryDataItem.php +++ /dev/null @@ -1,12 +0,0 @@ - + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + +declare(strict_types=1); + +namespace JsonApiPhp\JsonApi\Document; + +interface PrimaryDataItemInterface extends \JsonSerializable +{ +} diff --git a/src/Document/Resource/NullData.php b/src/Document/Resource/NullData.php deleted file mode 100644 index 2258ad4..0000000 --- a/src/Document/Resource/NullData.php +++ /dev/null @@ -1,14 +0,0 @@ - + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + +declare(strict_types=1); + +namespace JsonApiPhp\JsonApi\Document\Resource; + +use JsonApiPhp\JsonApi\Document\PrimaryDataInterface; + +final class NullDataInterface implements PrimaryDataInterface +{ + public function jsonSerialize() + { + return null; + } +} diff --git a/src/Document/Resource/Relationship/Linkage.php b/src/Document/Resource/Relationship/Linkage.php index 480b2c2..9464a5c 100644 --- a/src/Document/Resource/Relationship/Linkage.php +++ b/src/Document/Resource/Relationship/Linkage.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Document\Resource\Relationship; diff --git a/src/Document/Resource/Relationship/Relationship.php b/src/Document/Resource/Relationship/Relationship.php index 25b3ad2..324a158 100644 --- a/src/Document/Resource/Relationship/Relationship.php +++ b/src/Document/Resource/Relationship/Relationship.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Document\Resource\Relationship; diff --git a/src/Document/Resource/ResourceId.php b/src/Document/Resource/ResourceId.php index 0b2d117..533c27b 100644 --- a/src/Document/Resource/ResourceId.php +++ b/src/Document/Resource/ResourceId.php @@ -1,13 +1,24 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Document\Resource; -use JsonApiPhp\JsonApi\Document\PrimaryData; -use JsonApiPhp\JsonApi\Document\PrimaryDataItem; +use JsonApiPhp\JsonApi\Document\PrimaryDataInterface; +use JsonApiPhp\JsonApi\Document\PrimaryDataItemInterface; use JsonApiPhp\JsonApi\HasMeta; -final class ResourceId implements PrimaryData, PrimaryDataItem +final class ResourceId implements PrimaryDataInterface, PrimaryDataItemInterface { use HasMeta; diff --git a/src/Document/Resource/ResourceObject.php b/src/Document/Resource/ResourceObject.php index 2f251f1..a4e0910 100644 --- a/src/Document/Resource/ResourceObject.php +++ b/src/Document/Resource/ResourceObject.php @@ -1,14 +1,25 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Document\Resource; -use JsonApiPhp\JsonApi\Document\PrimaryData; -use JsonApiPhp\JsonApi\Document\PrimaryDataItem; +use JsonApiPhp\JsonApi\Document\PrimaryDataInterface; +use JsonApiPhp\JsonApi\Document\PrimaryDataItemInterface; use JsonApiPhp\JsonApi\Document\Resource\Relationship\Relationship; use JsonApiPhp\JsonApi\HasLinksAndMeta; -final class ResourceObject implements PrimaryData, PrimaryDataItem +final class ResourceObject implements PrimaryDataInterface, PrimaryDataItemInterface { use HasLinksAndMeta; diff --git a/src/HasLinks.php b/src/HasLinks.php index c0ba938..a5ef48e 100644 --- a/src/HasLinks.php +++ b/src/HasLinks.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi; diff --git a/src/HasLinksAndMeta.php b/src/HasLinksAndMeta.php index e631f93..a048c4c 100644 --- a/src/HasLinksAndMeta.php +++ b/src/HasLinksAndMeta.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi; diff --git a/src/HasMeta.php b/src/HasMeta.php index 98841da..6ab6f30 100644 --- a/src/HasMeta.php +++ b/src/HasMeta.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi; diff --git a/test/Document/DocumentTest.php b/test/Document/DocumentTest.php index 636be1d..357ae22 100644 --- a/test/Document/DocumentTest.php +++ b/test/Document/DocumentTest.php @@ -1,11 +1,22 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Test\Document; use JsonApiPhp\JsonApi\Document\Document; use JsonApiPhp\JsonApi\Document\Error; -use JsonApiPhp\JsonApi\Document\Resource\NullData; +use JsonApiPhp\JsonApi\Document\Resource\NullDataInterface; use JsonApiPhp\JsonApi\Document\Resource\ResourceId; use JsonApiPhp\JsonApi\Test\HasAssertEqualsAsJson; use PHPUnit\Framework\TestCase; @@ -135,6 +146,6 @@ private function createErrorDoc(): Document private function createNullDoc(): Document { - return Document::fromData(new NullData); + return Document::fromData(new NullDataInterface); } } diff --git a/test/Document/ErrorTest.php b/test/Document/ErrorTest.php index 88a375a..cfd508f 100644 --- a/test/Document/ErrorTest.php +++ b/test/Document/ErrorTest.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Document; diff --git a/test/Document/Resource/Relationship/LinkageTest.php b/test/Document/Resource/Relationship/LinkageTest.php index aab5305..abc4e7c 100644 --- a/test/Document/Resource/Relationship/LinkageTest.php +++ b/test/Document/Resource/Relationship/LinkageTest.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Test\Document\Resource\Relationship; diff --git a/test/Document/Resource/Relationship/RelationshipTest.php b/test/Document/Resource/Relationship/RelationshipTest.php index b6d86a6..688a5e1 100644 --- a/test/Document/Resource/Relationship/RelationshipTest.php +++ b/test/Document/Resource/Relationship/RelationshipTest.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Test\Document\Resource\Relationship; diff --git a/test/Document/Resource/ResourceTest.php b/test/Document/Resource/ResourceTest.php index b455284..a4f2637 100644 --- a/test/Document/Resource/ResourceTest.php +++ b/test/Document/Resource/ResourceTest.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Test\Document\Resource; diff --git a/test/HasAssertEqualsAsJson.php b/test/HasAssertEqualsAsJson.php index 03219db..281d3c1 100644 --- a/test/HasAssertEqualsAsJson.php +++ b/test/HasAssertEqualsAsJson.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Test; diff --git a/test/IntegrationTest.php b/test/IntegrationTest.php index 62ea346..152e6ab 100644 --- a/test/IntegrationTest.php +++ b/test/IntegrationTest.php @@ -1,4 +1,15 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + declare(strict_types=1); namespace JsonApiPhp\JsonApi\Test; diff --git a/test/bootstrap.php b/test/bootstrap.php index d4922df..325519f 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -1,3 +1,14 @@ + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__. '/HasAssertEqualsAsJson.php'; From e6ff1176e41ae64206e7cb643f249b01e9c11f04 Mon Sep 17 00:00:00 2001 From: Alexey Karapetov Date: Tue, 28 Mar 2017 17:21:27 -0700 Subject: [PATCH 2/3] Formatting --- test/Document/DocumentTest.php | 16 ++++++++-------- test/Document/ErrorTest.php | 2 +- .../Resource/Relationship/LinkageTest.php | 3 ++- test/Document/Resource/ResourceTest.php | 12 ++++++------ test/HasAssertEqualsAsJson.php | 2 +- test/IntegrationTest.php | 2 +- test/bootstrap.php | 4 ++-- 7 files changed, 21 insertions(+), 20 deletions(-) diff --git a/test/Document/DocumentTest.php b/test/Document/DocumentTest.php index 357ae22..859f328 100644 --- a/test/Document/DocumentTest.php +++ b/test/Document/DocumentTest.php @@ -7,7 +7,7 @@ * * * * For the full copyright and license information, please view the LICENSE * * file that was distributed with this source code. - * + * */ declare(strict_types=1); @@ -64,7 +64,7 @@ public function testCanCreateFromResourceId() [ 'data' => [ 'type' => 'books', - 'id' => 'abc123', + 'id' => 'abc123', ], ], Document::fromData(new ResourceId('books', 'abc123')) @@ -85,11 +85,11 @@ public function testCanCreateFromMultipleItems() 'data' => [ [ 'type' => 'books', - 'id' => '12', + 'id' => '12', ], [ 'type' => 'carrots', - 'id' => '42', + 'id' => '42', ], ], ], @@ -107,10 +107,10 @@ public function testDocumentMayContainVersion() $doc->setApiMeta(['a' => 'b']); $this->assertEqualsAsJson( [ - 'data' => null, + 'data' => null, 'jsonapi' => [ 'version' => '1.2.3', - 'meta' => ['a' => 'b'], + 'meta' => ['a' => 'b'], ], ], $doc @@ -124,9 +124,9 @@ public function testDocumentMayContainLinks() $doc->setLink('related', 'http://example.com/rel', ['a' => 'b']); $this->assertEqualsAsJson( [ - 'data' => null, + 'data' => null, 'links' => [ - 'self' => 'http://example.com/self', + 'self' => 'http://example.com/self', 'related' => [ 'href' => 'http://example.com/rel', 'meta' => ['a' => 'b'], diff --git a/test/Document/ErrorTest.php b/test/Document/ErrorTest.php index cfd508f..077d6af 100644 --- a/test/Document/ErrorTest.php +++ b/test/Document/ErrorTest.php @@ -7,7 +7,7 @@ * * * * For the full copyright and license information, please view the LICENSE * * file that was distributed with this source code. - * + * */ declare(strict_types=1); diff --git a/test/Document/Resource/Relationship/LinkageTest.php b/test/Document/Resource/Relationship/LinkageTest.php index abc4e7c..ea7b12b 100644 --- a/test/Document/Resource/Relationship/LinkageTest.php +++ b/test/Document/Resource/Relationship/LinkageTest.php @@ -7,7 +7,7 @@ * * * * For the full copyright and license information, please view the LICENSE * * file that was distributed with this source code. - * + * */ declare(strict_types=1); @@ -30,6 +30,7 @@ public function testNullLinkage() Linkage::nullLinkage() ); } + public function testEmptyArrayLinkage() { $this->assertEqualsAsJson( diff --git a/test/Document/Resource/ResourceTest.php b/test/Document/Resource/ResourceTest.php index a4f2637..288dff8 100644 --- a/test/Document/Resource/ResourceTest.php +++ b/test/Document/Resource/ResourceTest.php @@ -46,14 +46,14 @@ public function resourceProvider() [ [ 'type' => 'books', - 'id' => '42abc', + 'id' => '42abc', ], new ResourceId('books', '42abc'), ], [ [ 'type' => 'books', - 'id' => '42abc', + 'id' => '42abc', 'meta' => [ 'foo' => 'bar', ], @@ -62,8 +62,8 @@ public function resourceProvider() ], [ [ - 'type' => 'books', - 'id' => '42abc', + 'type' => 'books', + 'id' => '42abc', 'attributes' => [ 'attr' => 'val', ], @@ -74,10 +74,10 @@ public function resourceProvider() ], ], ], - 'links' => [ + 'links' => [ 'self' => 'http://localhost', ], - 'meta' => [ + 'meta' => [ 'foo' => 'bar', ], ], diff --git a/test/HasAssertEqualsAsJson.php b/test/HasAssertEqualsAsJson.php index 281d3c1..424ea9d 100644 --- a/test/HasAssertEqualsAsJson.php +++ b/test/HasAssertEqualsAsJson.php @@ -7,7 +7,7 @@ * * * * For the full copyright and license information, please view the LICENSE * * file that was distributed with this source code. - * + * */ declare(strict_types=1); diff --git a/test/IntegrationTest.php b/test/IntegrationTest.php index 152e6ab..b720c7e 100644 --- a/test/IntegrationTest.php +++ b/test/IntegrationTest.php @@ -7,7 +7,7 @@ * * * * For the full copyright and license information, please view the LICENSE * * file that was distributed with this source code. - * + * */ declare(strict_types=1); diff --git a/test/bootstrap.php b/test/bootstrap.php index 325519f..ba377ce 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -7,8 +7,8 @@ * * * * For the full copyright and license information, please view the LICENSE * * file that was distributed with this source code. - * + * */ require_once __DIR__ . '/../vendor/autoload.php'; -require_once __DIR__. '/HasAssertEqualsAsJson.php'; +require_once __DIR__ . '/HasAssertEqualsAsJson.php'; From c7d39216eec676a626d55d2aafe3b244b636e309 Mon Sep 17 00:00:00 2001 From: Alexey Karapetov Date: Tue, 28 Mar 2017 20:19:42 -0700 Subject: [PATCH 3/3] Compound Documents --- src/Document/Document.php | 77 ++++++++++-- src/Document/PrimaryDataItemInterface.php | 19 --- .../Resource/IdentifiableResource.php | 29 +++++ .../{NullDataInterface.php => NullData.php} | 9 +- .../Resource/Relationship/Linkage.php | 14 +++ .../Resource/Relationship/Relationship.php | 17 ++- src/Document/Resource/ResourceId.php | 6 +- src/Document/Resource/ResourceObject.php | 24 +++- test/Document/CompoundDocumentTest.php | 111 ++++++++++++++++++ test/Document/DocumentTest.php | 10 +- test/IntegrationTest.php | 2 +- 11 files changed, 265 insertions(+), 53 deletions(-) delete mode 100644 src/Document/PrimaryDataItemInterface.php create mode 100644 src/Document/Resource/IdentifiableResource.php rename src/Document/Resource/{NullDataInterface.php => NullData.php} (74%) create mode 100644 test/Document/CompoundDocumentTest.php diff --git a/src/Document/Document.php b/src/Document/Document.php index 7341d81..fa225c5 100644 --- a/src/Document/Document.php +++ b/src/Document/Document.php @@ -14,6 +14,8 @@ namespace JsonApiPhp\JsonApi\Document; +use JsonApiPhp\JsonApi\Document\Resource\IdentifiableResource; +use JsonApiPhp\JsonApi\Document\Resource\ResourceObject; use JsonApiPhp\JsonApi\HasLinksAndMeta; final class Document implements \JsonSerializable @@ -23,11 +25,13 @@ final class Document implements \JsonSerializable use HasLinksAndMeta; - protected $data; - protected $errors; - protected $meta; - protected $jsonapi; - protected $links; + private $data; + private $errors; + private $meta; + private $jsonapi; + private $links; + private $included; + private $sparse = false; /** * Use named constructors instead @@ -50,14 +54,14 @@ public static function fromErrors(Error ...$errors): self return $doc; } - public static function fromData(PrimaryDataInterface $data): self + public static function fromResource(IdentifiableResource $data): self { $doc = new self; $doc->data = $data; return $doc; } - public static function fromDataItems(PrimaryDataItemInterface ...$data): self + public static function fromResources(IdentifiableResource ...$data): self { $doc = new self; $doc->data = $data; @@ -74,19 +78,70 @@ public function setApiMeta(array $meta): void $this->jsonapi['meta'] = $meta; } + public function setIncluded(IdentifiableResource ...$included) + { + $this->included = $included; + } + + public function setSparse() + { + $this->sparse = true; + } + public function jsonSerialize() { + if ($this->included && !$this->sparse) { + foreach ($this->included as $resource) { + if ($this->hasLinkTo($resource)) { + continue; + } + throw new \LogicException("Full linkage is required for $resource"); + } + } return array_filter( [ - 'data' => $this->data, - 'errors' => $this->errors, - 'meta' => $this->meta, + 'data' => $this->data, + 'errors' => $this->errors, + 'meta' => $this->meta, 'jsonapi' => $this->jsonapi, - 'links' => $this->links, + 'links' => $this->links, + 'included' => $this->included, ], function ($v) { return null !== $v; } ); } + + private function hasLinkTo(IdentifiableResource $resource): bool + { + if (!$this->data) { + return false; + } + + foreach ($this->toDataItems() as $my_resource) { + + if ($my_resource instanceof ResourceObject) { + if ($my_resource->hasRelationTo($resource)) { + return true; + } + } + } + return false; + } + + /** + * @return IdentifiableResource[] + */ + private function toDataItems(): array + { + if ($this->data instanceof IdentifiableResource) { + return [$this->data]; + } elseif (is_array($this->data)) { + return $this->data; + } else { + return []; + } + + } } diff --git a/src/Document/PrimaryDataItemInterface.php b/src/Document/PrimaryDataItemInterface.php deleted file mode 100644 index c8dda17..0000000 --- a/src/Document/PrimaryDataItemInterface.php +++ /dev/null @@ -1,19 +0,0 @@ - - * * - * * For the full copyright and license information, please view the LICENSE - * * file that was distributed with this source code. - * - */ - -declare(strict_types=1); - -namespace JsonApiPhp\JsonApi\Document; - -interface PrimaryDataItemInterface extends \JsonSerializable -{ -} diff --git a/src/Document/Resource/IdentifiableResource.php b/src/Document/Resource/IdentifiableResource.php new file mode 100644 index 0000000..cbd458a --- /dev/null +++ b/src/Document/Resource/IdentifiableResource.php @@ -0,0 +1,29 @@ + + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + +namespace JsonApiPhp\JsonApi\Document\Resource; + +abstract class IdentifiableResource implements \JsonSerializable +{ + protected $id; + protected $type; + + public function isEqualTo(IdentifiableResource $that): bool + { + return $this->type === $that->type && $this->id === $that->id; + } + + public function __toString() + { + return "$this->type:$this->id"; + } +} \ No newline at end of file diff --git a/src/Document/Resource/NullDataInterface.php b/src/Document/Resource/NullData.php similarity index 74% rename from src/Document/Resource/NullDataInterface.php rename to src/Document/Resource/NullData.php index 2ade762..6b18ea9 100644 --- a/src/Document/Resource/NullDataInterface.php +++ b/src/Document/Resource/NullData.php @@ -14,10 +14,13 @@ namespace JsonApiPhp\JsonApi\Document\Resource; -use JsonApiPhp\JsonApi\Document\PrimaryDataInterface; - -final class NullDataInterface implements PrimaryDataInterface +final class NullData extends IdentifiableResource { + public function isEqualTo(IdentifiableResource $that): bool + { + return false; + } + public function jsonSerialize() { return null; diff --git a/src/Document/Resource/Relationship/Linkage.php b/src/Document/Resource/Relationship/Linkage.php index 9464a5c..c1e015e 100644 --- a/src/Document/Resource/Relationship/Linkage.php +++ b/src/Document/Resource/Relationship/Linkage.php @@ -14,6 +14,7 @@ namespace JsonApiPhp\JsonApi\Document\Resource\Relationship; +use JsonApiPhp\JsonApi\Document\Resource\IdentifiableResource; use JsonApiPhp\JsonApi\Document\Resource\ResourceId; final class Linkage implements \JsonSerializable @@ -50,6 +51,19 @@ public static function fromManyResourceIds(ResourceId ...$data): self return $linkage; } + public function isLinkedTo(IdentifiableResource $resource): bool + { + if ($this->data) { + foreach ((array)$this->data as $my_resource) { + if ($resource->isEqualTo($my_resource)) { + return true; + } + } + } + return false; + + } + public function jsonSerialize() { return $this->data; diff --git a/src/Document/Resource/Relationship/Relationship.php b/src/Document/Resource/Relationship/Relationship.php index 324a158..4d043e5 100644 --- a/src/Document/Resource/Relationship/Relationship.php +++ b/src/Document/Resource/Relationship/Relationship.php @@ -14,13 +14,17 @@ namespace JsonApiPhp\JsonApi\Document\Resource\Relationship; +use JsonApiPhp\JsonApi\Document\Resource\IdentifiableResource; use JsonApiPhp\JsonApi\HasLinksAndMeta; final class Relationship implements \JsonSerializable { use HasLinksAndMeta; - private $data; + /** + * @var Linkage + */ + private $linkage = null; private $meta; private $links; @@ -49,18 +53,23 @@ public static function fromRelatedLink(string $link, array $meta = null): self return $r; } - public static function fromLinkage(Linkage $data): self + public static function fromLinkage(Linkage $linkage): self { $r = new self; - $r->data = $data; + $r->linkage = $linkage; return $r; } + public function isLinkedTo(IdentifiableResource $resource): bool + { + return ($this->linkage && $this->linkage->isLinkedTo($resource)); + } + public function jsonSerialize() { return array_filter( [ - 'data' => $this->data, + 'data' => $this->linkage, 'links' => $this->links, 'meta' => $this->meta, ], diff --git a/src/Document/Resource/ResourceId.php b/src/Document/Resource/ResourceId.php index 533c27b..5a3ea5b 100644 --- a/src/Document/Resource/ResourceId.php +++ b/src/Document/Resource/ResourceId.php @@ -14,16 +14,12 @@ namespace JsonApiPhp\JsonApi\Document\Resource; -use JsonApiPhp\JsonApi\Document\PrimaryDataInterface; -use JsonApiPhp\JsonApi\Document\PrimaryDataItemInterface; use JsonApiPhp\JsonApi\HasMeta; -final class ResourceId implements PrimaryDataInterface, PrimaryDataItemInterface +final class ResourceId extends IdentifiableResource { use HasMeta; - private $type; - private $id; private $meta; public function __construct(string $type, string $id = null, array $meta = []) diff --git a/src/Document/Resource/ResourceObject.php b/src/Document/Resource/ResourceObject.php index a4e0910..5eb0711 100644 --- a/src/Document/Resource/ResourceObject.php +++ b/src/Document/Resource/ResourceObject.php @@ -14,17 +14,13 @@ namespace JsonApiPhp\JsonApi\Document\Resource; -use JsonApiPhp\JsonApi\Document\PrimaryDataInterface; -use JsonApiPhp\JsonApi\Document\PrimaryDataItemInterface; use JsonApiPhp\JsonApi\Document\Resource\Relationship\Relationship; use JsonApiPhp\JsonApi\HasLinksAndMeta; -final class ResourceObject implements PrimaryDataInterface, PrimaryDataItemInterface +final class ResourceObject extends IdentifiableResource { use HasLinksAndMeta; - private $id; - private $type; private $meta; private $links; private $attributes; @@ -55,6 +51,24 @@ public function setRelationship(string $name, Relationship $relationship): void $this->relationships[$name] = $relationship; } + public function HasRelationTo(IdentifiableResource $resource): bool + { + if ($this->relationships) { + /** @var Relationship $relationship */ + foreach ($this->relationships as $relationship) { + if ($relationship->isLinkedTo($resource)) { + return true; + } + } + } + return false; + } + + public function toId(): ResourceId + { + return new ResourceId($this->type, $this->id); + } + public function jsonSerialize() { return array_filter( diff --git a/test/Document/CompoundDocumentTest.php b/test/Document/CompoundDocumentTest.php new file mode 100644 index 0000000..5c91f75 --- /dev/null +++ b/test/Document/CompoundDocumentTest.php @@ -0,0 +1,111 @@ + + * * + * * For the full copyright and license information, please view the LICENSE + * * file that was distributed with this source code. + * + */ + +declare(strict_types=1); + +namespace JsonApiPhp\JsonApi\Test\Document; + +use JsonApiPhp\JsonApi\Document\Document; +use JsonApiPhp\JsonApi\Document\Resource\NullData; +use JsonApiPhp\JsonApi\Document\Resource\Relationship\Linkage; +use JsonApiPhp\JsonApi\Document\Resource\Relationship\Relationship; +use JsonApiPhp\JsonApi\Document\Resource\ResourceObject; +use JsonApiPhp\JsonApi\Test\HasAssertEqualsAsJson; +use PHPUnit\Framework\TestCase; + +class CompoundDocumentTest extends TestCase +{ + use HasAssertEqualsAsJson; + + public function testIncludedResourcesRepresentedAsArray() + { + $apple = new ResourceObject('apples', '1'); + $apple->setAttribute('color', 'red'); + $orange = new ResourceObject('oranges', '1'); + $orange->setAttribute('color', 'orange'); + $basket = new ResourceObject('basket', '1'); + $basket->setRelationship( + 'fruits', + Relationship::fromLinkage( + Linkage::fromManyResourceIds( + $apple->toId(), + $orange->toId() + ) + ) + ); + $doc = Document::fromResource($basket); + $doc->setIncluded($apple, $orange); + $this->assertEqualsAsJson( + [ + 'data' => [ + 'type' => 'basket', + 'id' => '1', + 'relationships' => [ + 'fruits' => [ + 'data' => [ + [ + 'type' => 'apples', + 'id' => '1', + ], + [ + 'type' => 'oranges', + 'id' => '1', + ], + ] + ] + ], + ], + 'included' => [ + [ + 'type' => 'apples', + 'id' => '1', + 'attributes' => [ + 'color' => 'red', + ], + ], + [ + 'type' => 'oranges', + 'id' => '1', + 'attributes' => [ + 'color' => 'orange', + ], + ], + ] + + ], + $doc + ); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Full linkage is required for apples:1 + */ + public function testFullLinkageIsRequired() + { + $doc = Document::fromResource(new NullData); + $doc->setIncluded( + new ResourceObject('apples', '1') + ); + json_encode($doc); + } + + public function testFullLinkageIsNotRequiredIfSparse() + { + $doc = Document::fromResource(new NullData); + $doc->setSparse(); + $doc->setIncluded( + new ResourceObject('apples', '1') + ); + $this->assertInternalType('string', json_encode($doc)); + } +} diff --git a/test/Document/DocumentTest.php b/test/Document/DocumentTest.php index 859f328..98c2e14 100644 --- a/test/Document/DocumentTest.php +++ b/test/Document/DocumentTest.php @@ -16,7 +16,7 @@ use JsonApiPhp\JsonApi\Document\Document; use JsonApiPhp\JsonApi\Document\Error; -use JsonApiPhp\JsonApi\Document\Resource\NullDataInterface; +use JsonApiPhp\JsonApi\Document\Resource\NullData; use JsonApiPhp\JsonApi\Document\Resource\ResourceId; use JsonApiPhp\JsonApi\Test\HasAssertEqualsAsJson; use PHPUnit\Framework\TestCase; @@ -67,7 +67,7 @@ public function testCanCreateFromResourceId() 'id' => 'abc123', ], ], - Document::fromData(new ResourceId('books', 'abc123')) + Document::fromResource(new ResourceId('books', 'abc123')) ); } @@ -77,7 +77,7 @@ public function testCanCreateFromMultipleItems() [ 'data' => [], ], - Document::fromDataItems() + Document::fromResources() ); $this->assertEqualsAsJson( @@ -93,7 +93,7 @@ public function testCanCreateFromMultipleItems() ], ], ], - Document::fromDataItems( + Document::fromResources( new ResourceId('books', '12'), new ResourceId('carrots', '42') ) @@ -146,6 +146,6 @@ private function createErrorDoc(): Document private function createNullDoc(): Document { - return Document::fromData(new NullDataInterface); + return Document::fromResource(new NullData); } } diff --git a/test/IntegrationTest.php b/test/IntegrationTest.php index b720c7e..e7d470c 100644 --- a/test/IntegrationTest.php +++ b/test/IntegrationTest.php @@ -59,7 +59,7 @@ public function testFromTheReadmeFile() $author->setLink('related', '/articles/1/author'); $articles->setRelationship('author', $author); $articles->setAttribute('title', 'Rails is Omakase'); - $doc = Document::fromData($articles); + $doc = Document::fromResource($articles); $this->assertEquals( $json,