Skip to content

Commit c49b781

Browse files
committed
feat: implement With helpers
1 parent 01f5c61 commit c49b781

File tree

3 files changed

+147
-20
lines changed

3 files changed

+147
-20
lines changed

src/JsonApiCollection.php

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
namespace Ark4ne\JsonApi\Resource;
44

55
use Ark4ne\JsonApi\Resource\Concerns\AsRelationship;
6+
use Ark4ne\JsonApi\Resource\Support\With;
67
use Illuminate\Http\Resources\Json\JsonResource;
78
use Illuminate\Http\Resources\Json\ResourceCollection;
8-
use Illuminate\Support\Arr;
99

1010
class JsonApiCollection extends ResourceCollection implements Resourceable
1111
{
@@ -32,40 +32,27 @@ public function toArray($request, bool $minimal = false): array
3232
{
3333
$data = [];
3434

35-
$this->with = collect($this->with)->toArray();
35+
$base = collect($this->with)->toArray();
3636
foreach ($this->collection as $resource) {
3737
$data[] = $resource->toArray($request, $minimal);
3838

3939
if ($resource instanceof JsonResource) {
4040
$with = collect($resource->with($request))->toArray();
41+
4142
if ($minimal) {
4243
unset($with['included']);
4344
}
44-
foreach ($with as $key => $value) {
45-
$this->with[$key] = array_merge_recursive(
46-
$this->with[$key] ?? [],
47-
$value
48-
);
49-
}
45+
46+
$base = With::merge($base, $with);
5047
}
5148
}
49+
$this->with = $base;
5250

5351
return $data;
5452
}
5553

5654
public function with($request)
5755
{
58-
return collect($this->with)
59-
->map(static function ($value) {
60-
if (is_iterable($value)) {
61-
$value = collect($value)->all();
62-
$isAssoc = Arr::isAssoc($value);
63-
$value = array_unique($value, SORT_REGULAR);
64-
return $isAssoc ? $value : array_values($value);
65-
}
66-
return $value;
67-
})
68-
->filter()
69-
->toArray();
56+
return With::wash($this->with);
7057
}
7158
}

src/Support/With.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Ark4ne\JsonApi\Resource\Support;
4+
5+
use Illuminate\Support\Arr;
6+
7+
class With
8+
{
9+
public static function merge(iterable $base, iterable $with): array
10+
{
11+
$base = collect($base)->toArray();
12+
13+
foreach (collect($with)->toArray() as $key => $value) {
14+
$base[$key] = array_merge_recursive(
15+
$base[$key] ?? [],
16+
$value
17+
);
18+
}
19+
20+
return self::uniqueRecursive($base);
21+
}
22+
23+
public static function wash(iterable $with): array
24+
{
25+
return collect(self::uniqueRecursive($with))
26+
->filter()
27+
->toArray();
28+
}
29+
30+
private static function uniqueRecursive($value)
31+
{
32+
return array_map(static function ($value) {
33+
if (is_iterable($value)) {
34+
$value = collect($value)->all();
35+
$isAssoc = Arr::isAssoc($value);
36+
$value = array_unique($value, SORT_REGULAR);
37+
return self::uniqueRecursive($isAssoc ? $value : array_values($value));
38+
}
39+
40+
return $value;
41+
}, collect($value)->all());
42+
}
43+
}

tests/Unit/Support/WithTest.php

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
namespace Test\Unit\Support;
4+
5+
use Ark4ne\JsonApi\Resource\Support\With;
6+
use Test\TestCase;
7+
8+
class WithTest extends TestCase
9+
{
10+
public function mergeProvider()
11+
{
12+
return [
13+
// [expected, base, with]
14+
[[], [], []],
15+
[['foo' => []], ['foo' => []], []],
16+
[['foo' => []], [], ['foo' => []]],
17+
[['foo' => []], ['foo' => []], ['foo' => []]],
18+
[['foo' => ['bar']], ['foo' => ['bar']], ['foo' => ['bar']]],
19+
[['foo' => ['bar', 'baz']], ['foo' => ['bar']], ['foo' => ['bar', 'baz']]],
20+
[
21+
['foo' => ['bar' => ['baz' => [1, 2]]]],
22+
['foo' => ['bar' => ['baz' => [1]]]],
23+
['foo' => ['bar' => ['baz' => [2]]]]
24+
],
25+
[
26+
[
27+
'included' => [
28+
['id' => 1, 'attributes' => ['a' => 1]],
29+
['id' => 2, 'attributes' => ['a' => 2]]
30+
]
31+
],
32+
[
33+
'included' => [
34+
['id' => 1, 'attributes' => ['a' => 1]],
35+
]
36+
],
37+
[
38+
'included' => [
39+
['id' => 2, 'attributes' => ['a' => 2]]
40+
]
41+
]
42+
],
43+
[
44+
[
45+
'included' => [
46+
['id' => 1, 'attributes' => ['a' => 1]],
47+
]
48+
],
49+
[
50+
'included' => [
51+
['id' => 1, 'attributes' => ['a' => 1]],
52+
]
53+
],
54+
[
55+
'included' => [
56+
['id' => 1, 'attributes' => ['a' => 1]]
57+
]
58+
]
59+
]
60+
];
61+
}
62+
63+
/**
64+
* @dataProvider mergeProvider
65+
*/
66+
public function testMerge($expected, $base, $with)
67+
{
68+
$this->assertEquals($expected, With::merge($base, $with));
69+
}
70+
71+
public function washProvider()
72+
{
73+
return [
74+
// [expected, with]
75+
[[], []],
76+
[[], ['foo' => []]],
77+
[['foo' => [1]], ['foo' => [1, 1, 1]]],
78+
[
79+
[
80+
'included' => [['id' => 1, 'attributes' => []]]
81+
],
82+
[
83+
'included' => [['id' => 1, 'attributes' => []]],
84+
'meta' => []
85+
],
86+
],
87+
];
88+
}
89+
90+
/**
91+
* @dataProvider washProvider
92+
*/
93+
public function testWash($expected, $base)
94+
{
95+
$this->assertEquals($expected, With::wash($base));
96+
}
97+
}

0 commit comments

Comments
 (0)