diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3fe04c..674424e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,8 @@ name: CI -on: push +on: + - push + - pull_request jobs: php-tests: diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c5c29b..5de9783 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.2] - 2025-03-14 + +### Added +- AbstractCollection for handle array of resources in data field +- Exception on pass array as data into AbstractDocument constructor + ## [0.0.1] - 2025-03-13 ### Added - Extract all DTO types from FreeElephants/json-api-php-toolkit to this project -[Unreleased]: https://github.com/FreeElephants/json-api-dto/compare/0.0.1...HEAD +[Unreleased]: https://github.com/FreeElephants/json-api-dto/compare/0.0.2...HEAD +[0.0.2]: https://github.com/FreeElephants/json-api-dto/releases/tag/0.0.2 [0.0.1]: https://github.com/FreeElephants/json-api-dto/releases/tag/0.0.1 diff --git a/src/FreeElephants/JsonApi/DTO/AbstractCollection.php b/src/FreeElephants/JsonApi/DTO/AbstractCollection.php new file mode 100644 index 0000000..bc5fce9 --- /dev/null +++ b/src/FreeElephants/JsonApi/DTO/AbstractCollection.php @@ -0,0 +1,19 @@ +getDataItemClassName(); + $this->data[] = new $dataItemClassName($item); + } + } + + abstract public function getDataItemClassName(): string; +} diff --git a/src/FreeElephants/JsonApi/DTO/AbstractDocument.php b/src/FreeElephants/JsonApi/DTO/AbstractDocument.php index 8ec1210..2a40df1 100644 --- a/src/FreeElephants/JsonApi/DTO/AbstractDocument.php +++ b/src/FreeElephants/JsonApi/DTO/AbstractDocument.php @@ -7,28 +7,20 @@ /** * @property AbstractResourceObject|mixed $data */ -abstract class AbstractDocument +abstract class AbstractDocument extends TopLevel { - final public function __construct(array $data) + final public function __construct(array $payload) { $concreteClass = new \ReflectionClass($this); $dataProperty = $concreteClass->getProperty('data'); /** @var \ReflectionNamedType $reflectionType */ $reflectionType = $dataProperty->getType(); $dataClassName = $reflectionType->getName(); - $this->data = new $dataClassName($data['data']); - } - - /** - * @param MessageInterface $httpMessage - * @return static - */ - public static function fromHttpMessage(MessageInterface $httpMessage): self - { - $httpMessage->getBody()->rewind(); - $rawJson = $httpMessage->getBody()->getContents(); - $decodedJson = json_decode($rawJson, true); - - return new static($decodedJson); + if ($dataClassName !== 'array') { + $data = new $dataClassName($payload['data']); + } else { + throw new \UnexpectedValueException('`data` property must be typed, for array of resources use AbstractCollection instead ' . self::class); + } + $this->data = $data; } } diff --git a/src/FreeElephants/JsonApi/DTO/TopLevel.php b/src/FreeElephants/JsonApi/DTO/TopLevel.php new file mode 100644 index 0000000..8ce1676 --- /dev/null +++ b/src/FreeElephants/JsonApi/DTO/TopLevel.php @@ -0,0 +1,25 @@ +getBody()->rewind(); + $rawJson = $httpMessage->getBody()->getContents(); + $decodedJson = json_decode($rawJson, true); + + return new static($decodedJson); + } +} diff --git a/tests/FreeElephants/JsonApi/DTO/CollectionTest.php b/tests/FreeElephants/JsonApi/DTO/CollectionTest.php new file mode 100644 index 0000000..298e739 --- /dev/null +++ b/tests/FreeElephants/JsonApi/DTO/CollectionTest.php @@ -0,0 +1,50 @@ +getBody()->write(<<assertCount(1, $collectionDto->data); + $this->assertSame('123', $collectionDto->data[0]->id); + $this->assertSame('foo', $collectionDto->data[0]->type); + } +} diff --git a/tests/FreeElephants/JsonApi/DTO/Example/SomeCollectionDocument.php b/tests/FreeElephants/JsonApi/DTO/Example/SomeCollectionDocument.php new file mode 100644 index 0000000..e9b1d40 --- /dev/null +++ b/tests/FreeElephants/JsonApi/DTO/Example/SomeCollectionDocument.php @@ -0,0 +1,19 @@ +