From ca6c4f72e273c53e7750b96d6f26595fd7e97fe6 Mon Sep 17 00:00:00 2001 From: Holger Veltrup <92872893+sitepark-veltrup@users.noreply.github.com> Date: Mon, 2 Sep 2024 15:52:56 +0200 Subject: [PATCH] fix: circular parent reference detection (#34) --- src/Loader/SiteKitResourceHierarchyLoader.php | 12 +++++++++++- .../SiteKitResourceHierarchyLoaderTest.php | 16 ++++++++++++++++ .../withDefaultRoot/dir/b.php | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Loader/SiteKitResourceHierarchyLoader.php b/src/Loader/SiteKitResourceHierarchyLoader.php index 4f2c43c..4430bff 100644 --- a/src/Loader/SiteKitResourceHierarchyLoader.php +++ b/src/Loader/SiteKitResourceHierarchyLoader.php @@ -44,8 +44,18 @@ public function cleanup(): void public function loadRoot(ResourceLocation $location): Resource { $resource = $this->resourceLoader->load($location); + $loaded = [$resource->location]; while (!$this->isRoot($resource)) { - $resource = $this->loadPrimaryParentResource($resource); + $parent = $this->loadPrimaryParentResource($resource); + if (in_array($parent->location, $loaded, true)) { + $loaded[] = $parent->location; + throw new InvalidResourceException( + $resource->toLocation(), + 'circular parent reference detected: ' . implode(' -> ', $loaded), + ); + } + $resource = $parent; + $loaded[] = $resource->location; } return $resource; diff --git a/test/Loader/SiteKitResourceHierarchyLoaderTest.php b/test/Loader/SiteKitResourceHierarchyLoaderTest.php index 91167f7..aafeb22 100644 --- a/test/Loader/SiteKitResourceHierarchyLoaderTest.php +++ b/test/Loader/SiteKitResourceHierarchyLoaderTest.php @@ -120,6 +120,22 @@ public function testLoadRoot(): void ); } + public function testLoadRootWithSelfRecursion(): void + { + $this->expectException(InvalidResourceException::class); + $this->hierarchyLoader->loadRoot( + ResourceLocation::of('/withSelfRecursion.php'), + ); + } + + public function testLoadRootWithRecursion(): void + { + $this->expectException(InvalidResourceException::class); + $this->hierarchyLoader->loadRoot( + ResourceLocation::of('/withRecursionA.php'), + ); + } + public function testIsRoot(): void { $root = TestResourceFactory::create([]); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php index 83fcf18..0b8c2b0 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php @@ -5,7 +5,7 @@ use Atoolo\Resource\Test\TestResourceFactory; return TestResourceFactory::create([ - 'url' => '/dir/a.php', + 'url' => '/dir/b.php', 'id' => 'a', 'name' => 'a', 'locale' => 'en_US',