From f3571314250e6a1d100c851f7550770a0498aa22 Mon Sep 17 00:00:00 2001 From: Brian Wells Date: Thu, 24 Mar 2016 07:28:23 -0600 Subject: [PATCH] Added JSON-API serializer collection links with tests. --- src/Serializer/JsonApiSerializer.php | 19 +- test/Serializer/JsonApiSerializerTest.php | 236 ++++++++++++++++++++++ 2 files changed, 250 insertions(+), 5 deletions(-) diff --git a/src/Serializer/JsonApiSerializer.php b/src/Serializer/JsonApiSerializer.php index fc841161..092c2b3b 100644 --- a/src/Serializer/JsonApiSerializer.php +++ b/src/Serializer/JsonApiSerializer.php @@ -326,7 +326,7 @@ protected function fillRelationships($data, $relationships) } } else { // Single resource foreach ($relationships as $key => $relationship) { - $data = $this->FillRelationshipAsSingleResource($data, $relationship, $key); + $data = $this->fillRelationshipAsSingleResource($data, $relationship, $key); } } @@ -448,14 +448,23 @@ private function createRootObjects($data) * * @param $data * @param $relationship - * @param $nestedDepth + * @param $key * * @return array */ - private function fillRelationshipAsCollection($data, $relationship, $nestedDepth) + private function fillRelationshipAsCollection($data, $relationship, $key) { foreach ($relationship as $index => $relationshipData) { - $data['data'][$index]['relationships'][$nestedDepth] = $relationshipData; + $data['data'][$index]['relationships'][$key] = $relationshipData; + + if ($this->shouldIncludeLinks()) { + $data['data'][$index]['relationships'][$key] = array_merge([ + 'links' => [ + 'self' => "{$this->baseUrl}/{$data['data'][$index]['type']}/{$data['data'][$index]['id']}/relationships/$key", + 'related' => "{$this->baseUrl}/{$data['data'][$index]['type']}/{$data['data'][$index]['id']}/$key", + ], + ], $data['data'][$index]['relationships'][$key]); + } } return $data; @@ -469,7 +478,7 @@ private function fillRelationshipAsCollection($data, $relationship, $nestedDepth * * @return array */ - private function FillRelationshipAsSingleResource($data, $relationship, $key) + private function fillRelationshipAsSingleResource($data, $relationship, $key) { $data['data']['relationships'][$key] = $relationship[0]; diff --git a/test/Serializer/JsonApiSerializerTest.php b/test/Serializer/JsonApiSerializerTest.php index b759b957..4cd7f024 100644 --- a/test/Serializer/JsonApiSerializerTest.php +++ b/test/Serializer/JsonApiSerializerTest.php @@ -1235,6 +1235,242 @@ public function testSerializingItemResourceWithLinksForHasManyRelationship() $this->assertSame($expectedJson, $scope->toJson()); } + public function testSerializingCollectionResourceWithLinksForHasOneRelationship() + { + $baseUrl = 'http://example.com'; + $this->manager->setSerializer(new JsonApiSerializer($baseUrl)); + $this->manager->parseIncludes('author'); + + $bookData = [ + [ + 'id' => 1, + 'title' => 'Foo', + 'year' => '1991', + '_author' => [ + 'id' => 1, + 'name' => 'Dave', + ], + ], + [ + 'id' => 2, + 'title' => 'Bar', + 'year' => '1991', + '_author' => [ + 'id' => 1, + 'name' => 'Dave', + ], + ], + ]; + + $resource = new Collection($bookData, new JsonApiBookTransformer(), 'books'); + + $scope = new Scope($this->manager, $resource); + + $expected = [ + 'data' => [ + [ + 'type' => 'books', + 'id' => '1', + 'attributes' => [ + 'title' => 'Foo', + 'year' => 1991, + ], + 'relationships' => [ + 'author' => [ + 'links' => [ + 'self' => 'http://example.com/books/1/relationships/author', + 'related' => 'http://example.com/books/1/author', + ], + 'data' => [ + 'type' => 'people', + 'id' => '1', + ], + ], + ], + 'links' => [ + 'self' => 'http://example.com/books/1', + ], + ], + [ + 'type' => 'books', + 'id' => '2', + 'attributes' => [ + 'title' => 'Bar', + 'year' => 1991, + ], + 'relationships' => [ + 'author' => [ + 'links' => [ + 'self' => 'http://example.com/books/2/relationships/author', + 'related' => 'http://example.com/books/2/author', + ], + 'data' => [ + 'type' => 'people', + 'id' => '1', + ], + ], + ], + 'links' => [ + 'self' => 'http://example.com/books/2', + ], + ], + ], + 'included' => [ + [ + 'type' => 'people', + 'id' => '1', + 'attributes' => [ + 'name' => 'Dave', + ], + 'links' => [ + 'self' => 'http://example.com/people/1', + ], + ], + ], + ]; + + $this->assertEquals($expected, $scope->toArray()); + + $expectedJson = '{"data":[{"type":"books","id":"1","attributes":{"title":"Foo","year":1991},"links":{"self":"http:\/\/example.com\/books\/1"},"relationships":{"author":{"links":{"self":"http:\/\/example.com\/books\/1\/relationships\/author","related":"http:\/\/example.com\/books\/1\/author"},"data":{"type":"people","id":"1"}}}},{"type":"books","id":"2","attributes":{"title":"Bar","year":1991},"links":{"self":"http:\/\/example.com\/books\/2"},"relationships":{"author":{"links":{"self":"http:\/\/example.com\/books\/2\/relationships\/author","related":"http:\/\/example.com\/books\/2\/author"},"data":{"type":"people","id":"1"}}}}],"included":[{"type":"people","id":"1","attributes":{"name":"Dave"},"links":{"self":"http:\/\/example.com\/people\/1"}}]}'; + $this->assertSame($expectedJson, $scope->toJson()); + } + + public function testSerializingCollectionResourceWithLinksForHasManyRelationship() + { + $baseUrl = 'http://example.com'; + $this->manager->setSerializer(new JsonApiSerializer($baseUrl)); + $this->manager->parseIncludes('published'); + + $authorData = [ + [ + 'id' => 1, + 'name' => 'Dave', + '_published' => [ + [ + 'id' => 1, + 'title' => 'Foo', + 'year' => '1991', + ], + [ + 'id' => 2, + 'title' => 'Bar', + 'year' => '2015', + ], + ], + ], + [ + 'id' => 2, + 'name' => 'Bill', + '_published' => [ + [ + 'id' => 1, + 'title' => 'Foo', + 'year' => '1991', + ], + [ + 'id' => 2, + 'title' => 'Bar', + 'year' => '2015', + ], + ], + ], + ]; + + $resource = new Collection($authorData, new JsonApiAuthorTransformer(), 'people'); + + $scope = new Scope($this->manager, $resource); + + $expected = [ + 'data' => [ + [ + 'type' => 'people', + 'id' => '1', + 'attributes' => [ + 'name' => 'Dave', + ], + 'relationships' => [ + 'published' => [ + 'links' => [ + 'self' => 'http://example.com/people/1/relationships/published', + 'related' => 'http://example.com/people/1/published', + ], + 'data' => [ + [ + 'type' => 'books', + 'id' => 1, + ], + [ + 'type' => 'books', + 'id' => 2, + ], + ], + ], + ], + 'links' => [ + 'self' => 'http://example.com/people/1', + ], + ], + [ + 'type' => 'people', + 'id' => '2', + 'attributes' => [ + 'name' => 'Bill', + ], + 'relationships' => [ + 'published' => [ + 'links' => [ + 'self' => 'http://example.com/people/2/relationships/published', + 'related' => 'http://example.com/people/2/published', + ], + 'data' => [ + [ + 'type' => 'books', + 'id' => 1, + ], + [ + 'type' => 'books', + 'id' => 2, + ], + ], + ], + ], + 'links' => [ + 'self' => 'http://example.com/people/2', + ], + ], + ], + 'included' => [ + [ + 'type' => 'books', + 'id' => '1', + 'attributes' => [ + 'title' => 'Foo', + 'year' => 1991, + ], + 'links' => [ + 'self' => 'http://example.com/books/1', + ], + ], + [ + 'type' => 'books', + 'id' => '2', + 'attributes' => [ + 'title' => 'Bar', + 'year' => 2015, + ], + 'links' => [ + 'self' => 'http://example.com/books/2', + ], + ], + ], + ]; + + $this->assertEquals($expected, $scope->toArray()); + + $expectedJson = '{"data":[{"type":"people","id":"1","attributes":{"name":"Dave"},"links":{"self":"http:\/\/example.com\/people\/1"},"relationships":{"published":{"links":{"self":"http:\/\/example.com\/people\/1\/relationships\/published","related":"http:\/\/example.com\/people\/1\/published"},"data":[{"type":"books","id":"1"},{"type":"books","id":"2"}]}}},{"type":"people","id":"2","attributes":{"name":"Bill"},"links":{"self":"http:\/\/example.com\/people\/2"},"relationships":{"published":{"links":{"self":"http:\/\/example.com\/people\/2\/relationships\/published","related":"http:\/\/example.com\/people\/2\/published"},"data":[{"type":"books","id":"1"},{"type":"books","id":"2"}]}}}],"included":[{"type":"books","id":"1","attributes":{"title":"Foo","year":1991},"links":{"self":"http:\/\/example.com\/books\/1"}},{"type":"books","id":"2","attributes":{"title":"Bar","year":2015},"links":{"self":"http:\/\/example.com\/books\/2"}}]}'; + $this->assertSame($expectedJson, $scope->toJson()); + } + /** * @expectedException InvalidArgumentException * @expectedExceptionMessage JSON API resource objects MUST have a valid id