Skip to content

Commit

Permalink
Merge pull request #67 from swisnl/feature/issue-66-unset-relation-us…
Browse files Browse the repository at this point in the history
…ing-itemhydrator

Unset relation when null (singular) or empty array (plural)
  • Loading branch information
JaZo authored Nov 18, 2019
2 parents ac2105b + 359336d commit d83ca25
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
9 changes: 9 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,10 @@ $attributes = [
'name' => 'Björn Brala',
'homepage' => 'https://github.com/bbrala',
],
'co-author' => null,
'date' => '2018-12-02 15:26:32',
'content' => 'JSON:API was originally drafted in May 2013 by Yehuda Katz...',
'media' => [],
'tags' => [
1,
15,
Expand All @@ -399,6 +401,12 @@ echo json_encode($itemDocument, JSON_PRETTY_PRINT);
"id": "f1a775ef-9407-40ba-93ff-7bd737888dc6"
}
},
"co-author": {
"data": null
},
"media": {
"data": []
},
"tags": {
"data": [{
"type": "tag",
Expand Down Expand Up @@ -426,6 +434,7 @@ echo json_encode($itemDocument, JSON_PRETTY_PRINT);

As you can see in this example, relations can be hydrated by id, or by an associative array with an id and more attributes.
If the item is hydrated using an associative array, it will be included in the resulting json unless `setOmitIncluded(true)` is called on the relation.
You can unset a relation by passing `null` for singular relations or an empty array for plural relations.

N.B. Morph relations require a 'type' attribute to be present in the data in order to know which type of item should be created.

Expand Down
12 changes: 12 additions & 0 deletions src/ItemHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use Illuminate\Support\Str;
use Swis\JsonApi\Client\Exceptions\HydrationException;
use Swis\JsonApi\Client\Interfaces\ItemInterface;
use Swis\JsonApi\Client\Interfaces\ManyRelationInterface;
use Swis\JsonApi\Client\Interfaces\OneRelationInterface;
use Swis\JsonApi\Client\Interfaces\TypeMapperInterface;
use Swis\JsonApi\Client\Relations\HasManyRelation;
use Swis\JsonApi\Client\Relations\HasOneRelation;
Expand Down Expand Up @@ -76,6 +78,16 @@ protected function fillRelations(ItemInterface $item, array $attributes): void

$relation = $this->getRelationFromItem($item, $availableRelation);

// The relation should be unset
if (
($relation instanceof OneRelationInterface && $attributes[$availableRelation] === null) ||
($relation instanceof ManyRelationInterface && $attributes[$availableRelation] === [])
) {
$relation->dissociate();

return;
}

// It is a valid relation
if ($relation instanceof HasOneRelation) {
$this->hydrateHasOneRelation($relation, $attributes[$availableRelation]);
Expand Down
88 changes: 88 additions & 0 deletions tests/ItemHydratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,28 @@ public function it_hydrates_hasone_relationships_with_attributes()
$this->assertArrayHasKey('hasone_relation', $item->toJsonApiArray()['relationships']);
}

/**
* @test
*/
public function it_dissociates_hasone_relationships_when_null()
{
$data = [
'hasone_relation' => null,
];

$item = new WithRelationshipItem();
$item = $this->getItemHydrator()->hydrate($item, $data);

/** @var \Swis\JsonApi\Client\Relations\HasOneRelation $hasOne */
$hasOne = $item->getRelation('hasone_relation');
$this->assertInstanceOf(HasOneRelation::class, $hasOne);

$this->assertNull($hasOne->getIncluded());

$this->assertArrayHasKey('hasone_relation', $item->toJsonApiArray()['relationships']);
$this->assertNull($item->toJsonApiArray()['relationships']['hasone_relation']['data']);
}

/**
* @test
*/
Expand Down Expand Up @@ -174,6 +196,28 @@ public function it_hydrates_hasmany_relationships_with_attributes()
$this->assertArrayHasKey('hasmany_relation', $item->toJsonApiArray()['relationships']);
}

/**
* @test
*/
public function it_dissociates_hasmany_relationships_when_empty_array()
{
$data = [
'hasmany_relation' => [],
];

$item = new WithRelationshipItem();
$item = $this->getItemHydrator()->hydrate($item, $data);

/** @var \Swis\JsonApi\Client\Relations\HasManyRelation $hasMany */
$hasMany = $item->getRelation('hasmany_relation');
$this->assertInstanceOf(HasManyRelation::class, $hasMany);

$this->assertTrue($hasMany->getIncluded()->isEmpty());

$this->assertArrayHasKey('hasmany_relation', $item->toJsonApiArray()['relationships']);
$this->assertSame([], $item->toJsonApiArray()['relationships']['hasmany_relation']['data']);
}

/**
* @test
*/
Expand Down Expand Up @@ -228,6 +272,28 @@ public function it_hydrates_morphto_relationships_with_attributes()
$this->assertArrayHasKey('morphto_relation', $item->toJsonApiArray()['relationships']);
}

/**
* @test
*/
public function it_dissociates_morphto_relationships_when_null()
{
$data = [
'morphto_relation' => null,
];

$item = new WithRelationshipItem();
$item = $this->getItemHydrator()->hydrate($item, $data);

/** @var \Swis\JsonApi\Client\Relations\MorphToRelation $morphTo */
$morphTo = $item->getRelation('morphto_relation');
$this->assertInstanceOf(MorphToRelation::class, $morphTo);

$this->assertNull($morphTo->getIncluded());

$this->assertArrayHasKey('morphto_relation', $item->toJsonApiArray()['relationships']);
$this->assertNull($item->toJsonApiArray()['relationships']['morphto_relation']['data']);
}

/**
* @test
*/
Expand Down Expand Up @@ -350,6 +416,28 @@ public function it_hydrates_morphtomany_relationships_with_attributes()
$this->assertArrayHasKey('morphtomany_relation', $item->toJsonApiArray()['relationships']);
}

/**
* @test
*/
public function it_dissociates_morphtomany_relationships_when_empty_array()
{
$data = [
'morphtomany_relation' => [],
];

$item = new WithRelationshipItem();
$item = $this->getItemHydrator()->hydrate($item, $data);

/** @var \Swis\JsonApi\Client\Relations\MorphToManyRelation $morphToMany */
$morphToMany = $item->getRelation('morphtomany_relation');
$this->assertInstanceOf(MorphToManyRelation::class, $morphToMany);

$this->assertTrue($morphToMany->getIncluded()->isEmpty());

$this->assertArrayHasKey('morphtomany_relation', $item->toJsonApiArray()['relationships']);
$this->assertSame([], $item->toJsonApiArray()['relationships']['morphtomany_relation']['data']);
}

/**
* @test
*/
Expand Down

0 comments on commit d83ca25

Please sign in to comment.