Skip to content

Commit 3340456

Browse files
committed
feat: applyWhen condition can be a closure
1 parent 1a9551f commit 3340456

File tree

5 files changed

+86
-33
lines changed

5 files changed

+86
-33
lines changed

src/Descriptors/Relations/RelationMissing.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
use Closure;
77
use Illuminate\Http\Resources\MissingValue;
88

9+
/**
10+
* @internal
11+
*/
912
final class RelationMissing extends Relation
1013
{
1114
private function __construct(string $related, Closure|string|null $relation)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Ark4ne\JsonApi\Descriptors\Relations;
4+
5+
use Ark4ne\JsonApi\Resources\Relationship;
6+
use Closure;
7+
8+
/**
9+
* @internal
10+
*/
11+
final class RelationRaw extends Relation
12+
{
13+
private function __construct(string $related, Closure|string|null $relation)
14+
{
15+
parent::__construct($related, $relation);
16+
}
17+
18+
protected function value(Closure $value): Relationship
19+
{
20+
return ($this->relation)();
21+
}
22+
23+
public static function fromRelationship(Relationship $relationship): self
24+
{
25+
return new self($relationship->getResource(), fn() => $relationship);
26+
}
27+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Ark4ne\JsonApi\Descriptors\Values;
4+
5+
use Closure;
6+
7+
/**
8+
* @internal
9+
* @template T
10+
* @extends Value<T>
11+
*/
12+
class ValueRaw extends Value
13+
{
14+
public function __construct(
15+
null|string|Closure $attribute,
16+
protected mixed $raw
17+
) {
18+
parent::__construct($attribute);
19+
}
20+
21+
public function value(mixed $of): mixed
22+
{
23+
return $this->raw;
24+
}
25+
}

src/Resources/Concerns/ConditionallyLoadsAttributes.php

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
namespace Ark4ne\JsonApi\Resources\Concerns;
44

5-
use Ark4ne\JsonApi\Descriptors\Relations\Relation;
6-
use Ark4ne\JsonApi\Descriptors\Relations\RelationMissing;
5+
use Ark4ne\JsonApi\Descriptors\Describer;
6+
use Ark4ne\JsonApi\Descriptors\Relations\RelationRaw;
7+
use Ark4ne\JsonApi\Descriptors\Values\ValueRaw;
78
use Ark4ne\JsonApi\Resources\Relationship;
89
use Ark4ne\JsonApi\Support\Fields;
910
use Ark4ne\JsonApi\Support\Includes;
1011
use Ark4ne\JsonApi\Support\Supported;
1112
use Ark4ne\JsonApi\Support\Values;
13+
use Closure;
1214
use Illuminate\Http\Request;
1315
use Illuminate\Http\Resources\MergeValue;
1416
use Illuminate\Http\Resources\MissingValue;
@@ -48,27 +50,23 @@ protected function whenIncluded(Request $request, string $type, mixed $value)
4850
}
4951

5052
/**
51-
* @param bool $condition
53+
* @param bool|Closure():boolean $condition
5254
* @param iterable<array-key, mixed> $data
5355
*
5456
* @return \Illuminate\Http\Resources\MergeValue
5557
*/
56-
protected function applyWhen(bool $condition, iterable $data): MergeValue
58+
protected function applyWhen(bool|Closure $condition, iterable $data): MergeValue
5759
{
58-
if ($condition) {
59-
return new MergeValue($data);
60-
}
61-
62-
return new MergeValue(collect($data)->map(function ($raw) {
63-
if ($raw instanceof Relationship) {
64-
return RelationMissing::fromRelationship($raw);
65-
}
66-
67-
if ($raw instanceof Relation) {
68-
return $raw->when(false);
60+
return new MergeValue(collect($data)->map(function ($raw, $key) use ($condition) {
61+
if ($raw instanceof Describer) {
62+
$value = $raw;
63+
} elseif ($raw instanceof Relationship) {
64+
$value = RelationRaw::fromRelationship($raw);
65+
} else {
66+
$value = new ValueRaw($key, $raw);
6967
}
7068

71-
return new MissingValue();
69+
return $value->when(fn () => value($condition));
7270
}));
7371
}
7472

@@ -111,7 +109,7 @@ public function whenHas($attribute, $value = null, $default = null)
111109
*/
112110
public function unless($condition, $value, $default = null)
113111
{
114-
if (Supported::$whenHas) {
112+
if (Supported::$unless) {
115113
// @phpstan-ignore-next-line
116114
return parent::unless($condition, $value, $default);
117115
}

tests/Unit/Resources/Concerns/ConditionallyLoadsAttributesTest.php

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
namespace Test\Unit\Resources\Concerns;
44

5-
use Ark4ne\JsonApi\Descriptors\Relations\RelationMissing;
65
use Ark4ne\JsonApi\Descriptors\Relations\RelationOne;
6+
use Ark4ne\JsonApi\Descriptors\Relations\RelationRaw;
77
use Ark4ne\JsonApi\Descriptors\Values\ValueMixed;
8+
use Ark4ne\JsonApi\Descriptors\Values\ValueRaw;
89
use Ark4ne\JsonApi\Resources\Concerns\ConditionallyLoadsAttributes;
910
use Ark4ne\JsonApi\Resources\Relationship;
10-
use Illuminate\Database\Eloquent\Model;
1111
use Illuminate\Http\Request;
1212
use Illuminate\Http\Resources\Json\JsonResource;
1313
use Illuminate\Http\Resources\MergeValue;
@@ -75,16 +75,16 @@ public function testApplyWhen()
7575
'missing.2' => 123,
7676
]);
7777
$this->assertEquals(new MergeValue([
78-
'missing.1' => new MissingValue,
79-
'missing.2' => new MissingValue,
78+
'missing.1' => (new ValueRaw('missing.1', 'abc'))->when(fn () => false),
79+
'missing.2' => (new ValueRaw('missing.2', 123))->when(fn () => false),
8080
]), $actual);
8181
$actual = Reflect::invoke($stub, 'applyWhen', true, [
8282
'present.1' => 'abc',
8383
'present.2' => 123,
8484
]);
8585
$this->assertEquals(new MergeValue([
86-
'present.1' => 'abc',
87-
'present.2' => 123,
86+
'present.1' => (new ValueRaw('present.1', 'abc'))->when(fn () => true),
87+
'present.2' => (new ValueRaw('present.2', 123))->when(fn () => true),
8888
]), $actual);
8989
$actual = Reflect::invoke($stub, 'applyWhen', true, [
9090
'present.1' => (new ValueMixed(fn() => 'abc')),
@@ -94,11 +94,11 @@ public function testApplyWhen()
9494
'present.5' => (new Relationship(UserResource::class, fn() => null)),
9595
]);
9696
$this->assertEquals(new MergeValue([
97-
'present.1' => (new ValueMixed(fn() => 'abc')),
98-
'present.2' => (new ValueMixed(fn() => 123)),
99-
'present.3' => (new RelationOne('present', fn() => 'abc')),
100-
'present.4' => (new RelationOne('present', fn() => 123)),
101-
'present.5' => (new Relationship(UserResource::class, fn() => null)),
97+
'present.1' => (new ValueMixed(fn() => 'abc'))->when(fn () => true),
98+
'present.2' => (new ValueMixed(fn() => 123))->when(fn () => true),
99+
'present.3' => (new RelationOne('present', fn() => 'abc'))->when(fn () => true),
100+
'present.4' => (new RelationOne('present', fn() => 123))->when(fn () => true),
101+
'present.5' => RelationRaw::fromRelationship(new Relationship(UserResource::class, fn() => null))->when(fn () => true),
102102
]), $actual);
103103
$actual = Reflect::invoke($stub, 'applyWhen', false, [
104104
'missing.1' => (new ValueMixed(fn() => 'abc')),
@@ -108,11 +108,11 @@ public function testApplyWhen()
108108
'missing.5' => (new Relationship(UserResource::class, fn() => null)),
109109
]);
110110
$this->assertEquals(new MergeValue([
111-
'missing.1' => new MissingValue,
112-
'missing.2' => new MissingValue,
113-
'missing.3' => (new RelationOne('present', fn() => 'abc'))->when(false),
114-
'missing.4' => (new RelationOne('present', fn() => 123))->when(false),
115-
'missing.5' => RelationMissing::fromRelationship((new Relationship(UserResource::class, fn() => null))),
111+
'missing.1' => (new ValueMixed(fn() => 'abc'))->when(fn () => false),
112+
'missing.2' => (new ValueMixed(fn() => 123))->when(fn () => false),
113+
'missing.3' => (new RelationOne('present', fn() => 'abc'))->when(fn () => false),
114+
'missing.4' => (new RelationOne('present', fn() => 123))->when(fn () => false),
115+
'missing.5' => RelationRaw::fromRelationship(new Relationship(UserResource::class, fn() => null))->when(fn () => false),
116116
]), $actual);
117117
}
118118

0 commit comments

Comments
 (0)