Skip to content

Commit 5e94195

Browse files
committed
feat: autoload improve inclusion
1 parent dd5b5d2 commit 5e94195

File tree

3 files changed

+70
-17
lines changed

3 files changed

+70
-17
lines changed

src/Resources/Concerns/Relationships.php

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Ark4ne\JsonApi\Descriptors\Resolver;
66
use Ark4ne\JsonApi\Resources\Relationship;
7+
use Ark4ne\JsonApi\Resources\Skeleton;
78
use Ark4ne\JsonApi\Support\Arr;
89
use Ark4ne\JsonApi\Support\Includes;
910
use Ark4ne\JsonApi\Support\Values;
@@ -43,31 +44,49 @@ protected function toRelationships(Request $request): iterable
4344
*/
4445
public function requestedRelationshipsLoad(Request $request): array
4546
{
46-
$schema = self::schema($request);
47+
return Arr::flatDot($this->requestedRelationshipsLoadFromSchema($request, self::schema($request)));
48+
}
49+
50+
private function requestedRelationshipsLoadFromSchema(Request $request, Skeleton $schema): array
51+
{
52+
$loads = [];
4753

48-
$walk = static function ($schema) use (&$walk, $request) {
49-
$loads = [];
54+
foreach ($schema->loads as $name => $load) {
55+
if ($load && Includes::include($request, $name)) {
56+
$include = Includes::through($name, fn() => $this->requestedRelationshipsLoadFromSchema($request, $schema->relationships[$name]));
5057

51-
foreach ($schema->loads as $name => $load) {
52-
if ($load && Includes::include($request, $name)) {
53-
$include = Includes::through($name, static fn() => $walk($schema->relationships[$name]));
58+
$apply = static function ($load, string $pre = null) use (&$loads, &$apply) {
5459
foreach ((array)$load as $key => $value) {
5560
if (is_string($value)) {
56-
$loads[$value] = $include;
61+
$loads["$pre.$value"] = [];
5762
} elseif (is_string($key)) {
58-
$loads[$key] = $value;
59-
foreach (Arr::flatDot($include, $key) as $inc => $item) {
60-
$loads[$inc] = $item;
63+
if (is_array($value)) {
64+
$apply($value, "$pre.$key");
65+
} else {
66+
$loads["$pre.$key"] = $value;
6167
}
6268
}
6369
}
70+
};
71+
72+
foreach ((array)$load as $key => $value) {
73+
if (is_string($value)) {
74+
$loads[$value] = $include;
75+
} elseif (is_string($key)) {
76+
if (is_array($value)) {
77+
$apply($value, $key);
78+
} else {
79+
$loads[$key] = $value;
80+
}
81+
foreach (Arr::flatDot($include, $key) as $inc => $item) {
82+
$loads[$inc] = $item;
83+
}
84+
}
6485
}
6586
}
87+
}
6688

67-
return $loads;
68-
};
69-
70-
return Arr::flatDot($walk($schema));
89+
return $loads;
7190
}
7291

7392
/**

src/Traits/HasRelationLoad.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77

88
trait HasRelationLoad
99
{
10-
/** @var bool|string|array<string, callable(Builder|Relation):mixed>|array<array-key, string> */
10+
/** @var bool|string|array<string, callable(Builder|Relation):mixed>|array<array-key, string|string[]|mixed> */
1111
protected bool|string|array $load = false;
1212

1313
/**
14-
* @param bool|string|array<string, callable(Builder|Relation):mixed>|array<array-key, string> $load
14+
* @param bool|string|array<string, callable(Builder|Relation):mixed>|array<array-key, string|string[]|mixed> $load
1515
* @return $this
1616
*/
1717
public function withLoad(bool|string|array $load): static
@@ -21,7 +21,7 @@ public function withLoad(bool|string|array $load): static
2121
}
2222

2323
/**
24-
* @return bool|string|array<string, callable(Builder|Relation):mixed>|array<array-key, string>
24+
* @return bool|string|array<string, callable(Builder|Relation):mixed>|array<array-key, string|string[]|mixed>
2525
*/
2626
public function load(): bool|string|array
2727
{

tests/Unit/Resources/Concerns/RelationshipsTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use Ark4ne\JsonApi\Resources\Concerns\Relationships;
66
use Ark4ne\JsonApi\Resources\Relationship;
77
use Ark4ne\JsonApi\Resources\Resourceable;
8+
use Ark4ne\JsonApi\Resources\Skeleton;
9+
use Ark4ne\JsonApi\Support\Arr;
810
use Ark4ne\JsonApi\Support\Includes;
911
use Illuminate\Http\Request;
1012
use Illuminate\Http\Resources\Json\JsonResource;
@@ -259,6 +261,38 @@ public function toRelationships(Request $request): iterable
259261
], $actual);
260262
}
261263

264+
public function testRequestedRelationshipsLoadFromSchema()
265+
{
266+
$r1 = new Skeleton('r1', 'r1');
267+
$r1->loads = [
268+
'_2' => 'r2',
269+
'_3' => 'r3'
270+
];
271+
272+
$r2 = new Skeleton('r2', 'r2');
273+
$r2->loads = ['_3' => ['r3' => ['r1']]];
274+
275+
$r3 = new Skeleton('r3', 'r3');
276+
$r3->loads = ['_1' => 'r1'];
277+
278+
$r1->relationships['_2'] = $r2;
279+
$r2->relationships['_3'] = $r3;
280+
$r3->relationships['_1'] = $r1;
281+
282+
$model = Stub::model(['id' => 1]);
283+
$resource = new class($model) extends JsonResource {
284+
use Relationships;
285+
};
286+
287+
$request = new Request([
288+
'include' => '_2._3'
289+
]);
290+
291+
$actual = Reflect::invoke($resource, 'requestedRelationshipsLoadFromSchema', $request, $r1);
292+
293+
$this->assertEquals(['r2.r3.r1' => []], Arr::flatDot($actual));
294+
}
295+
262296
private function getStub()
263297
{
264298
$resource = new class {

0 commit comments

Comments
 (0)