Skip to content

Commit 066e47b

Browse files
committed
fix: Resolve nested relations
1 parent d4b9e01 commit 066e47b

File tree

2 files changed

+103
-11
lines changed

2 files changed

+103
-11
lines changed

src/Resolver/StoryResolver.php

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,38 @@
2424
public function resolve(array $target, array $relations): array
2525
{
2626
$relationMap = [];
27+
$seen = [];
2728

2829
foreach ($relations as $relation) {
2930
Assert::keyExists($relation, 'uuid');
3031
Assert::uuid($relation['uuid']);
3132
$relationMap[$relation['uuid']] = $relation;
3233
}
3334

34-
foreach ($target as &$value) {
35-
if (\is_string($value) && \array_key_exists($value, $relationMap)) {
36-
$value = $relationMap[$value];
35+
return $this->doResolve($target, $relationMap, []);
36+
}
3737

38-
continue;
39-
}
38+
private function doResolve(array $target, array $relationMap, array $seen): array
39+
{
40+
foreach ($target as $key => $value) {
41+
if (\is_string($value) && isset($relationMap[$value])) {
42+
if (\in_array($value, $seen, true)) {
43+
continue;
44+
}
4045

41-
if (\is_array($value) && \array_key_exists('id', $value) && \array_key_exists($value['id'], $relationMap)) {
42-
$value = $relationMap[$value['id']];
46+
$seen[] = $value;
47+
$target[$key] = $this->doResolve($relationMap[$value], $relationMap, $seen);
48+
} elseif (\is_array($value) && isset($value['id'], $relationMap[$value['id']])) {
49+
$id = $value['id'];
4350

44-
continue;
45-
}
51+
if (\in_array($id, $seen, true)) {
52+
continue;
53+
}
4654

47-
if (\is_array($value)) {
48-
$value = $this->resolve($value, $relations);
55+
$seen[] = $id;
56+
$target[$key] = $this->doResolve($relationMap[$id], $relationMap, $seen);
57+
} elseif (\is_array($value)) {
58+
$target[$key] = $this->doResolve($value, $relationMap, $seen);
4959
}
5060
}
5161

tests/Unit/Resolver/StoryResolverTest.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,86 @@ public function resolveReplacesMultiLinkWithLinkPayload(): void
188188

189189
self::assertSame($expected, $resolver->resolve($story, $references));
190190
}
191+
192+
#[Test]
193+
public function resolveRecursive(): void
194+
{
195+
$resolver = new StoryResolver();
196+
197+
$faker = self::faker();
198+
199+
$story = [
200+
'name' => $faker->word(),
201+
'content' => [
202+
'uuid' => $faker->uuid(),
203+
'reference' => $cUuid = $faker->uuid(),
204+
'some_field' => $faker->word(),
205+
],
206+
];
207+
208+
$references = [
209+
$b = [
210+
'uuid' => $bUuid = $faker->uuid(),
211+
'name' => $faker->word(),
212+
'another_field' => $faker->sentence(),
213+
],
214+
$c = [
215+
'uuid' => $cUuid,
216+
'name' => $faker->word(),
217+
'some_field' => [
218+
'test' => $bUuid,
219+
],
220+
],
221+
];
222+
223+
$expected = $story;
224+
$expected['content']['reference'] = $c;
225+
$expected['content']['reference']['some_field']['test'] = $b;
226+
227+
self::assertSame($expected, $resolver->resolve($story, $references));
228+
}
229+
230+
#[Test]
231+
public function resolveWithManyNestedRels(): void
232+
{
233+
$resolver = new StoryResolver();
234+
235+
$faker = self::faker();
236+
237+
$story = [
238+
'name' => $faker->word(),
239+
'content' => [
240+
'uuid' => $faker->uuid(),
241+
'reference' => $cUuid = $faker->uuid(),
242+
'some_field' => $faker->word(),
243+
],
244+
];
245+
246+
$references = [
247+
$a = [
248+
'uuid' => $aUuid = $faker->uuid,
249+
'name' => $faker->word(),
250+
],
251+
$b = [
252+
'uuid' => $bUuid = $faker->uuid(),
253+
'name' => $faker->word(),
254+
'another_field' => $faker->sentence(),
255+
'field' => $aUuid,
256+
],
257+
$c = [
258+
'uuid' => $cUuid,
259+
'name' => $faker->word(),
260+
'some_field' => [
261+
'test' => $bUuid,
262+
],
263+
],
264+
];
265+
266+
$expected = $story;
267+
$expected['content']['reference'] = $c;
268+
$expected['content']['reference']['some_field']['test'] = $b;
269+
$expected['content']['reference']['some_field']['test']['field'] = $a;
270+
271+
self::assertSame($expected, $resolver->resolve($story, $references));
272+
}
191273
}

0 commit comments

Comments
 (0)