File tree Expand file tree Collapse file tree 7 files changed +132
-18
lines changed
src/FreeElephants/JsonApi/DTO
tests/FreeElephants/JsonApi/DTO Expand file tree Collapse file tree 7 files changed +132
-18
lines changed Original file line number Diff line number Diff line change 11name : CI
22
3- on : push
3+ on :
4+ - push
5+ - pull_request
46
57jobs :
68 php-tests :
Original file line number Diff line number Diff line change @@ -6,10 +6,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66
77## [ Unreleased]
88
9+ ## [ 0.0.2] - 2025-03-14
10+
11+ ### Added
12+ - AbstractCollection for handle array of resources in data field
13+ - Exception on pass array as data into AbstractDocument constructor
14+
915## [ 0.0.1] - 2025-03-13
1016
1117### Added
1218- Extract all DTO types from FreeElephants/json-api-php-toolkit to this project
1319
14- [ Unreleased ] : https://github.com/FreeElephants/json-api-dto/compare/0.0.1...HEAD
20+ [ Unreleased ] : https://github.com/FreeElephants/json-api-dto/compare/0.0.2...HEAD
21+ [ 0.0.2 ] : https://github.com/FreeElephants/json-api-dto/releases/tag/0.0.2
1522[ 0.0.1 ] : https://github.com/FreeElephants/json-api-dto/releases/tag/0.0.1
Original file line number Diff line number Diff line change 1+ <?php
2+ declare (strict_types=1 );
3+
4+ namespace FreeElephants \JsonApi \DTO ;
5+
6+ abstract class AbstractCollection extends TopLevel
7+ {
8+ public array $ data = [];
9+
10+ final public function __construct (array $ payload = [])
11+ {
12+ foreach ($ payload ['data ' ] as $ item ) {
13+ $ dataItemClassName = $ this ->getDataItemClassName ();
14+ $ this ->data [] = new $ dataItemClassName ($ item );
15+ }
16+ }
17+
18+ abstract public function getDataItemClassName (): string ;
19+ }
Original file line number Diff line number Diff line change 77/**
88 * @property AbstractResourceObject|mixed $data
99 */
10- abstract class AbstractDocument
10+ abstract class AbstractDocument extends TopLevel
1111{
12- final public function __construct (array $ data )
12+ final public function __construct (array $ payload )
1313 {
1414 $ concreteClass = new \ReflectionClass ($ this );
1515 $ dataProperty = $ concreteClass ->getProperty ('data ' );
1616 /** @var \ReflectionNamedType $reflectionType */
1717 $ reflectionType = $ dataProperty ->getType ();
1818 $ dataClassName = $ reflectionType ->getName ();
19- $ this ->data = new $ dataClassName ($ data ['data ' ]);
20- }
21-
22- /**
23- * @param MessageInterface $httpMessage
24- * @return static
25- */
26- public static function fromHttpMessage (MessageInterface $ httpMessage ): self
27- {
28- $ httpMessage ->getBody ()->rewind ();
29- $ rawJson = $ httpMessage ->getBody ()->getContents ();
30- $ decodedJson = json_decode ($ rawJson , true );
31-
32- return new static ($ decodedJson );
19+ if ($ dataClassName !== 'array ' ) {
20+ $ data = new $ dataClassName ($ payload ['data ' ]);
21+ } else {
22+ throw new \UnexpectedValueException ('`data` property must be typed, for array of resources use AbstractCollection instead ' . self ::class);
23+ }
24+ $ this ->data = $ data ;
3325 }
3426}
Original file line number Diff line number Diff line change 1+ <?php
2+ declare (strict_types=1 );
3+
4+ namespace FreeElephants \JsonApi \DTO ;
5+
6+ use Psr \Http \Message \MessageInterface ;
7+
8+ /**
9+ * @property AbstractResourceObject|AbstractResourceObject[] $data
10+ */
11+ abstract class TopLevel
12+ {
13+ /**
14+ * @param MessageInterface $httpMessage
15+ * @return static
16+ */
17+ public static function fromHttpMessage (MessageInterface $ httpMessage ): self
18+ {
19+ $ httpMessage ->getBody ()->rewind ();
20+ $ rawJson = $ httpMessage ->getBody ()->getContents ();
21+ $ decodedJson = json_decode ($ rawJson , true );
22+
23+ return new static ($ decodedJson );
24+ }
25+ }
Original file line number Diff line number Diff line change 1+ <?php
2+ declare (strict_types=1 );
3+
4+ namespace FreeElephants \JsonApi \DTO ;
5+
6+ use FreeElephants \JsonApi \AbstractTestCase ;
7+ use FreeElephants \JsonApi \DTO \Example \SomeCollectionDocument ;
8+ use Nyholm \Psr7 \ServerRequest ;
9+
10+ class CollectionTest extends AbstractTestCase
11+ {
12+ public function testCollectionFromHttpMessage (): void
13+ {
14+ $ request = new ServerRequest ('GET ' , '/foos ' );
15+ $ request ->getBody ()->write (<<<JSON
16+ {
17+ "data": [
18+ {
19+ "id": "123",
20+ "type": "foo",
21+ "attributes": {
22+ "foo": "bar",
23+ "date": "2012-04-23T18:25:43.511Z",
24+ "nested": {
25+ "someNestedStructure": {
26+ "someKey": "someValue"
27+ }
28+ }
29+ },
30+ "relationships": {
31+ "baz": {
32+ "data": {
33+ "type": "bazs",
34+ "id": "baz-id"
35+ }
36+ }
37+ }
38+ }
39+ ]
40+ }
41+ JSON
42+ );
43+
44+ $ collectionDto = SomeCollectionDocument::fromHttpMessage ($ request );
45+
46+ $ this ->assertCount (1 , $ collectionDto ->data );
47+ $ this ->assertSame ('123 ' , $ collectionDto ->data [0 ]->id );
48+ $ this ->assertSame ('foo ' , $ collectionDto ->data [0 ]->type );
49+ }
50+ }
Original file line number Diff line number Diff line change 1+ <?php
2+ declare (strict_types=1 );
3+
4+ namespace FreeElephants \JsonApi \DTO \Example ;
5+
6+ use FreeElephants \JsonApi \DTO \AbstractCollection ;
7+ use FreeElephants \JsonApi \DTO \AbstractResourceObject ;
8+
9+ class SomeCollectionDocument extends AbstractCollection
10+ {
11+ public function getDataItemClassName (): string
12+ {
13+ return DataItemResourceObject::class;
14+ }
15+ }
16+
17+ class DataItemResourceObject extends AbstractResourceObject
18+ {
19+ }
You can’t perform that action at this time.
0 commit comments