diff --git a/src/Resolver/StoryResolver.php b/src/Resolver/StoryResolver.php index 1027b89..651241f 100644 --- a/src/Resolver/StoryResolver.php +++ b/src/Resolver/StoryResolver.php @@ -31,24 +31,30 @@ public function resolve(array $target, array $relations): array $relationMap[$relation['uuid']] = $relation; } - foreach ($target as &$value) { - if (\is_string($value) && \array_key_exists($value, $relationMap)) { - $value = $relationMap[$value]; - continue; - } + // Resolve relations within the relation map first + $this->doResolve($relationMap, $relationMap); - if (\is_array($value) && \array_key_exists('id', $value) && \array_key_exists($value['id'], $relationMap)) { - $value = $relationMap[$value['id']]; + // Then resolve relations in the main target + $this->doResolve($target, $relationMap); + + return $target; + } + private function doResolve(array &$target, array &$relationMap): void + { + foreach ($target as $key => &$value) { + if ('uuid' === $key) { continue; } - if (\is_array($value)) { - $value = $this->resolve($value, $relations); + if (\is_string($value) && isset($relationMap[$value])) { + $value = $relationMap[$value]; + } elseif (\is_array($value) && isset($value['id'], $relationMap[$value['id']])) { + $value = $relationMap[$value['id']]; + } elseif (\is_array($value)) { + $this->doResolve($value, $relationMap); } } - - return $target; } } diff --git a/tests/Unit/Resolver/StoryResolverTest.php b/tests/Unit/Resolver/StoryResolverTest.php index 8690eb2..9926cdc 100644 --- a/tests/Unit/Resolver/StoryResolverTest.php +++ b/tests/Unit/Resolver/StoryResolverTest.php @@ -188,4 +188,121 @@ public function resolveReplacesMultiLinkWithLinkPayload(): void self::assertSame($expected, $resolver->resolve($story, $references)); } + + #[Test] + public function resolveRecursive(): void + { + $resolver = new StoryResolver(); + + $faker = self::faker(); + + $story = [ + 'name' => $faker->word(), + 'content' => [ + 'uuid' => $faker->uuid(), + 'reference' => $cUuid = $faker->uuid(), + 'some_field' => $faker->word(), + ], + ]; + + $references = [ + $b = [ + 'uuid' => $bUuid = $faker->uuid(), + 'name' => $faker->word(), + 'another_field' => $faker->sentence(), + ], + $c = [ + 'uuid' => $cUuid, + 'name' => $faker->word(), + 'some_field' => [ + 'test' => $bUuid, + ], + ], + ]; + + $expected = $story; + $expected['content']['reference'] = $c; + $expected['content']['reference']['some_field']['test'] = $b; + + self::assertSame($expected, $resolver->resolve($story, $references)); + } + + #[Test] + public function resolveWithManyNestedRels(): void + { + $resolver = new StoryResolver(); + + $faker = self::faker(); + + $story = [ + 'name' => $faker->word(), + 'content' => [ + 'uuid' => $faker->uuid(), + 'reference' => $cUuid = $faker->uuid(), + 'some_field' => $faker->word(), + ], + ]; + + $references = [ + $a = [ + 'uuid' => $aUuid = $faker->uuid(), + 'name' => $faker->word(), + ], + $b = [ + 'uuid' => $bUuid = $faker->uuid(), + 'name' => $faker->word(), + 'another_field' => $faker->sentence(), + 'field' => $aUuid, + ], + $c = [ + 'uuid' => $cUuid, + 'name' => $faker->word(), + 'some_field' => [ + 'test' => $bUuid, + ], + ], + ]; + + $expected = $story; + $expected['content']['reference'] = $c; + $expected['content']['reference']['some_field']['test'] = $b; + $expected['content']['reference']['some_field']['test']['field'] = $a; + + self::assertSame($expected, $resolver->resolve($story, $references)); + } + + #[Test] + public function resolveMustNeverResolveUuidOfStory(): void + { + $resolver = new StoryResolver(); + + $faker = self::faker(); + + $story = [ + 'name' => $faker->word(), + 'content' => [ + 'uuid' => $uuid = $faker->uuid(), + 'reference' => $referenceUuid = $faker->uuid(), + 'some_field' => $faker->word(), + ], + ]; + + $references = [ + $a = [ + 'uuid' => $referenceUuid, + 'name' => $faker->word(), + 'another_field' => $faker->sentence(), + ], + $b = [ + 'uuid' => $uuid, + 'name' => $faker->word(), + 'another_field' => $faker->sentence(), + ], + ]; + + $expected = $story; + $expected['content']['reference'] = $a; + + self::assertSame($expected, $resolver->resolve($story, $references)); + } }