Skip to content

Commit

Permalink
Merge pull request #290 from wells/feature/json-api-collection-relati…
Browse files Browse the repository at this point in the history
…onship-links

Feature/json api collection relationship links
  • Loading branch information
philsturgeon authored Jul 19, 2016
2 parents d2be7f6 + f357131 commit d064765
Show file tree
Hide file tree
Showing 2 changed files with 250 additions and 5 deletions.
19 changes: 14 additions & 5 deletions src/Serializer/JsonApiSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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;
Expand All @@ -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];

Expand Down
236 changes: 236 additions & 0 deletions test/Serializer/JsonApiSerializerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit d064765

Please sign in to comment.