From db7ef18da15d1a9ca8e9839b314aafbf49d4d604 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Wed, 13 Mar 2024 10:26:46 +0100 Subject: [PATCH 01/31] feat: add ResourceHierarchyLoader::findRecursive() and new CachedResourceLoader --- src/Loader/CachedResourceLoader.php | 49 +++++++++++++ src/Loader/SiteKitResourceHierarchyLoader.php | 46 ++++++++++++ src/ResourceHierarchyLoader.php | 24 +++++++ test/Loader/CachedResourceLoaderTest.php | 71 +++++++++++++++++++ .../SiteKitResourceHierarchyLoaderTest.php | 31 ++++++++ .../SiteKitResourceHierarchyLoader/a.php | 15 +++- 6 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 src/Loader/CachedResourceLoader.php create mode 100644 test/Loader/CachedResourceLoaderTest.php diff --git a/src/Loader/CachedResourceLoader.php b/src/Loader/CachedResourceLoader.php new file mode 100644 index 0000000..bb14543 --- /dev/null +++ b/src/Loader/CachedResourceLoader.php @@ -0,0 +1,49 @@ + + */ + private array $cache = []; + public function __construct( + private readonly ResourceLoader $resourceLoader, + ) { + } + + /** + * @throws InvalidResourceException + * @throws ResourceNotFoundException + */ + public function load(string $location): Resource + { + if (isset($this->cache[$location])) { + return $this->cache[$location]; + } + + $resource = $this->resourceLoader->load($location); + $this->cache[$location] = $resource; + return $resource; + } + + public function exists(string $location): bool + { + if (isset($this->cache[$location])) { + return true; + } + return $this->resourceLoader->exists($location); + } +} diff --git a/src/Loader/SiteKitResourceHierarchyLoader.php b/src/Loader/SiteKitResourceHierarchyLoader.php index 0ea34e9..6603bb9 100644 --- a/src/Loader/SiteKitResourceHierarchyLoader.php +++ b/src/Loader/SiteKitResourceHierarchyLoader.php @@ -82,6 +82,52 @@ public function loadChildren(string $location): array return $children; } + /** + * Walks the tree of resources starting from the given location and calls + * the given function for each resource. Returns the resource where the + * callable returns true. + * + * The callable function expects the following parameters: + * - array of Resource: the path to the current resource. Don't contains + * the current resource. + * - Resource: the current resource + * + * The callable function should return true if the current resource is the + * one we are looking for. + * + * @param callable(Resource[], Resource): bool $fn + * @param Resource[] $parentPath + * @throws InvalidResourceException + * @throws ResourceNotFoundException + */ + public function findRecursive( + string $location, + callable $fn, + array $parentPath = [] + ): ?Resource { + + $resource = $this->resourceLoader->load($location); + + if ($fn($parentPath, $resource) === true) { + return $resource; + } + + $childrenLocationList = $this->getChildrenLocationList($resource); + foreach ($childrenLocationList as $childLocation) { + $parentPathForChild = array_merge($parentPath, [$resource]); + $result = $this->findRecursive( + $childLocation, + $fn, + $parentPathForChild + ); + if ($result !== null) { + return $result; + } + } + + return null; + } + /** * @throws InvalidResourceException if no primary parent can be found * @throws ResourceNotFoundException diff --git a/src/ResourceHierarchyLoader.php b/src/ResourceHierarchyLoader.php index 120f185..3aa9945 100644 --- a/src/ResourceHierarchyLoader.php +++ b/src/ResourceHierarchyLoader.php @@ -49,4 +49,28 @@ public function loadPath(string $location): array; * @throws ResourceNotFoundException */ public function loadChildren(string $location): array; + + /** + * Walks the tree of resources starting from the given location and calls + * the given function for each resource. Returns the resource where the + * callable returns true. + * + * The callable function expects the following parameters: + * - array of Resource: the path to the current resource. Don't contains + * the current resource. + * - Resource: the current resource + * + * The callable function should return true if the current resource is the + * one we are looking for. + * + * @param callable(Resource[], Resource): bool $fn + * @param Resource[] $parentPath + * @throws InvalidResourceException + * @throws ResourceNotFoundException + */ + public function findRecursive( + string $location, + callable $fn, + array $parentPath = [] + ): ?Resource; } diff --git a/test/Loader/CachedResourceLoaderTest.php b/test/Loader/CachedResourceLoaderTest.php new file mode 100644 index 0000000..f5bf601 --- /dev/null +++ b/test/Loader/CachedResourceLoaderTest.php @@ -0,0 +1,71 @@ +createStub(Resource::class); + $loader = $this->createMock(ResourceLoader::class); + $loader->expects($this->once()) + ->method('load') + ->with('test') + ->willReturn($resource); + $cachedLoader = new CachedResourceLoader($loader); + $cachedLoader->load('test'); // cache warmup + + $this->assertEquals( + $resource, + $cachedLoader->load('test'), + 'Resource should be loaded from cache' + ); + } + + public function testExistsUncached(): void + { + $loader = $this->createMock(ResourceLoader::class); + $loader->expects($this->once()) + ->method('exists') + ->with('test') + ->willReturn(true); + $cachedLoader = new CachedResourceLoader($loader); + + $this->assertTrue( + $cachedLoader->exists('test'), + 'Resource should be test from cache' + ); + } + + public function testExistsCached(): void + { + + $resource = $this->createStub(Resource::class); + $loader = $this->createMock(ResourceLoader::class); + $loader->expects($this->once()) + ->method('load') + ->with('test') + ->willReturn($resource); + $loader->expects($this->exactly(0)) + ->method('exists') + ->with('test') + ->willReturn(true); + + $cachedLoader = new CachedResourceLoader($loader); + $cachedLoader->load('test'); // cache warmup + + $this->assertTrue( + $cachedLoader->exists('test'), + 'Resource should be test from cache' + ); + } +} diff --git a/test/Loader/SiteKitResourceHierarchyLoaderTest.php b/test/Loader/SiteKitResourceHierarchyLoaderTest.php index 2974a85..21f7969 100644 --- a/test/Loader/SiteKitResourceHierarchyLoaderTest.php +++ b/test/Loader/SiteKitResourceHierarchyLoaderTest.php @@ -172,4 +172,35 @@ public function testLoadRootResourceFirstParentWithNonStringUrl(): void $this->expectException(InvalidResourceException::class); $this->hierarchyLoader->loadParent('/firstParentWithNonStringUrl.php'); } + + public function testFindRecursive(): void + { + $resource = $this->hierarchyLoader->findRecursive( + '/a.php', + static function ($path, $resource) { + return $resource->getId() === 'c'; + } + ); + + $this->assertEquals( + 'c', + $resource->getId(), + 'unexpected resource' + ); + } + + public function testFindRecursiveNotFound(): void + { + $resource = $this->hierarchyLoader->findRecursive( + '/a.php', + static function ($path, $resource) { + return $resource->getId() === 'not-existing'; + } + ); + + $this->assertNull( + $resource, + 'resource should be null' + ); + } } diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php index f42eb0c..fe83764 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php @@ -7,5 +7,18 @@ 'a', 'a', '', - [] + [ + 'base' => [ + 'trees' => [ + 'category' => [ + 'children' => [ + 'b' => [ + 'id' => 'b', + 'url' => '/b.php' + ] + ] + ] + ] + ] + ] ); From 7ccc28e7caef9e3f620361cfd2a5e9e1265baa61 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 14 Mar 2024 09:45:22 +0100 Subject: [PATCH 02/31] feat: work in process --- composer.json | 5 +++++ src/Loader/ServerVarResourceBaseLocator.php | 24 +++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index d8f7264..9d5f077 100644 --- a/composer.json +++ b/composer.json @@ -43,6 +43,11 @@ }, "sort-packages": true }, + "extra": { + "branch-alias": { + "feature/find-in-hierarchy": "dev-main" + } + }, "scripts": { "post-install-cmd": "phive --no-progress install --force-accept-unsigned --trust-gpg-keys C00543248C87FB13,4AA394086372C20A,CF1A108D0E7AE720,51C67305FFC2E5C0", "analyse": [ diff --git a/src/Loader/ServerVarResourceBaseLocator.php b/src/Loader/ServerVarResourceBaseLocator.php index 1bdd7da..64fb263 100644 --- a/src/Loader/ServerVarResourceBaseLocator.php +++ b/src/Loader/ServerVarResourceBaseLocator.php @@ -5,27 +5,43 @@ namespace Atoolo\Resource\Loader; use Atoolo\Resource\ResourceBaseLocator; +use RuntimeException; class ServerVarResourceBaseLocator implements ResourceBaseLocator { + private ?string $resourceBase = null; + public function __construct( - private readonly string $variableName, - private readonly ?string $subDirectory = null + private readonly string $variableName ) { } public function locate(): string { + if ($this->resourceBase !== null) { + return $this->resourceBase; + } + if (empty($_SERVER[$this->variableName])) { throw new \RuntimeException( 'missing server variable ' . $this->variableName ); } - if ($this->subDirectory === null) { + $resourceLayoutResourceBase = $_SERVER[$this->variableName] . '/object'; + if (is_dir($resourceLayoutResourceBase)) { + $this->resourceBase = $resourceLayoutResourceBase; + return $resourceLayoutResourceBase; + } + + if (is_dir($_SERVER[$this->variableName])) { + $this->resourceBase = $_SERVER[$this->variableName]; return $_SERVER[$this->variableName]; } - return $_SERVER[$this->variableName] . '/' . $this->subDirectory; + throw new RuntimeException( + "Resource root directory not found: " . + $_SERVER[$this->variableName] + ); } } From 72a4ef1e473bd80f18d85c47fc7fbb1a37d6dbef Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 14 Mar 2024 09:50:35 +0100 Subject: [PATCH 03/31] docs: typo --- src/Loader/SiteKitResourceHierarchyLoader.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Loader/SiteKitResourceHierarchyLoader.php b/src/Loader/SiteKitResourceHierarchyLoader.php index 6603bb9..e3ee1e3 100644 --- a/src/Loader/SiteKitResourceHierarchyLoader.php +++ b/src/Loader/SiteKitResourceHierarchyLoader.php @@ -88,8 +88,8 @@ public function loadChildren(string $location): array * callable returns true. * * The callable function expects the following parameters: - * - array of Resource: the path to the current resource. Don't contains - * the current resource. + * - array of Resource: the path to the current resource. + * Does not contain the current resource * - Resource: the current resource * * The callable function should return true if the current resource is the From 80540ef9fb0b5310f0c4726f19f28c20b2147602 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 14 Mar 2024 09:55:15 +0100 Subject: [PATCH 04/31] refactor: create findRecursiveInternal for internal method signatur --- src/Loader/SiteKitResourceHierarchyLoader.php | 15 ++++++++++++--- src/ResourceHierarchyLoader.php | 3 +-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Loader/SiteKitResourceHierarchyLoader.php b/src/Loader/SiteKitResourceHierarchyLoader.php index e3ee1e3..e676259 100644 --- a/src/Loader/SiteKitResourceHierarchyLoader.php +++ b/src/Loader/SiteKitResourceHierarchyLoader.php @@ -96,14 +96,23 @@ public function loadChildren(string $location): array * one we are looking for. * * @param callable(Resource[], Resource): bool $fn - * @param Resource[] $parentPath * @throws InvalidResourceException * @throws ResourceNotFoundException */ public function findRecursive( string $location, callable $fn, - array $parentPath = [] + ): ?Resource { + return $this->findRecursiveInternal($location, $fn, []); + } + + /** + * @param Resource[] $parentPath + */ + private function findRecursiveInternal( + string $location, + callable $fn, + array $parentPath ): ?Resource { $resource = $this->resourceLoader->load($location); @@ -115,7 +124,7 @@ public function findRecursive( $childrenLocationList = $this->getChildrenLocationList($resource); foreach ($childrenLocationList as $childLocation) { $parentPathForChild = array_merge($parentPath, [$resource]); - $result = $this->findRecursive( + $result = $this->findRecursiveInternal( $childLocation, $fn, $parentPathForChild diff --git a/src/ResourceHierarchyLoader.php b/src/ResourceHierarchyLoader.php index 3aa9945..71a7f9e 100644 --- a/src/ResourceHierarchyLoader.php +++ b/src/ResourceHierarchyLoader.php @@ -70,7 +70,6 @@ public function loadChildren(string $location): array; */ public function findRecursive( string $location, - callable $fn, - array $parentPath = [] + callable $fn ): ?Resource; } From 3e022b93e3f9908a04e66f08d659c33a41541369 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 14 Mar 2024 10:09:26 +0100 Subject: [PATCH 05/31] refactor: remove $parentPath for findResource() callable --- src/Loader/SiteKitResourceHierarchyLoader.php | 25 ++++--------------- .../SiteKitResourceHierarchyLoaderTest.php | 4 +-- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/Loader/SiteKitResourceHierarchyLoader.php b/src/Loader/SiteKitResourceHierarchyLoader.php index e676259..92759ef 100644 --- a/src/Loader/SiteKitResourceHierarchyLoader.php +++ b/src/Loader/SiteKitResourceHierarchyLoader.php @@ -87,15 +87,13 @@ public function loadChildren(string $location): array * the given function for each resource. Returns the resource where the * callable returns true. * - * The callable function expects the following parameters: - * - array of Resource: the path to the current resource. - * Does not contain the current resource + * The callable function expects the following parameter: * - Resource: the current resource * * The callable function should return true if the current resource is the * one we are looking for. * - * @param callable(Resource[], Resource): bool $fn + * @param callable(Resource): bool $fn * @throws InvalidResourceException * @throws ResourceNotFoundException */ @@ -103,31 +101,18 @@ public function findRecursive( string $location, callable $fn, ): ?Resource { - return $this->findRecursiveInternal($location, $fn, []); - } - - /** - * @param Resource[] $parentPath - */ - private function findRecursiveInternal( - string $location, - callable $fn, - array $parentPath - ): ?Resource { $resource = $this->resourceLoader->load($location); - if ($fn($parentPath, $resource) === true) { + if ($fn($resource) === true) { return $resource; } $childrenLocationList = $this->getChildrenLocationList($resource); foreach ($childrenLocationList as $childLocation) { - $parentPathForChild = array_merge($parentPath, [$resource]); - $result = $this->findRecursiveInternal( + $result = $this->findRecursive( $childLocation, - $fn, - $parentPathForChild + $fn ); if ($result !== null) { return $result; diff --git a/test/Loader/SiteKitResourceHierarchyLoaderTest.php b/test/Loader/SiteKitResourceHierarchyLoaderTest.php index 21f7969..7183a49 100644 --- a/test/Loader/SiteKitResourceHierarchyLoaderTest.php +++ b/test/Loader/SiteKitResourceHierarchyLoaderTest.php @@ -177,7 +177,7 @@ public function testFindRecursive(): void { $resource = $this->hierarchyLoader->findRecursive( '/a.php', - static function ($path, $resource) { + static function ($resource) { return $resource->getId() === 'c'; } ); @@ -193,7 +193,7 @@ public function testFindRecursiveNotFound(): void { $resource = $this->hierarchyLoader->findRecursive( '/a.php', - static function ($path, $resource) { + static function ($resource) { return $resource->getId() === 'not-existing'; } ); From 0279cc82e352bf24842ef34546740faba8e9746d Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Wed, 20 Mar 2024 17:29:55 +0100 Subject: [PATCH 06/31] feat: lang support --- .githooks/commit-msg | 8 ++ composer.json | 8 +- src/Loader/CachedResourceLoader.php | 23 +-- src/Loader/SiteKitLoader.php | 108 +++++++++++--- src/Resource.php | 6 + src/ResourceChannel.php | 34 +++++ src/ResourceChannelFactory.php | 10 ++ src/ResourceHierarchyLoader.php | 3 +- src/ResourceLoader.php | 4 +- src/SiteKitResourceChannelFactory.php | 94 +++++++++++++ .../ServerVarResourceBaseLocatorTest.php | 57 ++++++-- test/Loader/SiteKitLoaderTest.php | 47 ++++++- test/ResourceTest.php | 22 +++ test/SiteKitResourceChannelFactoryTest.php | 133 ++++++++++++++++++ .../SiteKitLoader/missingLocaleResource.php | 26 ++++ .../SiteKitLoader/nonStringLocaleResource.php | 27 ++++ .../validResource.php.translations/en_US.php | 80 +++++++++++ .../withDefaultRoot/dir/a.php | 1 + .../withDefaultRoot/dir/b.php | 1 + .../withDefaultRoot/dir/c.php | 1 + .../withDefaultRoot/dir/index.php | 1 + .../withDefaultRoot/index.php | 1 + .../withHomeFlag/a.php | 1 + .../withHomeFlag/b.php | 1 + .../withHomeFlag/c.php | 1 + .../withoutRoot/a.php | 1 + .../SiteKitResourceHierarchyLoader/a.php | 1 + .../SiteKitResourceHierarchyLoader/b.php | 1 + .../SiteKitResourceHierarchyLoader/c.php | 1 + .../childrenWithInvalidData.php | 1 + .../firstParentWithNonStringUrl.php | 1 + .../firstParentWithoutUrl.php | 1 + .../primaryParentWithInvalidData.php | 1 + .../primaryParentWithNonStringUrl.php | 1 + .../primaryParentWithoutUrl.php | 1 + .../documentRootLayout/WEB-IES/context.php | 14 ++ .../invalid/context.php | 3 + .../resourceLayout/context.php | 14 ++ 38 files changed, 697 insertions(+), 42 deletions(-) create mode 100644 src/ResourceChannel.php create mode 100644 src/ResourceChannelFactory.php create mode 100644 src/SiteKitResourceChannelFactory.php create mode 100644 test/SiteKitResourceChannelFactoryTest.php create mode 100644 test/resources/Loader/SiteKitLoader/missingLocaleResource.php create mode 100644 test/resources/Loader/SiteKitLoader/nonStringLocaleResource.php create mode 100644 test/resources/Loader/SiteKitLoader/validResource.php.translations/en_US.php create mode 100644 test/resources/SiteKitResourceChannelFactory/documentRootLayout/WEB-IES/context.php create mode 100644 test/resources/SiteKitResourceChannelFactory/invalid/context.php create mode 100644 test/resources/SiteKitResourceChannelFactory/resourceLayout/context.php diff --git a/.githooks/commit-msg b/.githooks/commit-msg index b5c5f08..d7e7bb3 100755 --- a/.githooks/commit-msg +++ b/.githooks/commit-msg @@ -3,10 +3,18 @@ # Create a regex for a conventional commit. convetional_commit_regex="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z \-]+\))?!?: .+$" +# Accept Merge commits +merge_msg_regex="^Merge branch '.+'.+$" + # Get the commit message (the parameter we're given is just the path to the # temporary file which holds the message). commit_message=$(cat "$1") +if [[ "$commit_message" =~ $merge_msg_regex ]]; then + echo -e "\e[32mAccept Merge commits...\e[0m" + exit 0 +fi + # Check the message, if we match, all good baby. if [[ "$commit_message" =~ $convetional_commit_regex ]]; then echo -e "\e[32mCommit message meets Conventional Commit standards...\e[0m" diff --git a/composer.json b/composer.json index 9d5f077..34b90ed 100644 --- a/composer.json +++ b/composer.json @@ -10,8 +10,9 @@ } ], "require": { - "php": ">=8.1 <8.4.0" - }, + "php": ">=8.1 <8.4.0", + "ext-intl": "*" + }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "infection/infection": "^0.27.6", @@ -45,7 +46,8 @@ }, "extra": { "branch-alias": { - "feature/find-in-hierarchy": "dev-main" + "feature/find-in-hierarchy": "dev-main", + "feature/resource-channel" : "dev-main" } }, "scripts": { diff --git a/src/Loader/CachedResourceLoader.php b/src/Loader/CachedResourceLoader.php index bb14543..c8e8f61 100644 --- a/src/Loader/CachedResourceLoader.php +++ b/src/Loader/CachedResourceLoader.php @@ -28,22 +28,29 @@ public function __construct( * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function load(string $location): Resource + public function load(string $location, string $lang = ''): Resource { - if (isset($this->cache[$location])) { - return $this->cache[$location]; + $key = $this->getKey($location, $lang); + if (isset($this->cache[$key])) { + return $this->cache[$key]; } - $resource = $this->resourceLoader->load($location); - $this->cache[$location] = $resource; + $resource = $this->resourceLoader->load($location, $lang); + $this->cache[$key] = $resource; return $resource; } - public function exists(string $location): bool + public function exists(string $location, string $lang = ''): bool { - if (isset($this->cache[$location])) { + $key = $this->getKey($location, $lang); + if (isset($this->cache[$key])) { return true; } - return $this->resourceLoader->exists($location); + return $this->resourceLoader->exists($location, $lang); + } + + private function getKey(string $location, string $lang): string + { + return $lang . ':' . $location; } } diff --git a/src/Loader/SiteKitLoader.php b/src/Loader/SiteKitLoader.php index f2ab638..48fecb1 100644 --- a/src/Loader/SiteKitLoader.php +++ b/src/Loader/SiteKitLoader.php @@ -10,17 +10,32 @@ use Atoolo\Resource\Loader\SiteKit\LifecylceStub; use Atoolo\Resource\Resource; use Atoolo\Resource\ResourceBaseLocator; +use Atoolo\Resource\ResourceChannelFactory; use Atoolo\Resource\ResourceLoader; +use Error; +use Locale; +use ParseError; /** * ResourceLoader that loads resources created with SiteKit aggregators. - * @phpstan-type InitData array{id: int, name: string, objectType: string} + * @phpstan-type InitData array{ + * id: int, + * name: string, + * objectType: string, + * locale: string + * } * @phpstan-type ResourceData array{init: InitData} */ class SiteKitLoader implements ResourceLoader { + /** + * @var array|null + */ + private ?array $langLocaleMap = null; + public function __construct( - private readonly ResourceBaseLocator $baseLocator + private readonly ResourceBaseLocator $baseLocator, + private readonly ResourceChannelFactory $resourceChannel, ) { } @@ -28,40 +43,54 @@ public function __construct( * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function load(string $location): Resource + public function load(string $location, string $lang = ''): Resource { - $data = $this->loadRaw($location); + $data = $this->loadRaw($location, $lang); - $this->validateData($location, $data); + $data = $this->validateData($location, $data); $init = $data['init']; + $locale = $init['locale']; + $resourceLang = substr($locale, 0, 2); + return new Resource( $location, (string)$init['id'], $init['name'], $init['objectType'], + $resourceLang, $data ); } - public function exists(string $location): bool + + public function exists(string $location, string $lang = ''): bool { return file_exists( - $this->baseLocator->locate() - . DIRECTORY_SEPARATOR - . $location + $this->locationToFile($location, $lang) ); } + private function locationToFile(string $location, string $lang): string + { + $file = $this->baseLocator->locate() . '/' . $location; + $locale = $this->langToLocale($lang); + if (empty($locale)) { + return $file; + } + + return $file . '.translations/' . $locale . '.php'; + } + /** - * @return array $data + * @return array * @throws InvalidResourceException * @throws ResourceNotFoundException */ - private function loadRaw(string $location): array + private function loadRaw(string $location, string $lang): array { - $file = $this->baseLocator->locate() . '/' . $location; + $file = $this->locationToFile($location, $lang); /** * $context and $lifecycle must be defined here, because for the SiteKit @@ -83,15 +112,16 @@ private function loadRaw(string $location): array 'The resource should return an array' ); } + /* @var ResourceData $data */ return $data; - } catch (\ParseError $e) { + } catch (ParseError $e) { throw new InvalidResourceException( $location, $e->getMessage(), 0, $e ); - } catch (\Error $e) { + } catch (Error $e) { if (!file_exists($file)) { throw new ResourceNotFoundException( $location, @@ -112,12 +142,41 @@ private function loadRaw(string $location): array } } + private function langToLocale(string $lang): string + { + if (empty($lang)) { + return $lang; + } + + if ($this->langLocaleMap === null) { + $this->langLocaleMap = $this->createLangLocaleMap(); + } + + return $this->langLocaleMap[$lang] ?? ''; + } + /** - * @param array $data - * @return ($data is ResourceData ? void : never) + * @return array + */ + private function createLangLocaleMap(): array + { + $map = []; + $resourceChannel = $this->resourceChannel->create(); + foreach ( + $resourceChannel->translationLocales as $availableLocale + ) { + $primaryLang = Locale::getPrimaryLanguage($availableLocale); + $map[$primaryLang] = $availableLocale; + } + return $map; + } + + /** + * @param array $data + * @return ResourceData * @throws InvalidResourceException */ - private function validateData(string $location, array $data): void + private function validateData(string $location, array $data): array { /* @@ -169,5 +228,20 @@ private function validateData(string $location, array $data): void 'objectType field not a string' ); } + if (!isset($init['locale'])) { + throw new InvalidResourceException( + $location, + 'locale field missing' + ); + } + if (!is_string($init['locale'])) { + throw new InvalidResourceException( + $location, + 'locale field not a string' + ); + } + + /** @var ResourceData $data */ + return $data; } } diff --git a/src/Resource.php b/src/Resource.php index bc4acf2..96607ea 100644 --- a/src/Resource.php +++ b/src/Resource.php @@ -19,6 +19,7 @@ public function __construct( private readonly string $id, private readonly string $name, private readonly string $objectType, + private readonly string $lang, array $data, ) { $this->data = new DataBag($data); @@ -44,6 +45,11 @@ public function getObjectType(): string return $this->objectType; } + public function getLang(): string + { + return $this->lang; + } + public function getData(): DataBag { return $this->data; diff --git a/src/ResourceChannel.php b/src/ResourceChannel.php new file mode 100644 index 0000000..ab094a2 --- /dev/null +++ b/src/ResourceChannel.php @@ -0,0 +1,34 @@ +resourceChannel !== null) { + return $this->resourceChannel; + } + + $data = $this->loadContextPhpFile(); + + $searchIndex = str_replace( + '.', + '-', + $data['publisher']['anchor'] + ); + $this->resourceChannel = new ResourceChannel( + (string)$data['publisher']['id'], + $data['publisher']['name'], + $data['publisher']['anchor'], + $data['publisher']['serverName'], + $data['publisher']['preview'], + $data['publisher']['nature'], + $data['publisher']['locale'] ?? 'de_DE', + $data['publisher']['encoding'] ?? 'UTF-8', + $searchIndex, + $data['publisher']['translationLocales'] ?? [], + ); + + return $this->resourceChannel; + } + + /** + * @return ContextPhp + */ + private function loadContextPhpFile(): array + { + $contextPhpFile = $this->findContextPhpFile(); + $context = require $contextPhpFile; + if (!is_array($context)) { + throw new RuntimeException( + 'context.php must return an array' + ); + } + + /** @var ContextPhp $context */ + return $context; + } + private function findContextPhpFile(): string + { + $resourceBase = $this->resourceBaseLocator->locate(); + if (str_ends_with($resourceBase, '/object')) { + $contextPhpFile = dirname($resourceBase) . '/context.php'; + } else { + $contextPhpFile = $resourceBase . '/WEB-IES/context.php'; + } + if (!file_exists($contextPhpFile)) { + throw new RuntimeException( + 'context.php does not exists: ' . $contextPhpFile + ); + } + return $contextPhpFile; + } +} diff --git a/test/Loader/ServerVarResourceBaseLocatorTest.php b/test/Loader/ServerVarResourceBaseLocatorTest.php index b940ec6..01238aa 100644 --- a/test/Loader/ServerVarResourceBaseLocatorTest.php +++ b/test/Loader/ServerVarResourceBaseLocatorTest.php @@ -4,7 +4,6 @@ namespace Atoolo\Resource\Test\Loader; -use Atoolo\Resource\Loader\ResourceLayoutResourceBaseLocator; use Atoolo\Resource\Loader\ServerVarResourceBaseLocator; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -28,31 +27,53 @@ public function tearDown(): void $_SERVER = $this->saveServerState; } - public function testWithoutSubDirectory(): void + public function testWithDocumentRootLayout(): void { - $_SERVER['RESOURCE_ROOT'] = 'abc'; + $baseLocation = + __DIR__ . + '/../resources/Loader/ServerVarResourceBaseLocator' . + '/documentRootLayout'; + $_SERVER['RESOURCE_ROOT'] = $baseLocation; + $locator = new ServerVarResourceBaseLocator('RESOURCE_ROOT'); $this->assertEquals( - 'abc', + $baseLocation, $locator->locate(), 'unexpected resource base' ); } - public function testWithSubDirectory(): void + public function testWithResourceLayout(): void { - $_SERVER['RESOURCE_ROOT'] = 'abc'; + $baseLocation = + __DIR__ . + '/../resources/Loader/ServerVarResourceBaseLocator' . + '/resourceLayout'; + $_SERVER['RESOURCE_ROOT'] = $baseLocation; $locator = new ServerVarResourceBaseLocator( - 'RESOURCE_ROOT', - 'objects' + 'RESOURCE_ROOT' ); $this->assertEquals( - 'abc/objects', + $baseLocation . '/object', $locator->locate(), 'unexpected resource base' ); } + public function testWithInvalidDirectory(): void + { + $baseLocation = + __DIR__ . + '/../resources/Loader/ServerVarResourceBaseLocator' . + '/invalid'; + $_SERVER['RESOURCE_ROOT'] = $baseLocation; + $locator = new ServerVarResourceBaseLocator( + 'RESOURCE_ROOT' + ); + $this->expectException(RuntimeException::class); + $locator->locate(); + } + public function testWithMissingSeverVariable(): void { $locator = new ServerVarResourceBaseLocator('RESOURCE_ROOT'); @@ -60,4 +81,22 @@ public function testWithMissingSeverVariable(): void $this->expectException(RuntimeException::class); $locator->locate(); } + + public function testUseCache(): void + { + $baseLocation = + __DIR__ . + '/../resources/Loader/ServerVarResourceBaseLocator' . + '/documentRootLayout'; + $_SERVER['RESOURCE_ROOT'] = $baseLocation; + + $locator = new ServerVarResourceBaseLocator('RESOURCE_ROOT'); + $locator->locate(); + + $this->assertEquals( + $baseLocation, + $locator->locate(), + 'unexpected resource base' + ); + } } diff --git a/test/Loader/SiteKitLoaderTest.php b/test/Loader/SiteKitLoaderTest.php index 9a46da4..29d2aa1 100644 --- a/test/Loader/SiteKitLoaderTest.php +++ b/test/Loader/SiteKitLoaderTest.php @@ -9,6 +9,8 @@ use Atoolo\Resource\Loader\SiteKitLoader; use Atoolo\Resource\Loader\StaticResourceBaseLocator; use Atoolo\Resource\Resource; +use Atoolo\Resource\ResourceChannel; +use Atoolo\Resource\ResourceChannelFactory; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -20,8 +22,23 @@ class SiteKitLoaderTest extends TestCase protected function setUp(): void { $base = realpath(__DIR__ . '/../resources/Loader/SiteKitLoader'); + $channel = new ResourceChannel( + '1', + 'Test Channel', + 'test-www', + 'test-server', + false, + 'internet', + 'de_DE', + 'UTF-8', + 'test-www', + ['en_US'] + ); + $channelFactory = $this->createStub(ResourceChannelFactory::class); + $channelFactory->method('create')->willReturn($channel); $this->loader = new SiteKitLoader( - new StaticResourceBaseLocator($base) + new StaticResourceBaseLocator($base), + $channelFactory ); } @@ -31,6 +48,12 @@ public function testExists(): void $this->assertTrue($exists, 'resource should exist'); } + public function testExistsWithLang(): void + { + $exists = $this->loader->exists('validResource.php', 'en'); + $this->assertTrue($exists, 'resource should exist'); + } + public function testLoadValidResource(): void { $resource = $this->loader->load('validResource.php'); @@ -41,6 +64,16 @@ public function testLoadValidResource(): void ); } + public function testLoadValidResourceWithLang(): void + { + $resource = $this->loader->load('validResource.php', 'en'); + $this->assertEquals( + '1118', + $resource->getId(), + 'unexpected id' + ); + } + public function testLoadMissingLocation(): void { $this->expectException(ResourceNotFoundException::class); @@ -107,6 +140,18 @@ public function testLoadWithNonStringObjectType(): void $this->loader->load('nonStringObjectTypeResource.php'); } + public function testLoadWithMissingLocale(): void + { + $this->expectException(InvalidResourceException::class); + $this->loader->load('missingLocaleResource.php'); + } + + public function testLoadWithNonStringLocale(): void + { + $this->expectException(InvalidResourceException::class); + $this->loader->load('nonStringLocaleResource.php'); + } + public function testLoadWithNonArrayReturned(): void { $this->expectException(InvalidResourceException::class); diff --git a/test/ResourceTest.php b/test/ResourceTest.php index 3c1317f..709dd12 100644 --- a/test/ResourceTest.php +++ b/test/ResourceTest.php @@ -19,6 +19,7 @@ public function testGetLocation(): void '', '', '', + '', [] ); $this->assertEquals( @@ -35,6 +36,7 @@ public function testGetId(): void '123', '', '', + '', [] ); $this->assertEquals( @@ -51,6 +53,7 @@ public function testGetName(): void '', 'Content-Page', '', + '', [] ); $this->assertEquals( @@ -67,6 +70,7 @@ public function testGetObjectType(): void '', '', 'content', + '', [] ); $this->assertEquals( @@ -76,6 +80,23 @@ public function testGetObjectType(): void ); } + public function testGetLang(): void + { + $resource = new Resource( + '', + '', + '', + 'content', + 'en', + [] + ); + $this->assertEquals( + 'en', + $resource->getLang(), + 'unexpected lang' + ); + } + public function testGetData(): void { $resource = new Resource( @@ -83,6 +104,7 @@ public function testGetData(): void '', '', '', + '', ['field' => 'value'] ); $this->assertEquals( diff --git a/test/SiteKitResourceChannelFactoryTest.php b/test/SiteKitResourceChannelFactoryTest.php new file mode 100644 index 0000000..c13c36c --- /dev/null +++ b/test/SiteKitResourceChannelFactoryTest.php @@ -0,0 +1,133 @@ +createStub( + ResourceBaseLocator::class + ); + $resourceDir = __DIR__ . + '/resources/SiteKitResourceChannelFactory' . + '/resourceLayout/object'; + $resourceBaseLocator->method('locate') + ->willReturn($resourceDir); + + $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); + $channel = $factory->create(); + + $expected = new ResourceChannel( + '1', + 'Test', + 'test', + 'www.test.org', + true, + 'internet', + 'de_DE', + 'UTF-8', + 'test', + [] + ); + $this->assertEquals( + $expected, + $channel, + 'ResourceChannel does not match expected values' + ); + } + + public function testCreateCache(): void + { + $resourceBaseLocator = $this->createMock( + ResourceBaseLocator::class + ); + $resourceDir = __DIR__ . + '/resources/SiteKitResourceChannelFactory' . + '/resourceLayout/object'; + $resourceBaseLocator + ->expects($this->once()) + ->method('locate') + ->willReturn($resourceDir); + + $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); + $factory->create(); + $factory->create(); + } + + public function testCreateWithDocumentRootLayout(): void + { + $resourceBaseLocator = $this->createStub( + ResourceBaseLocator::class + ); + $resourceDir = __DIR__ . + '/resources/SiteKitResourceChannelFactory' . + '/documentRootLayout'; + $resourceBaseLocator->method('locate') + ->willReturn($resourceDir); + + $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); + $channel = $factory->create(); + + $expected = new ResourceChannel( + '1', + 'Test', + 'test', + 'www.test.org', + true, + 'internet', + 'de_DE', + 'UTF-8', + 'test', + [] + ); + $this->assertEquals( + $expected, + $channel, + 'ResourceChannel does not match expected values' + ); + } + + public function testCreateNonExistsContextPhp(): void + { + $resourceBaseLocator = $this->createStub( + ResourceBaseLocator::class + ); + $resourceDir = __DIR__ . + '/resources/SiteKitResourceChannelFactory' . + '/noexists'; + $resourceBaseLocator->method('locate') + ->willReturn($resourceDir); + + $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); + + $this->expectException(\RuntimeException::class); + $factory->create(); + } + + public function testCreateWithInvalidContextPhp(): void + { + $resourceBaseLocator = $this->createStub( + ResourceBaseLocator::class + ); + $resourceDir = __DIR__ . + '/resources/SiteKitResourceChannelFactory' . + '/invalid/object'; + $resourceBaseLocator->method('locate') + ->willReturn($resourceDir); + + $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); + + $this->expectException(\RuntimeException::class); + $factory->create(); + } +} diff --git a/test/resources/Loader/SiteKitLoader/missingLocaleResource.php b/test/resources/Loader/SiteKitLoader/missingLocaleResource.php new file mode 100644 index 0000000..003d1a8 --- /dev/null +++ b/test/resources/Loader/SiteKitLoader/missingLocaleResource.php @@ -0,0 +1,26 @@ +getAttribute('lifecycle'); +} + +$resource = $context->redirectToTranslation($lifecycle, '/index.php'); +if ($resource !== null) { + return $resource; +} + +/* Lifecylce-Process */ +$resource = $lifecycle->init([ + "id" => 1118, + "objectType" => "home", + "name" => "Startseite", +]); + +return $lifecycle->service($resource); diff --git a/test/resources/Loader/SiteKitLoader/nonStringLocaleResource.php b/test/resources/Loader/SiteKitLoader/nonStringLocaleResource.php new file mode 100644 index 0000000..a6bd4a9 --- /dev/null +++ b/test/resources/Loader/SiteKitLoader/nonStringLocaleResource.php @@ -0,0 +1,27 @@ +getAttribute('lifecycle'); +} + +$resource = $context->redirectToTranslation($lifecycle, '/index.php'); +if ($resource !== null) { + return $resource; +} + +/* Lifecylce-Process */ +$resource = $lifecycle->init([ + "id" => 1118, + "objectType" => 'home', + "name" => "Startseite", + 'locale' => 123 +]); + +return $lifecycle->service($resource); diff --git a/test/resources/Loader/SiteKitLoader/validResource.php.translations/en_US.php b/test/resources/Loader/SiteKitLoader/validResource.php.translations/en_US.php new file mode 100644 index 0000000..8eb3c64 --- /dev/null +++ b/test/resources/Loader/SiteKitLoader/validResource.php.translations/en_US.php @@ -0,0 +1,80 @@ +getAttribute('lifecycle'); +} + +$resource = $context->redirectToTranslation($lifecycle, '/index.php'); +if ($resource !== null) { + return $resource; +} + +/* Lifecylce-Process */ +$resource = $lifecycle->init([ + "id" => 1118, + "version" => "1694758793440", + "encoding" => "UTF-8", + "locale" => "en_US", + "objectType" => "home", + "url" => "/index.php", + "name" => "Homepage", + "anchor" => "internetwebsite.home", +]); +if ($lifecycle->finish($resource)) { + return $resource; +} + +if ($lifecycle->process("base", $resource)) { + $resource->process("base", [ + "date" => 1571988240 + ]); +} + +if ($lifecycle->finish($resource)) { + return $resource; +} + +if ($lifecycle->process("metadata", $resource)) { + $resource->process("metadata", [ + "description" => "The new website with up-to-date information." + ]); +} + +if ($lifecycle->finish($resource)) { + return $resource; +} + +if ($lifecycle->process("searchindexdata", $resource)) { + $resource->process("searchindexdata", [ + "content" => "The new website with up-to-date information." + ]); +} + +if ($lifecycle->finish($resource)) { + return $resource; +} + +if ($lifecycle->process("content", $resource)) { + $resource->process("content", [ + "type" => "ROOT", + "id" => "ROOT", + "items" => [[ + "type" => "main", + "id" => "main", + "items" => [[ + ]] + ]] + ]); +} +if ($lifecycle->finish($resource)) { + return $resource; +} + +return $lifecycle->service($resource); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/a.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/a.php index 9837662..6f106c6 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/a.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/a.php @@ -5,5 +5,6 @@ 'a', 'a', '', + 'de_DE', [] ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php index b38b76e..fc56006 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php @@ -5,6 +5,7 @@ 'b', 'b', '', + 'de_DE', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php index 1508ece..cead96f 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php @@ -5,6 +5,7 @@ 'c', 'c', '', + 'de_DE', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php index 7e4bd0f..381d6aa 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php @@ -5,5 +5,6 @@ 'dir-index', 'dir-index', '', + 'de_DE', [] ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php index 1fbf006..ee5e89c 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php @@ -5,6 +5,7 @@ 'root', 'root', '', + 'de_DE', [ 'init' => [ 'home' => true diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php index 0feb4b9..b346f43 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php @@ -5,6 +5,7 @@ 'a', 'a', '', + 'de_DE', [ 'init' => [ 'home' => true diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php index 3cc9e43..43919d7 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php @@ -5,6 +5,7 @@ 'b', 'b', '', + 'de_DE', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php index 96b4a98..9ef8307 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php @@ -5,6 +5,7 @@ 'c', 'c', '', + 'de_DE', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php index ea37cf7..960770d 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php @@ -5,5 +5,6 @@ 'a', 'a', '', + 'de_DE', [] ); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php index fe83764..38b8f56 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php @@ -7,6 +7,7 @@ 'a', 'a', '', + 'en', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php index ed98223..a5625c3 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php @@ -7,6 +7,7 @@ 'b', 'b', '', + 'en', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php index 4b326dc..ea950b0 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php @@ -7,6 +7,7 @@ 'c', 'c', '', + 'en', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php index 3aee934..a1bd1e0 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php @@ -7,6 +7,7 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', + 'en', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php index dce78fb..34ad2e2 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php @@ -7,6 +7,7 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', + 'en', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php index 16bc5d5..4c104cb 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php @@ -7,6 +7,7 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', + 'en', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php index c0b75ef..6b0cd82 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php @@ -7,6 +7,7 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', + 'en', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php index 5853985..c2b30fb 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php @@ -7,6 +7,7 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', + 'en', [ 'base' => [ 'trees' => [ diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php index b18d272..1084fd6 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php @@ -7,6 +7,7 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', + 'en', [ 'base' => [ 'trees' => [ diff --git a/test/resources/SiteKitResourceChannelFactory/documentRootLayout/WEB-IES/context.php b/test/resources/SiteKitResourceChannelFactory/documentRootLayout/WEB-IES/context.php new file mode 100644 index 0000000..5c2f9b4 --- /dev/null +++ b/test/resources/SiteKitResourceChannelFactory/documentRootLayout/WEB-IES/context.php @@ -0,0 +1,14 @@ + [ + 'id' => '1', + 'name' => 'Test', + 'anchor' => 'test', + 'serverName' => 'www.test.org', + 'preview' => true, + 'nature' => 'internet', + 'locale' => null, + 'encoding' => null, + ] +]; diff --git a/test/resources/SiteKitResourceChannelFactory/invalid/context.php b/test/resources/SiteKitResourceChannelFactory/invalid/context.php new file mode 100644 index 0000000..8076041 --- /dev/null +++ b/test/resources/SiteKitResourceChannelFactory/invalid/context.php @@ -0,0 +1,3 @@ + [ + 'id' => '1', + 'name' => 'Test', + 'anchor' => 'test', + 'serverName' => 'www.test.org', + 'preview' => true, + 'nature' => 'internet', + 'locale' => 'de_DE', + 'encoding' => 'UTF-8', + ] +]; From 23acd442c85165180c04df7c1e39fbb9007ed80c Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Wed, 20 Mar 2024 17:32:08 +0100 Subject: [PATCH 07/31] chore: normalize composer.json --- composer.json | 10 ++-------- composer.lock | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index 34b90ed..83ef2cf 100644 --- a/composer.json +++ b/composer.json @@ -11,8 +11,8 @@ ], "require": { "php": ">=8.1 <8.4.0", - "ext-intl": "*" - }, + "ext-intl": "*" + }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "infection/infection": "^0.27.6", @@ -44,12 +44,6 @@ }, "sort-packages": true }, - "extra": { - "branch-alias": { - "feature/find-in-hierarchy": "dev-main", - "feature/resource-channel" : "dev-main" - } - }, "scripts": { "post-install-cmd": "phive --no-progress install --force-accept-unsigned --trust-gpg-keys C00543248C87FB13,4AA394086372C20A,CF1A108D0E7AE720,51C67305FFC2E5C0", "analyse": [ diff --git a/composer.lock b/composer.lock index 475209f..55bd78e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "266effc88deaa99d53a4da4be1e50533", + "content-hash": "74aae9ff5c4a4aaea0d1ab3eaa727b8c", "packages": [], "packages-dev": [ { @@ -1745,7 +1745,7 @@ "codeigniter4/shield": "<1.0.0.0-beta8", "codiad/codiad": "<=2.8.4", "composer/composer": "<1.10.27|>=2,<2.2.23|>=2.3,<2.7", - "concrete5/concrete5": "<9.2.5", + "concrete5/concrete5": "<9.2.7", "concrete5/core": "<8.5.8|>=9,<9.1", "contao-components/mediaelement": ">=2.14.2,<2.21.1", "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.40|>=4.10,<4.11.7|>=4.13,<4.13.21|>=5.1,<5.1.4", @@ -1814,7 +1814,7 @@ "ezsystems/ezplatform-solr-search-engine": ">=1.7,<1.7.12|>=2,<2.0.2|>=3.3,<3.3.15", "ezsystems/ezplatform-user": ">=1,<1.0.1", "ezsystems/ezpublish-kernel": "<6.13.8.2-dev|>=7,<7.5.31", - "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.06,<=2019.03.5.1", + "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.03.5.1", "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", "ezsystems/repository-forms": ">=2.3,<2.3.2.1-dev|>=2.5,<2.5.15", "ezyang/htmlpurifier": "<4.1.1", @@ -1845,6 +1845,7 @@ "friendsofsymfony/oauth2-php": "<1.3", "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", + "friendsofsymfony1/symfony1": ">=1.3,<1.5.13", "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", "friendsoftypo3/openid": ">=4.5,<4.5.31|>=4.7,<4.7.16|>=6,<6.0.11|>=6.1,<6.1.6", "froala/wysiwyg-editor": "<3.2.7|>=4.0.1,<=4.1.1", @@ -1888,6 +1889,7 @@ "ibexa/user": ">=4,<4.4.3", "icecoder/icecoder": "<=8.1", "idno/known": "<=1.3.1", + "ilicmiljan/secure-props": ">=1.2,<1.2.2", "illuminate/auth": "<5.5.10", "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.99999|>=4.2,<=4.2.99999|>=5,<=5.0.99999|>=5.1,<=5.1.99999|>=5.2,<=5.2.99999|>=5.3,<=5.3.99999|>=5.4,<=5.4.99999|>=5.5,<=5.5.49|>=5.6,<=5.6.99999|>=5.7,<=5.7.99999|>=5.8,<=5.8.99999|>=6,<6.18.31|>=7,<7.22.4", "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", @@ -1948,7 +1950,7 @@ "liftkit/database": "<2.13.2", "limesurvey/limesurvey": "<3.27.19", "livehelperchat/livehelperchat": "<=3.91", - "livewire/livewire": ">2.2.4,<2.2.6", + "livewire/livewire": ">2.2.4,<2.2.6|>=3.3.5,<3.4.9", "lms/routes": "<2.1.1", "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", "luyadev/yii-helpers": "<1.2.1", @@ -2074,7 +2076,7 @@ "pixelfed/pixelfed": "<0.11.11", "plotly/plotly.js": "<2.25.2", "pocketmine/bedrock-protocol": "<8.0.2", - "pocketmine/pocketmine-mp": "<=4.23|>=5,<5.3.1", + "pocketmine/pocketmine-mp": "<5.11.2", "pocketmine/raklib": ">=0.14,<0.14.6|>=0.15,<0.15.1", "pressbooks/pressbooks": "<5.18", "prestashop/autoupgrade": ">=4,<4.10.1", @@ -2106,7 +2108,7 @@ "react/http": ">=0.7,<1.9", "really-simple-plugins/complianz-gdpr": "<6.4.2", "redaxo/source": "<=5.15.1", - "remdex/livehelperchat": "<3.99", + "remdex/livehelperchat": "<4.29", "reportico-web/reportico": "<=7.1.21", "rhukster/dom-sanitizer": "<1.0.7", "rmccue/requests": ">=1.6,<1.8", @@ -2195,7 +2197,7 @@ "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", - "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<5.3.15|>=5.4.3,<5.4.4|>=6.0.3,<6.0.4", "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", @@ -4539,8 +4541,9 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": ">=8.1 <8.4.0" + "php": ">=8.1 <8.4.0", + "ext-intl": "*" }, "platform-dev": [], - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } From e90d5f67f3c39d3074f9591a0ed190bc44ed3ece Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Wed, 20 Mar 2024 17:34:36 +0100 Subject: [PATCH 08/31] fix: add empty directories for tests --- .../ServerVarResourceBaseLocator/documentRootLayout/.gitkeep | 0 .../ServerVarResourceBaseLocator/resourceLayout/object/.gitkeep | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/resources/Loader/ServerVarResourceBaseLocator/documentRootLayout/.gitkeep create mode 100644 test/resources/Loader/ServerVarResourceBaseLocator/resourceLayout/object/.gitkeep diff --git a/test/resources/Loader/ServerVarResourceBaseLocator/documentRootLayout/.gitkeep b/test/resources/Loader/ServerVarResourceBaseLocator/documentRootLayout/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/resources/Loader/ServerVarResourceBaseLocator/resourceLayout/object/.gitkeep b/test/resources/Loader/ServerVarResourceBaseLocator/resourceLayout/object/.gitkeep new file mode 100644 index 0000000..e69de29 From c9a4b61d862985f0d002537406d05ecce254e678 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Fri, 22 Mar 2024 13:13:48 +0100 Subject: [PATCH 09/31] fix: resource base location --- src/Loader/ServerVarResourceBaseLocator.php | 3 ++- src/SiteKitResourceChannelFactory.php | 2 +- test/Loader/ServerVarResourceBaseLocatorTest.php | 2 +- test/SiteKitResourceChannelFactoryTest.php | 12 ++++++------ .../resourceLayout/{object => objects}/.gitkeep | 0 .../invalid/objects/.gitkeep | 0 .../resourceLayout/objects/.gitkeep | 0 7 files changed, 10 insertions(+), 9 deletions(-) rename test/resources/Loader/ServerVarResourceBaseLocator/resourceLayout/{object => objects}/.gitkeep (100%) create mode 100644 test/resources/SiteKitResourceChannelFactory/invalid/objects/.gitkeep create mode 100644 test/resources/SiteKitResourceChannelFactory/resourceLayout/objects/.gitkeep diff --git a/src/Loader/ServerVarResourceBaseLocator.php b/src/Loader/ServerVarResourceBaseLocator.php index 64fb263..cd3ff2a 100644 --- a/src/Loader/ServerVarResourceBaseLocator.php +++ b/src/Loader/ServerVarResourceBaseLocator.php @@ -28,7 +28,8 @@ public function locate(): string ); } - $resourceLayoutResourceBase = $_SERVER[$this->variableName] . '/object'; + $resourceLayoutResourceBase = $_SERVER[$this->variableName] . + '/objects'; if (is_dir($resourceLayoutResourceBase)) { $this->resourceBase = $resourceLayoutResourceBase; return $resourceLayoutResourceBase; diff --git a/src/SiteKitResourceChannelFactory.php b/src/SiteKitResourceChannelFactory.php index 5168053..2e19993 100644 --- a/src/SiteKitResourceChannelFactory.php +++ b/src/SiteKitResourceChannelFactory.php @@ -79,7 +79,7 @@ private function loadContextPhpFile(): array private function findContextPhpFile(): string { $resourceBase = $this->resourceBaseLocator->locate(); - if (str_ends_with($resourceBase, '/object')) { + if (file_exists($resourceBase . '/../context.php')) { $contextPhpFile = dirname($resourceBase) . '/context.php'; } else { $contextPhpFile = $resourceBase . '/WEB-IES/context.php'; diff --git a/test/Loader/ServerVarResourceBaseLocatorTest.php b/test/Loader/ServerVarResourceBaseLocatorTest.php index 01238aa..8e7ddf7 100644 --- a/test/Loader/ServerVarResourceBaseLocatorTest.php +++ b/test/Loader/ServerVarResourceBaseLocatorTest.php @@ -54,7 +54,7 @@ public function testWithResourceLayout(): void 'RESOURCE_ROOT' ); $this->assertEquals( - $baseLocation . '/object', + $baseLocation . '/objects', $locator->locate(), 'unexpected resource base' ); diff --git a/test/SiteKitResourceChannelFactoryTest.php b/test/SiteKitResourceChannelFactoryTest.php index c13c36c..d25134a 100644 --- a/test/SiteKitResourceChannelFactoryTest.php +++ b/test/SiteKitResourceChannelFactoryTest.php @@ -20,9 +20,9 @@ public function testCreateWithResourceLayout(): void ); $resourceDir = __DIR__ . '/resources/SiteKitResourceChannelFactory' . - '/resourceLayout/object'; + '/resourceLayout'; $resourceBaseLocator->method('locate') - ->willReturn($resourceDir); + ->willReturn($resourceDir . '/objects'); $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); $channel = $factory->create(); @@ -53,11 +53,11 @@ public function testCreateCache(): void ); $resourceDir = __DIR__ . '/resources/SiteKitResourceChannelFactory' . - '/resourceLayout/object'; + '/resourceLayout'; $resourceBaseLocator ->expects($this->once()) ->method('locate') - ->willReturn($resourceDir); + ->willReturn($resourceDir . '/objects'); $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); $factory->create(); @@ -121,9 +121,9 @@ public function testCreateWithInvalidContextPhp(): void ); $resourceDir = __DIR__ . '/resources/SiteKitResourceChannelFactory' . - '/invalid/object'; + '/invalid'; $resourceBaseLocator->method('locate') - ->willReturn($resourceDir); + ->willReturn($resourceDir . '/objects'); $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); diff --git a/test/resources/Loader/ServerVarResourceBaseLocator/resourceLayout/object/.gitkeep b/test/resources/Loader/ServerVarResourceBaseLocator/resourceLayout/objects/.gitkeep similarity index 100% rename from test/resources/Loader/ServerVarResourceBaseLocator/resourceLayout/object/.gitkeep rename to test/resources/Loader/ServerVarResourceBaseLocator/resourceLayout/objects/.gitkeep diff --git a/test/resources/SiteKitResourceChannelFactory/invalid/objects/.gitkeep b/test/resources/SiteKitResourceChannelFactory/invalid/objects/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/resources/SiteKitResourceChannelFactory/resourceLayout/objects/.gitkeep b/test/resources/SiteKitResourceChannelFactory/resourceLayout/objects/.gitkeep new file mode 100644 index 0000000..e69de29 From 747dca1f266c5f8e6353d88cf7d51cce4fa7f198 Mon Sep 17 00:00:00 2001 From: Holger Veltrup <92872893+sitepark-veltrup@users.noreply.github.com> Date: Tue, 2 Apr 2024 14:06:24 +0200 Subject: [PATCH 10/31] Update src/ResourceHierarchyLoader.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mario Schäper <95750382+sitepark-schaeper@users.noreply.github.com> --- src/ResourceHierarchyLoader.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/ResourceHierarchyLoader.php b/src/ResourceHierarchyLoader.php index 71a7f9e..df84e15 100644 --- a/src/ResourceHierarchyLoader.php +++ b/src/ResourceHierarchyLoader.php @@ -56,15 +56,12 @@ public function loadChildren(string $location): array; * callable returns true. * * The callable function expects the following parameters: - * - array of Resource: the path to the current resource. Don't contains - * the current resource. * - Resource: the current resource * * The callable function should return true if the current resource is the * one we are looking for. * - * @param callable(Resource[], Resource): bool $fn - * @param Resource[] $parentPath + * @param callable(Resource): bool $fn * @throws InvalidResourceException * @throws ResourceNotFoundException */ From 69be91cfeed042952d39ab18b4df3fc7d3af31ca Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 4 Apr 2024 14:06:29 +0200 Subject: [PATCH 11/31] feat: ResourceHierarchyWalker implementation --- .../SiteKitNavigationHierarchyLoader.php | 2 +- src/Loader/SiteKitResourceHierarchyLoader.php | 77 ++- src/ResourceHierarchyFinder.php | 52 +++ src/ResourceHierarchyLoader.php | 59 ++- src/ResourceHierarchyWalker.php | 412 ++++++++++++++++ .../SiteKitResourceHierarchyLoaderTest.php | 147 +++++- test/ResourceHierarchyFinderTest.php | 91 ++++ test/ResourceHierarchyWalkerTest.php | 438 ++++++++++++++++++ test/resources/ResourceHierarchyFinder/a.php | 24 + test/resources/ResourceHierarchyFinder/b.php | 29 ++ test/resources/ResourceHierarchyFinder/c.php | 27 ++ test/resources/ResourceHierarchyWalker/1.php | 29 ++ .../resources/ResourceHierarchyWalker/1/1.php | 32 ++ .../ResourceHierarchyWalker/1/1/1.php | 29 ++ .../ResourceHierarchyWalker/1/1/1/1.php | 23 + test/resources/ResourceHierarchyWalker/2.php | 33 ++ .../resources/ResourceHierarchyWalker/2/1.php | 23 + .../resources/ResourceHierarchyWalker/2/2.php | 23 + .../ResourceHierarchyWalker/root.php | 28 ++ 19 files changed, 1536 insertions(+), 42 deletions(-) create mode 100644 src/ResourceHierarchyFinder.php create mode 100644 src/ResourceHierarchyWalker.php create mode 100644 test/ResourceHierarchyFinderTest.php create mode 100644 test/ResourceHierarchyWalkerTest.php create mode 100644 test/resources/ResourceHierarchyFinder/a.php create mode 100644 test/resources/ResourceHierarchyFinder/b.php create mode 100644 test/resources/ResourceHierarchyFinder/c.php create mode 100644 test/resources/ResourceHierarchyWalker/1.php create mode 100644 test/resources/ResourceHierarchyWalker/1/1.php create mode 100644 test/resources/ResourceHierarchyWalker/1/1/1.php create mode 100644 test/resources/ResourceHierarchyWalker/1/1/1/1.php create mode 100644 test/resources/ResourceHierarchyWalker/2.php create mode 100644 test/resources/ResourceHierarchyWalker/2/1.php create mode 100644 test/resources/ResourceHierarchyWalker/2/2.php create mode 100644 test/resources/ResourceHierarchyWalker/root.php diff --git a/src/Loader/SiteKitNavigationHierarchyLoader.php b/src/Loader/SiteKitNavigationHierarchyLoader.php index 9db113b..389047e 100644 --- a/src/Loader/SiteKitNavigationHierarchyLoader.php +++ b/src/Loader/SiteKitNavigationHierarchyLoader.php @@ -17,7 +17,7 @@ public function __construct(ResourceLoader $resourceLoader) parent::__construct($resourceLoader, 'navigation'); } - protected function isRoot(Resource $resource): bool + public function isRoot(Resource $resource): bool { return $resource->getData()->getBool('init.home'); } diff --git a/src/Loader/SiteKitResourceHierarchyLoader.php b/src/Loader/SiteKitResourceHierarchyLoader.php index 92759ef..1fa1e96 100644 --- a/src/Loader/SiteKitResourceHierarchyLoader.php +++ b/src/Loader/SiteKitResourceHierarchyLoader.php @@ -36,7 +36,7 @@ public function loadRoot(string $location): Resource * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function loadParent(string $location): ?Resource + public function loadPrimaryParent(string $location): ?Resource { $resource = $this->resourceLoader->load($location); if ($this->isRoot($resource)) { @@ -45,13 +45,26 @@ public function loadParent(string $location): ?Resource return $this->loadPrimaryParentResource($resource); } + /** + * @throws InvalidResourceException + * @throws ResourceNotFoundException + */ + public function loadParent(string $location, string $parentId): ?Resource + { + $resource = $this->resourceLoader->load($location); + if ($this->isRoot($resource)) { + return null; + } + return $this->loadParentResource($resource, $parentId); + } + /** * @return Resource[] * @throws InvalidResourceException if an encountered Resource has no * parent but is not considered a root. * @throws ResourceNotFoundException */ - public function loadPath(string $location): array + public function loadPrimaryPath(string $location): array { $resource = $this->resourceLoader->load($location); $path = [$resource]; @@ -74,7 +87,7 @@ public function loadChildren(string $location): array $resource = $this->resourceLoader->load($location); $children = []; - $childrenLocationList = $this->getChildrenLocationList($resource); + $childrenLocationList = $this->getChildrenLocations($resource); foreach ($childrenLocationList as $childLocation) { $children[] = $this->resourceLoader->load($childLocation); } @@ -108,7 +121,7 @@ public function findRecursive( return $resource; } - $childrenLocationList = $this->getChildrenLocationList($resource); + $childrenLocationList = $this->getChildrenLocations($resource); foreach ($childrenLocationList as $childLocation) { $result = $this->findRecursive( $childLocation, @@ -139,14 +152,29 @@ protected function loadPrimaryParentResource( return $this->resourceLoader->load($parentLocation); } - protected function getResourceLoader(): ResourceLoader + protected function loadParentResource( + Resource $resource, + string $parentId + ): ?Resource { + $parentLocation = $this->getParentLocation($resource, $parentId); + if ($parentLocation === null) { + return null; + } + return $this->resourceLoader->load($parentLocation); + } + + public function getResourceLoader(): ResourceLoader { return $this->resourceLoader; } - protected function isRoot(Resource $resource): bool + public function isRoot(Resource $resource): bool { - return $this->getPrimaryParentLocation($resource) === null; + $parentList = $resource->getData()->getAssociativeArray( + 'base.trees.' . $this->treeName . '.parents' + ); + + return count($parentList) === 0; } /** @@ -154,7 +182,7 @@ protected function isRoot(Resource $resource): bool * @return string|null * @throws InvalidResourceException */ - protected function getPrimaryParentLocation(Resource $resource): ?string + public function getPrimaryParentLocation(Resource $resource): ?string { $parentList = $resource->getData()->getAssociativeArray( 'base.trees.' . $this->treeName . '.parents' @@ -220,10 +248,41 @@ protected function getPrimaryParentLocation(Resource $resource): ?string return $firstParent['url']; } + public function getParentLocation( + Resource $resource, + string $parentId + ): ?string { + $parentList = $resource->getData()->getAssociativeArray( + 'base.trees.' . $this->treeName . '.parents' + ); + + if ( + count($parentList) === 0 + ) { + return null; + } + + foreach ($parentList as $id => $parent) { + if (!is_array($parent)) { + throw new InvalidResourceException( + $resource->getLocation(), + 'parent in ' . + 'base.trees.' . $this->treeName . '.parents ' . + 'not an array' + ); + } + if ($parentId === (string)$id) { + return $parent['url']; + } + } + + return null; + } + /** * @return string[] */ - protected function getChildrenLocationList(Resource $resource): array + public function getChildrenLocations(Resource $resource): array { $childrenList = $resource->getData()->getAssociativeArray( 'base.trees.' . $this->treeName . '.children' diff --git a/src/ResourceHierarchyFinder.php b/src/ResourceHierarchyFinder.php new file mode 100644 index 0000000..62173ac --- /dev/null +++ b/src/ResourceHierarchyFinder.php @@ -0,0 +1,52 @@ +loader); + + $walker->init($base); + + $current = $walker->getCurrent(); + + if ($fn($current) === true) { + return $current; + } + while ($current = $walker->next()) { + if ($fn($current) === true) { + return $current; + } + } + + return null; + } +} diff --git a/src/ResourceHierarchyLoader.php b/src/ResourceHierarchyLoader.php index df84e15..f2e453e 100644 --- a/src/ResourceHierarchyLoader.php +++ b/src/ResourceHierarchyLoader.php @@ -23,23 +23,23 @@ interface ResourceHierarchyLoader public function loadRoot(string $location): Resource; /** - * Determines the parent resource via the parent links contained in the - * resource data. + * Determines the primary parent resource via the parent links + * contained in the resource data. * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function loadParent(string $location): ?Resource; + public function loadPrimaryParent(string $location): ?Resource; /** - * Determines the path to the root resource via the parent links contained - * in the resource data. + * Determines the path to the root resource via the primary parent links + * contained in the resource data. * The array contains the resources starting with the root resource. The * last element of the array is the resource of the passed `$location` * @return Resource[] * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function loadPath(string $location): array; + public function loadPrimaryPath(string $location): array; /** * Determines the children resources via the children links contained in the @@ -51,22 +51,39 @@ public function loadPath(string $location): array; public function loadChildren(string $location): array; /** - * Walks the tree of resources starting from the given location and calls - * the given function for each resource. Returns the resource where the - * callable returns true. - * - * The callable function expects the following parameters: - * - Resource: the current resource + * Indicates whether the passed resource is a root resource. * - * The callable function should return true if the current resource is the - * one we are looking for. + * @param Resource $resource + * @return bool + */ + public function isRoot(Resource $resource): bool; + + /** + * Determines the children locations via the children links contained in the + * resource data. * - * @param callable(Resource): bool $fn - * @throws InvalidResourceException - * @throws ResourceNotFoundException + * @return string[] + */ + public function getChildrenLocations(Resource $resource): array; + + /** + * Determines the primary parent location via the parent links contained in + * the resource data. + */ + public function getPrimaryParentLocation(Resource $resource): ?string; + + /** + * Determines the secondary parent location via the parent links contained + * in the resource data. A secondary parent is identified by the passed + * `$parentId`. + */ + public function getParentLocation( + Resource $resource, + string $parentId + ): ?string; + + /** + * Returns the `ResourceLoader` instance used to load resources. */ - public function findRecursive( - string $location, - callable $fn - ): ?Resource; + public function getResourceLoader(): ResourceLoader; } diff --git a/src/ResourceHierarchyWalker.php b/src/ResourceHierarchyWalker.php new file mode 100644 index 0000000..aa44006 --- /dev/null +++ b/src/ResourceHierarchyWalker.php @@ -0,0 +1,412 @@ +> + */ + private array $childrenStack = []; + + /** + * Points to the children for all children lists of + * $childrenStack`. $childrenStackPointer[0] indicates the + * current position of `$childrenStack[0]`. + * + * @var array + */ + private array $childrenStackPointer = []; + + /** + * @var Resource[] + */ + private array $parentPath = []; + + public function __construct( + private readonly ResourceHierarchyLoader $hierarchyLoader, + ) { + } + + /** + * Defines the resource that the walker should initially use. + * It is important to first set an initial resource so that + * the walker can work. + * + * If the walker has already worked, it is reset. + * + * @param Resource|string $base The resource to be used initially. + * If `$base` is a string it is assumed that it is a location and + * the resource is loaded. + */ + public function init(Resource|string $base): void + { + if (is_string($base)) { + $base = $this->load($base); + } + $this->current = $base; + $this->childrenStack = []; + $this->childrenStackPointer = []; + $this->parentPath = []; + } + + /** + * There can be more than one higher-level resource in the hierarchy of + * a resource. One of these higher-level resources is always defined + * as primary. This method can be used to set the walker to the primary + * parent resource. + * + * Internally, `init()` is also called here with the determined parent. + * So that the walker is also reset if necessary. + * + * @return Resource|null Returns null if the current resource is + * a root resource. + * @throws LogicException If no current resource is set. + */ + public function primaryParent(): ?Resource + { + if ($this->current === null) { + throw new LogicException('No current resource set'); + } + + if ($this->hierarchyLoader->isRoot($this->current)) { + return null; + } + + $primaryParentLocation = $this->hierarchyLoader + ->getPrimaryParentLocation($this->current); + if ($primaryParentLocation === null) { + return null; + } + + $this->init($this->load( + $primaryParentLocation + )); + + return $this->getCurrent(); + } + + /** + * There can be more than one parent resource in the hierarchy of a + * resource. + * This method can be used to set the walker to a specific parent + * resource. + * + * Internally, `init()` is also called here with the determined parent. + * So that the walker is also reset if necessary. + * + * @return Resource|null Returns null if the current resource is + * a root resource or the parent could not be determined. + * @throws LogicException If no current resource is set. + */ + public function parent(string $parentId): ?Resource + { + if ($this->current === null) { + throw new LogicException('No current resource set'); + } + + if ($this->hierarchyLoader->isRoot($this->current)) { + return null; + } + + $secondaryParentLocation = $this->hierarchyLoader + ->getParentLocation($this->current, $parentId); + if ($secondaryParentLocation === null) { + return null; + } + + $this->init($this->load( + $secondaryParentLocation + )); + + return $this->getCurrent(); + } + + /** + * The resource where the Walker is currently positioned. + * @throws LogicException If no current resource is set. + */ + public function getCurrent(): Resource + { + if ($this->current === null) { + throw new LogicException('No current resource set'); + } + return $this->current; + } + + /** + * The level in which the walker is currently located. + * Based on the resource that was initially used. + */ + public function getLevel(): int + { + return count($this->parentPath); + } + + /** + * The path the walker has traveled up to the current element. + * Based on the resource that was initially used. + * The initial resource is the first, the current resource the + * last element of the path. + * + * @return Resource[] + */ + public function getPath(): array + { + if ($this->current === null) { + return []; + } + + $path = $this->parentPath; + $path[] = $this->current; + return $path; + } + + /** + * Walk to the next sibling. Please note that this does not work for + * the initial resource that was set with `init()`, as the parent + * resource is not known. This case can be solved with the help of + * `primaryParent()` and `secondaryParent()`. + * + * ``` + * $walker->init($base); + * $walker->primaryParent(); + * $walker->child($base->getId()); + * $walker->nextSibling(); + * ``` + * + * @return Resource|null Returns null if there are no more siblings. + */ + public function nextSibling(): ?Resource + { + if (empty($this->childrenStack)) { + return null; + } + + $topStackIndex = count($this->childrenStack) - 1; + $children = $this->childrenStack[$topStackIndex]; + $pointer = $this->childrenStackPointer[$topStackIndex] + 1; + + if ($pointer >= count($children)) { + return null; + } + + $childLocation = $children[$pointer]; + $child = $this->load($childLocation); + + $this->childrenStackPointer[$topStackIndex] = $pointer; + $this->current = $child; + return $child; + } + + /** + * Walk to the previous sibling. Please note that this does not work for + * the initial resource that was set with `init()`, as the parent + * resource is not known. This case can be solved with the help of + * `primaryParent()` and `secondaryParent()`. + * + * ``` + * $walker->init($base); + * $walker->primaryParent(); + * $walker->child($base->getId()); + * $walker->previousSibling(); + * ``` + * + * @return Resource|null Returns null if there are no more siblings. + */ + public function previousSibling(): ?Resource + { + if (empty($this->childrenStack)) { + return null; + } + + $topStackIndex = count($this->childrenStack) - 1; + $children = $this->childrenStack[$topStackIndex]; + $pointer = $this->childrenStackPointer[$topStackIndex] - 1; + + if ($pointer < 0) { + return null; + } + + // + $childLocation = $children[$pointer]; + $child = $this->load($childLocation); + + $this->childrenStackPointer[$topStackIndex] = $pointer; + $this->current = $child; + return $child; + } + + + /** + * Go up one level. This is only possible if the walker has already + * gone down one level. If the parent element is to be determined + * from an initial resource, `primaryParent` or `secondaryParent` + * must be used. + * + * @return Resource|null Returns null if the walker is already at the + * highest level. + */ + public function up(): ?Resource + { + if ($this->current === null) { + throw new LogicException('No current resource set'); + } + + if (empty($this->parentPath)) { + return null; + } + + $parent = array_pop($this->parentPath); + + array_pop($this->childrenStack); + array_pop($this->childrenStackPointer); + + $this->current = $parent; + + return $this->current; + } + + /** + * Goes down one level. And use the first child. + * This is only possible if the current resource also + * has children. + * + * @return Resource|null Returns null if the current resource + * has no children. + * @throws LogicException If no current resource is set. + */ + public function down(): ?Resource + { + if ($this->current === null) { + throw new LogicException('No current resource set'); + } + + $childrenLocations = $this->hierarchyLoader->getChildrenLocations( + $this->current + ); + $children = array_values($childrenLocations); + + if (empty($children)) { + return null; + } + + $this->parentPath[] = $this->current; + $this->current = $this->load($children[0]); + + $this->childrenStack[] = array_values($children); + $this->childrenStackPointer[count($this->childrenStack) - 1] = 0; + + return $this->current; + } + + /** + * Goes down one level like `down()`. However, the first child resource + * is not used here, instead `$childId` is used to specify which one is to + * be used child resource. + * + * @param string $childId The ID of the child resource to be used. + * @return Resource|null Returns null if the current resource has no + * children or the child resource could not be found. + */ + public function child(string $childId): ?Resource + { + if ($this->current === null) { + throw new LogicException('No current resource set'); + } + + $childrenLocations = $this->hierarchyLoader->getChildrenLocations( + $this->current + ); + + if (empty($childrenLocations)) { + return null; + } + + $childPointer = array_search( + (int)$childId, + array_keys($childrenLocations), + true + ); + + if ($childPointer === false) { + return null; + } + + $children = array_values($childrenLocations); + + $this->parentPath[] = $this->current; + $this->current = $this->load($children[$childPointer]); + + $this->childrenStack[] = array_values($children); + $this->childrenStackPointer[count($this->childrenStack) - 1] = + $childPointer; + + return $this->current; + } + + + /** + * This method runs through the hierarchy downwards from the + * initial resource. + * + * @return Resource|null Returns `null` after the last resource in + * the hierarchy has been run through. + */ + public function next(): ?Resource + { + if ($this->current === null) { + throw new LogicException('No current resource set'); + } + + $firstChildOfCurrent = $this->down(); + if ($firstChildOfCurrent !== null) { + return $firstChildOfCurrent; + } + + while (count($this->childrenStack) > 0) { + $child = $this->nextSibling(); + if ($child !== null) { + return $child; + } + $this->up(); + } + + return null; + } + + + /** + * Traverses the entire hierarchy downwards and calls the `$fn` method + * for each resource. Including the passed `$base` resource. + * In the method, `init($base)` is called, which resets the walker + * if necessary. Here `next()` is used to traverse the hierarchy. + * + * @param Resource $base The resource from which the hierarchy is to + * be traversed. + * @param callable(Resource): void $fn The method to be called for each + * resource. + */ + public function walk(Resource $base, callable $fn): void + { + $this->init($base); + $fn($base); + while ($current = $this->next()) { + $fn($current); + } + } + + private function load(string $location): Resource + { + return $this->hierarchyLoader->getResourceLoader()->load($location); + } +} diff --git a/test/Loader/SiteKitResourceHierarchyLoaderTest.php b/test/Loader/SiteKitResourceHierarchyLoaderTest.php index 7183a49..61a549a 100644 --- a/test/Loader/SiteKitResourceHierarchyLoaderTest.php +++ b/test/Loader/SiteKitResourceHierarchyLoaderTest.php @@ -6,6 +6,7 @@ use Atoolo\Resource\Exception\InvalidResourceException; use Atoolo\Resource\Loader\SiteKitResourceHierarchyLoader; +use Atoolo\Resource\Resource; use Atoolo\Resource\ResourceLoader; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -75,9 +76,9 @@ public function testLoadRoot(): void ); } - public function testLoadParent(): void + public function testLoadPrimaryParent(): void { - $parent = $this->hierarchyLoader->loadParent('/c.php'); + $parent = $this->hierarchyLoader->loadPrimaryParent('/c.php'); $this->assertEquals( 'b', @@ -120,9 +121,9 @@ public function testLoadWithoutChildren(): void ); } - public function testLoadPath(): void + public function testLoadPrimaryPath(): void { - $path = $this->hierarchyLoader->loadPath('/c.php'); + $path = $this->hierarchyLoader->loadPrimaryPath('/c.php'); $pathIdList = array_map(function ($resource) { return $resource->getId(); @@ -135,28 +136,32 @@ public function testLoadPath(): void ); } - public function testLoadParentWithoutParent(): void + public function testLoadPrimaryParentWithoutParent(): void { - $parent = $this->hierarchyLoader->loadParent('/a.php'); + $parent = $this->hierarchyLoader->loadPrimaryParent('/a.php'); $this->assertNull($parent, 'parent should be null'); } public function testLoadRootResourcePrimaryParentWithoutUrl(): void { $this->expectException(InvalidResourceException::class); - $this->hierarchyLoader->loadParent('/primaryParentWithoutUrl.php'); + $this->hierarchyLoader->loadPrimaryParent( + '/primaryParentWithoutUrl.php' + ); } public function testLoadRootResourcePrimaryParentWithInvalidData(): void { $this->expectException(InvalidResourceException::class); - $this->hierarchyLoader->loadParent('/primaryParentWithInvalidData.php'); + $this->hierarchyLoader->loadPrimaryParent( + '/primaryParentWithInvalidData.php' + ); } public function testLoadRootResourcePrimaryParentWithNonStringUrl(): void { $this->expectException(InvalidResourceException::class); - $this->hierarchyLoader->loadParent( + $this->hierarchyLoader->loadPrimaryParent( '/primaryParentWithNonStringUrl.php' ); } @@ -164,13 +169,133 @@ public function testLoadRootResourcePrimaryParentWithNonStringUrl(): void public function testLoadRootResourceFirstParentWithoutUrl(): void { $this->expectException(InvalidResourceException::class); - $this->hierarchyLoader->loadParent('/firstParentWithoutUrl.php'); + $this->hierarchyLoader->loadPrimaryParent( + '/firstParentWithoutUrl.php' + ); } public function testLoadRootResourceFirstParentWithNonStringUrl(): void { $this->expectException(InvalidResourceException::class); - $this->hierarchyLoader->loadParent('/firstParentWithNonStringUrl.php'); + $this->hierarchyLoader->loadPrimaryParent( + '/firstParentWithNonStringUrl.php' + ); + } + + public function testLoadParent(): void + { + $parent = $this->hierarchyLoader->loadParent( + '/b.php', + 'a' + ); + $this->assertEquals( + 'a', + $parent->getId(), + 'unexpected parent' + ); + } + + public function testLoadParentIdNotFound(): void + { + $parent = $this->hierarchyLoader->loadParent( + '/b.php', + 'x' + ); + $this->assertNull( + $parent, + 'parent should be null' + ); + } + + public function testLoadParentOfRoot(): void + { + $parent = $this->hierarchyLoader->loadParent( + '/a.php', + 'x' + ); + $this->assertNull( + $parent, + 'parent should be null' + ); + } + + public function testGetParentLocationWithoutParents(): void + { + $resource = new Resource( + '', + '', + '', + '', + [] + ); + $parent = $this->hierarchyLoader->getParentLocation( + $resource, + 'x' + ); + $this->assertNull( + $parent, + 'parent should be null' + ); + } + + public function testGetParentLocationWithInvalidData(): void + { + $resource = new Resource( + '', + '', + '', + '', + [ + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => 'invalid' + ] + ] + ] + ] + ] + ); + + $this->expectException(InvalidResourceException::class); + $this->hierarchyLoader->getParentLocation( + $resource, + 'x' + ); + } + + public function testGetParentLocationWithParentIdNotFound(): void + { + $resource = new Resource( + '', + '', + '', + '', + [ + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => [ + 'id' => 'a', + 'url' => '/a.php' + ] + ] + ] + ] + ] + ] + ); + + $parent = $this->hierarchyLoader->getParentLocation( + $resource, + 'x' + ); + $this->assertNull( + $parent, + 'parent should be null' + ); } public function testFindRecursive(): void diff --git a/test/ResourceHierarchyFinderTest.php b/test/ResourceHierarchyFinderTest.php new file mode 100644 index 0000000..13b3cfa --- /dev/null +++ b/test/ResourceHierarchyFinderTest.php @@ -0,0 +1,91 @@ +loader = $this->createStub( + ResourceLoader::class + ); + $this->loader->method('load') + ->willReturnCallback(static function ($location) use ( + $resourceBaseDir + ) { + return include $resourceBaseDir . $location; + }); + + $hierarchyLoader = new SiteKitResourceHierarchyLoader( + $this->loader, + 'category' + ); + $this->finder = new ResourceHierarchyFinder( + $hierarchyLoader + ); + } + + public function testFindFirst(): void + { + $resource = $this->finder->findFirst( + '/a.php', + static function ($resource) { + return $resource->getId() === 'c'; + } + ); + + $this->assertEquals( + 'c', + $resource->getId(), + 'Resource c should be found' + ); + } + + public function testFindFirstFindBase(): void + { + $resource = $this->finder->findFirst( + '/a.php', + static function ($resource) { + return $resource->getId() === 'a'; + } + ); + + $this->assertEquals( + 'a', + $resource->getId(), + 'Resource a should be found' + ); + } + + public function testFindFirstNotFound(): void + { + $resource = $this->finder->findFirst( + '/a.php', + static function ($resource) { + return $resource->getId() === 'x'; + } + ); + + $this->assertNull( + $resource, + 'Resource should not be found' + ); + } +} diff --git a/test/ResourceHierarchyWalkerTest.php b/test/ResourceHierarchyWalkerTest.php new file mode 100644 index 0000000..bc8be44 --- /dev/null +++ b/test/ResourceHierarchyWalkerTest.php @@ -0,0 +1,438 @@ +loader = $this->createStub( + ResourceLoader::class + ); + $this->loader->method('load') + ->willReturnCallback(static function ($location) use ( + $resourceBaseDir + ) { + return include $resourceBaseDir . $location; + }); + + $hierarchyLoader = new SiteKitResourceHierarchyLoader( + $this->loader, + 'category' + ); + + $this->walker = new ResourceHierarchyWalker( + $hierarchyLoader + ); + } + + public function testInitWithLocation(): void + { + $this->walker->init('/1.php'); + + $this->assertEquals( + '1', + $this->walker->getCurrent()->getId(), + 'base resource should be found' + ); + } + + public function testGetCurrentWithoutInit(): void + { + $this->expectException(LogicException::class); + $this->walker->getCurrent(); + } + + public function testInitWithResource(): void + { + $base = $this->loader->load('/1.php'); + $this->walker->init($base); + + $this->assertEquals( + '1', + $this->walker->getCurrent()->getId(), + 'base resource should be found' + ); + } + + public function testPrimaryParent(): void + { + $base = $this->loader->load('/1/1.php'); + $this->walker->init($base); + + $this->walker->primaryParent(); + + $this->assertEquals( + '1', + $this->walker->getCurrent()->getId(), + 'unexpected primary parent' + ); + } + + public function testPrimaryParentWithoutInit(): void + { + $this->expectException(LogicException::class); + $this->walker->primaryParent(); + } + + public function testPrimaryParentOfRoot(): void + { + $base = $this->loader->load('/root.php'); + $this->walker->init($base); + + $this->assertNull( + $this->walker->primaryParent(), + 'root should not have a primary parent' + ); + } + + /** + * @throws Exception + */ + public function testPrimaryParentWithoutPrimaryParent(): void + { + $hierarchyLoader = $this->createStub( + ResourceHierarchyLoader::class + ); + $hierarchyLoader->method('getPrimaryParentLocation') + ->willReturn(null); + + $walker = new ResourceHierarchyWalker( + $hierarchyLoader + ); + $base = $this->createStub(Resource::class); + + $walker->init($base); + + $this->assertNull( + $walker->primaryParent(), + 'root should not have a primary parent' + ); + } + + public function testParent(): void + { + $base = $this->loader->load('/1/1.php'); + $this->walker->init($base); + + $this->walker->parent('2'); + + $this->assertEquals( + '2', + $this->walker->getCurrent()->getId(), + 'unexpected secondary parent' + ); + } + + public function testParentWithoutInit(): void + { + $this->expectException(LogicException::class); + $this->walker->parent('1'); + } + + public function testParentOfRoot(): void + { + $base = $this->loader->load('/root.php'); + $this->walker->init($base); + + $this->assertNull( + $this->walker->parent('1'), + 'root should not have a primary parent' + ); + } + + /** + * @throws Exception + */ + public function testParentWithoutPrimaryParent(): void + { + $hierarchyLoader = $this->createStub( + ResourceHierarchyLoader::class + ); + $hierarchyLoader->method('getPrimaryParentLocation') + ->willReturn(null); + + $walker = new ResourceHierarchyWalker( + $hierarchyLoader + ); + $base = $this->createStub(Resource::class); + + $walker->init($base); + + $this->assertNull( + $walker->parent('1'), + 'root should not have a primary parent' + ); + } + + public function testGetLevel(): void + { + $base = $this->loader->load('/1.php'); + $this->walker->init($base); + $this->walker->down(); + + $this->assertEquals( + 1, + $this->walker->getLevel(), + 'level should be 1' + ); + } + + public function testGetPath(): void + { + $base = $this->loader->load('/1.php'); + $this->walker->init($base); + $this->walker->down(); + + $expected = ['1', '1-1']; + + $this->assertEquals( + $expected, + array_map( + static fn($resource) => $resource->getId(), + $this->walker->getPath() + ), + 'unexpected path' + ); + } + + public function testGetPathWithoutInit(): void + { + $this->assertEmpty( + $this->walker->getPath(), + 'path should be empty' + ); + } + + public function testNextSibling(): void + { + $base = $this->loader->load('/root.php'); + $this->walker->init($base); + $this->walker->down(); + $this->walker->nextSibling(); + + $this->assertEquals( + '2', + $this->walker->getCurrent()->getId(), + 'unexpected sibling' + ); + } + + public function testNextSiblingWithoutInit(): void + { + $this->assertNull( + $this->walker->nextSibling(), + 'nextSibling should be null' + ); + } + + public function testPreviousSibling(): void + { + $base = $this->loader->load('/root.php'); + $this->walker->init($base); + $this->walker->down(); + $this->walker->nextSibling(); + $this->walker->previousSibling(); + + $this->assertEquals( + '1', + $this->walker->getCurrent()->getId(), + 'unexpected sibling' + ); + } + + public function testPreviousSiblingWithoutInit(): void + { + $this->assertNull( + $this->walker->previousSibling(), + 'previousSibling should be null' + ); + } + + public function testPreviousSiblingWithFirstChild(): void + { + $base = $this->loader->load('/root.php'); + $this->walker->init($base); + $this->walker->down(); + $this->walker->previousSibling(); + + $this->assertNull( + $this->walker->previousSibling(), + 'previousSibling should be null' + ); + } + + public function testUp(): void + { + $base = $this->loader->load('/root.php'); + $this->walker->init($base); + $this->walker->down(); + $this->walker->up(); + + $this->assertEquals( + 'root', + $this->walker->getCurrent()->getId(), + 'unexpected current resource' + ); + } + + public function testUpWithoutInit(): void + { + $this->expectException(LogicException::class); + $this->walker->up(); + } + + public function testUpForFirstLevel(): void + { + $base = $this->loader->load('/root.php'); + $this->walker->init($base); + + $this->assertNull( + $this->walker->up(), + 'up should be null' + ); + } + + public function testDown(): void + { + $base = $this->loader->load('/root.php'); + $this->walker->init($base); + $this->walker->down(); + + $this->assertEquals( + '1', + $this->walker->getCurrent()->getId(), + 'unexpected current resource' + ); + } + + public function testDownWithoutInit(): void + { + $this->expectException(LogicException::class); + $this->walker->down(); + } + + public function testChild(): void + { + $base = $this->loader->load('/root.php'); + $this->walker->init($base); + $this->walker->child('2'); + + $this->assertEquals( + '2', + $this->walker->getCurrent()->getId(), + 'unexpected current resource' + ); + } + + public function testChildNotFound(): void + { + $base = $this->loader->load('/root.php'); + $this->walker->init($base); + + $this->assertNull( + $this->walker->child('7'), + 'child should be null' + ); + } + + public function testChildWithoutInit(): void + { + $this->expectException(LogicException::class); + $this->walker->child('2'); + } + + /** + * @throws Exception + */ + public function testChildWithoutChildren(): void + { + $hierarchyLoader = $this->createStub( + ResourceHierarchyLoader::class + ); + $hierarchyLoader->method('getChildrenLocations') + ->willReturn([]); + + $walker = new ResourceHierarchyWalker( + $hierarchyLoader + ); + $base = $this->createStub(Resource::class); + + $walker->init($base); + + $this->assertNull( + $walker->child('1'), + 'child should be null' + ); + } + + public function testNext(): void + { + $base = $this->loader->load('/root.php'); + $this->walker->init($base); + $this->walker->next(); + + $this->assertEquals( + '1', + $this->walker->getCurrent()->getId(), + 'unexpected current resource' + ); + } + + public function testNextWithoutInit(): void + { + $this->expectException(LogicException::class); + $this->walker->next(); + } + + public function testWalk(): void + { + $root = $this->loader->load('/root.php'); + $this->walker->init($root); + + $idList = []; + $this->walker->walk($root, function ($resource) use (&$idList) { + $idList[] = $resource->getId(); + }); + + $expected = [ + 'root', + '1', + '1-1', + '1-1-1', + '1-1-1-1', + '2', + '2-1', + '2-2', + ]; + $this->assertEquals( + $expected, + $idList, + 'unexpected id list' + ); + } +} diff --git a/test/resources/ResourceHierarchyFinder/a.php b/test/resources/ResourceHierarchyFinder/a.php new file mode 100644 index 0000000..fe83764 --- /dev/null +++ b/test/resources/ResourceHierarchyFinder/a.php @@ -0,0 +1,24 @@ + [ + 'trees' => [ + 'category' => [ + 'children' => [ + 'b' => [ + 'id' => 'b', + 'url' => '/b.php' + ] + ] + ] + ] + ] + ] +); diff --git a/test/resources/ResourceHierarchyFinder/b.php b/test/resources/ResourceHierarchyFinder/b.php new file mode 100644 index 0000000..ed98223 --- /dev/null +++ b/test/resources/ResourceHierarchyFinder/b.php @@ -0,0 +1,29 @@ + [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => [ + 'url' => '/a.php' + ] + ], + 'children' => [ + 'c' => [ + 'id' => 'c', + 'url' => '/c.php' + ] + ] + ] + ] + ] + ] +); diff --git a/test/resources/ResourceHierarchyFinder/c.php b/test/resources/ResourceHierarchyFinder/c.php new file mode 100644 index 0000000..4b326dc --- /dev/null +++ b/test/resources/ResourceHierarchyFinder/c.php @@ -0,0 +1,27 @@ + [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'b' => [ + 'isPrimary' => true, + 'url' => '/b.php' + ], + 'a' => [ + 'url' => '/a.php' + ] + ] + ] + ] + ] + ] +); diff --git a/test/resources/ResourceHierarchyWalker/1.php b/test/resources/ResourceHierarchyWalker/1.php new file mode 100644 index 0000000..f715ed6 --- /dev/null +++ b/test/resources/ResourceHierarchyWalker/1.php @@ -0,0 +1,29 @@ + [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'root' => [ + 'url' => '/root.php' + ] + ], + 'children' => [ + '1-1' => [ + 'id' => '1-1', + 'url' => '/1/1.php' + ] + ] + ] + ] + ] + ] +); diff --git a/test/resources/ResourceHierarchyWalker/1/1.php b/test/resources/ResourceHierarchyWalker/1/1.php new file mode 100644 index 0000000..f310d50 --- /dev/null +++ b/test/resources/ResourceHierarchyWalker/1/1.php @@ -0,0 +1,32 @@ + [ + 'trees' => [ + 'category' => [ + 'parents' => [ + '1' => [ + 'url' => '/1.php' + ], + '2' => [ + 'url' => '/2.php' + ] + ], + 'children' => [ + '1-1-1' => [ + 'id' => '1-1-1', + 'url' => '/1/1/1.php' + ] + ] + ] + ] + ] + ] +); diff --git a/test/resources/ResourceHierarchyWalker/1/1/1.php b/test/resources/ResourceHierarchyWalker/1/1/1.php new file mode 100644 index 0000000..95131cd --- /dev/null +++ b/test/resources/ResourceHierarchyWalker/1/1/1.php @@ -0,0 +1,29 @@ + [ + 'trees' => [ + 'category' => [ + 'parents' => [ + '1-1' => [ + 'url' => '/1/1.php' + ] + ], + 'children' => [ + '1-1-1-1' => [ + 'id' => '1-1-1-1', + 'url' => '/1/1/1/1.php' + ] + ] + ] + ] + ] + ] +); diff --git a/test/resources/ResourceHierarchyWalker/1/1/1/1.php b/test/resources/ResourceHierarchyWalker/1/1/1/1.php new file mode 100644 index 0000000..22899f0 --- /dev/null +++ b/test/resources/ResourceHierarchyWalker/1/1/1/1.php @@ -0,0 +1,23 @@ + [ + 'trees' => [ + 'category' => [ + 'parents' => [ + '1-1-1' => [ + 'url' => '/1/1/1.php' + ] + ], + ] + ] + ] + ] +); diff --git a/test/resources/ResourceHierarchyWalker/2.php b/test/resources/ResourceHierarchyWalker/2.php new file mode 100644 index 0000000..3c56a48 --- /dev/null +++ b/test/resources/ResourceHierarchyWalker/2.php @@ -0,0 +1,33 @@ + [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'root' => [ + 'url' => '/root.php' + ] + ], + 'children' => [ + '2-1' => [ + 'id' => '2-1', + 'url' => '/2/1.php' + ], + '2-2' => [ + 'id' => '2-2', + 'url' => '/2/2.php' + ] + ] + ] + ] + ] + ] +); diff --git a/test/resources/ResourceHierarchyWalker/2/1.php b/test/resources/ResourceHierarchyWalker/2/1.php new file mode 100644 index 0000000..334d15e --- /dev/null +++ b/test/resources/ResourceHierarchyWalker/2/1.php @@ -0,0 +1,23 @@ + [ + 'trees' => [ + 'category' => [ + 'parents' => [ + '2' => [ + 'url' => '/2.php' + ] + ] + ] + ] + ] + ] +); diff --git a/test/resources/ResourceHierarchyWalker/2/2.php b/test/resources/ResourceHierarchyWalker/2/2.php new file mode 100644 index 0000000..959eb0b --- /dev/null +++ b/test/resources/ResourceHierarchyWalker/2/2.php @@ -0,0 +1,23 @@ + [ + 'trees' => [ + 'category' => [ + 'parents' => [ + '2' => [ + 'url' => '/2.php' + ] + ] + ] + ] + ] + ] +); diff --git a/test/resources/ResourceHierarchyWalker/root.php b/test/resources/ResourceHierarchyWalker/root.php new file mode 100644 index 0000000..c44081f --- /dev/null +++ b/test/resources/ResourceHierarchyWalker/root.php @@ -0,0 +1,28 @@ + [ + 'trees' => [ + 'category' => [ + 'children' => [ + '1 1' => [ + 'id' => '1', + 'url' => '/1.php' + ], + '2' => [ + 'id' => '2', + 'url' => '/2.php' + ] + ] + ] + ] + ] + ] +); From a3da45469e3b6e226fbd595c45765a1aaedbe233 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 4 Apr 2024 14:08:35 +0200 Subject: [PATCH 12/31] refactor: findRecursive replaced --- src/Loader/SiteKitResourceHierarchyLoader.php | 40 ------------------- .../SiteKitResourceHierarchyLoaderTest.php | 31 -------------- 2 files changed, 71 deletions(-) diff --git a/src/Loader/SiteKitResourceHierarchyLoader.php b/src/Loader/SiteKitResourceHierarchyLoader.php index 1fa1e96..ad79fac 100644 --- a/src/Loader/SiteKitResourceHierarchyLoader.php +++ b/src/Loader/SiteKitResourceHierarchyLoader.php @@ -95,46 +95,6 @@ public function loadChildren(string $location): array return $children; } - /** - * Walks the tree of resources starting from the given location and calls - * the given function for each resource. Returns the resource where the - * callable returns true. - * - * The callable function expects the following parameter: - * - Resource: the current resource - * - * The callable function should return true if the current resource is the - * one we are looking for. - * - * @param callable(Resource): bool $fn - * @throws InvalidResourceException - * @throws ResourceNotFoundException - */ - public function findRecursive( - string $location, - callable $fn, - ): ?Resource { - - $resource = $this->resourceLoader->load($location); - - if ($fn($resource) === true) { - return $resource; - } - - $childrenLocationList = $this->getChildrenLocations($resource); - foreach ($childrenLocationList as $childLocation) { - $result = $this->findRecursive( - $childLocation, - $fn - ); - if ($result !== null) { - return $result; - } - } - - return null; - } - /** * @throws InvalidResourceException if no primary parent can be found * @throws ResourceNotFoundException diff --git a/test/Loader/SiteKitResourceHierarchyLoaderTest.php b/test/Loader/SiteKitResourceHierarchyLoaderTest.php index 61a549a..1d62588 100644 --- a/test/Loader/SiteKitResourceHierarchyLoaderTest.php +++ b/test/Loader/SiteKitResourceHierarchyLoaderTest.php @@ -297,35 +297,4 @@ public function testGetParentLocationWithParentIdNotFound(): void 'parent should be null' ); } - - public function testFindRecursive(): void - { - $resource = $this->hierarchyLoader->findRecursive( - '/a.php', - static function ($resource) { - return $resource->getId() === 'c'; - } - ); - - $this->assertEquals( - 'c', - $resource->getId(), - 'unexpected resource' - ); - } - - public function testFindRecursiveNotFound(): void - { - $resource = $this->hierarchyLoader->findRecursive( - '/a.php', - static function ($resource) { - return $resource->getId() === 'not-existing'; - } - ); - - $this->assertNull( - $resource, - 'resource should be null' - ); - } } From 2e83a278f747c3174cde85b8029e0425578a62b4 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 4 Apr 2024 14:43:15 +0200 Subject: [PATCH 13/31] docs: add ResourceHierarchyWalker class doc --- src/ResourceHierarchyWalker.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/ResourceHierarchyWalker.php b/src/ResourceHierarchyWalker.php index aa44006..a5137a2 100644 --- a/src/ResourceHierarchyWalker.php +++ b/src/ResourceHierarchyWalker.php @@ -6,6 +6,29 @@ use LogicException; +/** + * The `ResourceHierarchyWalker` class is used to traverse a hierarchy of + * resources. + * + * The walker needs a base resource to start with. This can be set with + * `init()`. + * + * The walker can then be moved up and down in the hierarchy + * with the help of methods like + * - `down()` + * - `child()` + * - `up()` + * - `nextSibling()` + * - `previousSibling()` + * - `next()` + * + * With these methods, the walker can only move below the base resource. + * To move above the base resource, the methods `primaryParent()` + * and `parent()` can be used. + * + * The walker can also be used to traverse the entire hierarchy + * with the help of the `walk()` method. + */ class ResourceHierarchyWalker { private ?Resource $current = null; From 1b673701ab0396180ba4f1da7b6ed5daf152b29b Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 4 Apr 2024 15:28:46 +0200 Subject: [PATCH 14/31] refactor: ResourceHierarchyLoader extends ResourceLoader --- .../SiteKitNavigationHierarchyLoader.php | 6 +-- src/Loader/SiteKitResourceHierarchyLoader.php | 18 ++++++--- src/ResourceHierarchyLoader.php | 7 +--- src/ResourceHierarchyWalker.php | 2 +- .../SiteKitResourceHierarchyLoaderTest.php | 37 ++++++++++++++++--- 5 files changed, 49 insertions(+), 21 deletions(-) diff --git a/src/Loader/SiteKitNavigationHierarchyLoader.php b/src/Loader/SiteKitNavigationHierarchyLoader.php index 389047e..021835a 100644 --- a/src/Loader/SiteKitNavigationHierarchyLoader.php +++ b/src/Loader/SiteKitNavigationHierarchyLoader.php @@ -32,7 +32,7 @@ protected function loadPrimaryParentResource(Resource $resource): Resource if ($parentLocation === null) { return $this->loadDefaultRootResource($resource); } - return $this->getResourceLoader()->load($parentLocation); + return $this->load($parentLocation); } /** @@ -53,8 +53,8 @@ private function loadDefaultRootResource(Resource $resource): Resource } else { $location = $dir . '/index.php'; } - if ($this->getResourceLoader()->exists($location)) { - $root = $this->getResourceLoader()->load($location); + if ($this->exists($location)) { + $root = $this->load($location); if ($this->isRoot($root)) { return $root; } diff --git a/src/Loader/SiteKitResourceHierarchyLoader.php b/src/Loader/SiteKitResourceHierarchyLoader.php index ad79fac..b7cb46d 100644 --- a/src/Loader/SiteKitResourceHierarchyLoader.php +++ b/src/Loader/SiteKitResourceHierarchyLoader.php @@ -18,6 +18,19 @@ public function __construct( ) { } + /** + * @throws InvalidResourceException + * @throws ResourceNotFoundException + */ + public function load(string $location): Resource + { + return $this->resourceLoader->load($location); + } + + public function exists(string $location): bool + { + return $this->resourceLoader->exists($location); + } /** * @throws InvalidResourceException * @throws ResourceNotFoundException @@ -123,11 +136,6 @@ protected function loadParentResource( return $this->resourceLoader->load($parentLocation); } - public function getResourceLoader(): ResourceLoader - { - return $this->resourceLoader; - } - public function isRoot(Resource $resource): bool { $parentList = $resource->getData()->getAssociativeArray( diff --git a/src/ResourceHierarchyLoader.php b/src/ResourceHierarchyLoader.php index f2e453e..0d737e7 100644 --- a/src/ResourceHierarchyLoader.php +++ b/src/ResourceHierarchyLoader.php @@ -12,7 +12,7 @@ * resources or nodes whose hierarchical structure is defined in the resources. * For example, the navigation tree. */ -interface ResourceHierarchyLoader +interface ResourceHierarchyLoader extends ResourceLoader { /** * Determines the root resource via the parent links contained in the @@ -81,9 +81,4 @@ public function getParentLocation( Resource $resource, string $parentId ): ?string; - - /** - * Returns the `ResourceLoader` instance used to load resources. - */ - public function getResourceLoader(): ResourceLoader; } diff --git a/src/ResourceHierarchyWalker.php b/src/ResourceHierarchyWalker.php index a5137a2..80bbaff 100644 --- a/src/ResourceHierarchyWalker.php +++ b/src/ResourceHierarchyWalker.php @@ -430,6 +430,6 @@ public function walk(Resource $base, callable $fn): void private function load(string $location): Resource { - return $this->hierarchyLoader->getResourceLoader()->load($location); + return $this->hierarchyLoader->load($location); } } diff --git a/test/Loader/SiteKitResourceHierarchyLoaderTest.php b/test/Loader/SiteKitResourceHierarchyLoaderTest.php index 1d62588..bcfe12c 100644 --- a/test/Loader/SiteKitResourceHierarchyLoaderTest.php +++ b/test/Loader/SiteKitResourceHierarchyLoaderTest.php @@ -9,6 +9,7 @@ use Atoolo\Resource\Resource; use Atoolo\Resource\ResourceLoader; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\TestCase; #[CoversClass(SiteKitResourceHierarchyLoader::class)] @@ -45,14 +46,38 @@ private function createLoader(string $className) ); } - public function testGetResourceLoader(): void + /** + * @throws Exception + */ + public function testLoad(): void { - $class = new \ReflectionClass(SiteKitResourceHierarchyLoader::class); - $method = $class->getMethod('getResourceLoader'); - $this->assertNotNull( - $method->invoke($this->hierarchyLoader), - 'getResourceLoader should return the resource-loader' + $resourceLoader = $this->createMock(ResourceLoader::class); + $hierarchyLoader = new SiteKitResourceHierarchyLoader( + $resourceLoader, + 'category' + ); + + $resourceLoader->expects($this->once()) + ->method('load'); + + $hierarchyLoader->load('/a.php'); + } + + /** + * @throws Exception + */ + public function testExists(): void + { + $resourceLoader = $this->createMock(ResourceLoader::class); + $hierarchyLoader = new SiteKitResourceHierarchyLoader( + $resourceLoader, + 'category' ); + + $resourceLoader->expects($this->once()) + ->method('exists'); + + $hierarchyLoader->exists('/a.php'); } public function testLoadPrimaryParentResourceWithoutParent(): void From b5ad318147545dbf43f9f37efbf3e9cb0aac2101 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Wed, 10 Apr 2024 15:38:28 +0200 Subject: [PATCH 15/31] feat: allow string for ResourceHierarchyWalker::walk --- src/Loader/CachedResourceLoader.php | 1 + src/ResourceHierarchyWalker.php | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Loader/CachedResourceLoader.php b/src/Loader/CachedResourceLoader.php index c8e8f61..dcb1c2a 100644 --- a/src/Loader/CachedResourceLoader.php +++ b/src/Loader/CachedResourceLoader.php @@ -12,6 +12,7 @@ /** * The CachedResourceLoader class is used to load resources * from a given location and cache them for future use. + * The cache is stored in memory and is not persistent. */ class CachedResourceLoader implements ResourceLoader { diff --git a/src/ResourceHierarchyWalker.php b/src/ResourceHierarchyWalker.php index a22e3ca..cc2e318 100644 --- a/src/ResourceHierarchyWalker.php +++ b/src/ResourceHierarchyWalker.php @@ -414,12 +414,13 @@ public function next(): ?Resource * In the method, `init($base)` is called, which resets the walker * if necessary. Here `next()` is used to traverse the hierarchy. * - * @param Resource $base The resource from which the hierarchy is to - * be traversed. + * @param Resource|string $base The resource to be used initially. + * * If `$base` is a string it is assumed that it is a location and + * * the resource is loaded. * @param callable(Resource): void $fn The method to be called for each * resource. */ - public function walk(Resource $base, callable $fn): void + public function walk(Resource|string $base, callable $fn): void { $this->init($base); $fn($base); From f0981a579efecbcaff394426209cfe1ba3acbdea Mon Sep 17 00:00:00 2001 From: Holger Veltrup <92872893+sitepark-veltrup@users.noreply.github.com> Date: Thu, 11 Apr 2024 08:38:23 +0200 Subject: [PATCH 16/31] Update src/Loader/SiteKitLoader.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mario Schäper <95750382+sitepark-schaeper@users.noreply.github.com> --- src/Loader/SiteKitLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Loader/SiteKitLoader.php b/src/Loader/SiteKitLoader.php index 48fecb1..fe96ad9 100644 --- a/src/Loader/SiteKitLoader.php +++ b/src/Loader/SiteKitLoader.php @@ -29,7 +29,7 @@ class SiteKitLoader implements ResourceLoader { /** - * @var array|null + * @var ?array $langLocaleMap */ private ?array $langLocaleMap = null; From 79d05cd4cd4aa0a02fdc6eee76337c0e17022ac8 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 11 Apr 2024 08:21:57 +0200 Subject: [PATCH 17/31] fix: phpstan error --- src/ResourceHierarchyWalker.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ResourceHierarchyWalker.php b/src/ResourceHierarchyWalker.php index cc2e318..55fc061 100644 --- a/src/ResourceHierarchyWalker.php +++ b/src/ResourceHierarchyWalker.php @@ -422,6 +422,9 @@ public function next(): ?Resource */ public function walk(Resource|string $base, callable $fn): void { + if (is_string($base)) { + $base = $this->load($base); + } $this->init($base); $fn($base); while ($current = $this->next()) { From c91dac554db11d4e339e2582d324534c057316a7 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 11 Apr 2024 08:34:17 +0200 Subject: [PATCH 18/31] refactor: use shortened syntax --- src/Loader/CachedResourceLoader.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Loader/CachedResourceLoader.php b/src/Loader/CachedResourceLoader.php index dcb1c2a..1fa7c05 100644 --- a/src/Loader/CachedResourceLoader.php +++ b/src/Loader/CachedResourceLoader.php @@ -32,13 +32,10 @@ public function __construct( public function load(string $location, string $lang = ''): Resource { $key = $this->getKey($location, $lang); - if (isset($this->cache[$key])) { - return $this->cache[$key]; - } - - $resource = $this->resourceLoader->load($location, $lang); - $this->cache[$key] = $resource; - return $resource; + return $this->cache[$key] ??= $this->resourceLoader->load( + $location, + $lang + ); } public function exists(string $location, string $lang = ''): bool From 3a3c266dfab7c81d525d9d3e4ed171ed2c85b64b Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 11 Apr 2024 08:36:43 +0200 Subject: [PATCH 19/31] refactor: make code easier to understand --- src/Loader/ServerVarResourceBaseLocator.php | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/Loader/ServerVarResourceBaseLocator.php b/src/Loader/ServerVarResourceBaseLocator.php index cd3ff2a..04d1d12 100644 --- a/src/Loader/ServerVarResourceBaseLocator.php +++ b/src/Loader/ServerVarResourceBaseLocator.php @@ -28,21 +28,16 @@ public function locate(): string ); } - $resourceLayoutResourceBase = $_SERVER[$this->variableName] . - '/objects'; - if (is_dir($resourceLayoutResourceBase)) { - $this->resourceBase = $resourceLayoutResourceBase; - return $resourceLayoutResourceBase; + $base = $_SERVER[$this->variableName]; + $baseObjects = $base . DIRECTORY_SEPARATOR . 'objects'; + if (is_dir($baseObjects)) { + return $this->resourceBase = $baseObjects; } - - if (is_dir($_SERVER[$this->variableName])) { - $this->resourceBase = $_SERVER[$this->variableName]; - return $_SERVER[$this->variableName]; + if (is_dir($base)) { + return $this->resourceBase = $base; } - throw new RuntimeException( - "Resource root directory not found: " . - $_SERVER[$this->variableName] + 'Resource root directory not found: ' . $base ); } } From 5d5f3c64b91ad2c342c9bd128a7f4cd9b666c5ad Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 11 Apr 2024 09:12:12 +0200 Subject: [PATCH 20/31] refactor: rename $resourceChannel to $resourceChannelFactory --- src/Loader/SiteKitLoader.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Loader/SiteKitLoader.php b/src/Loader/SiteKitLoader.php index fe96ad9..6340059 100644 --- a/src/Loader/SiteKitLoader.php +++ b/src/Loader/SiteKitLoader.php @@ -35,7 +35,7 @@ class SiteKitLoader implements ResourceLoader public function __construct( private readonly ResourceBaseLocator $baseLocator, - private readonly ResourceChannelFactory $resourceChannel, + private readonly ResourceChannelFactory $resourceChannelFactory, ) { } @@ -161,7 +161,7 @@ private function langToLocale(string $lang): string private function createLangLocaleMap(): array { $map = []; - $resourceChannel = $this->resourceChannel->create(); + $resourceChannel = $this->resourceChannelFactory->create(); foreach ( $resourceChannel->translationLocales as $availableLocale ) { From 315944be4203fa891e1d2713c227e469b1ffa0b7 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 11 Apr 2024 09:13:06 +0200 Subject: [PATCH 21/31] refactor: call $this->baseLocator->locate() in constructor --- src/Loader/SiteKitLoader.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Loader/SiteKitLoader.php b/src/Loader/SiteKitLoader.php index 6340059..3351a6f 100644 --- a/src/Loader/SiteKitLoader.php +++ b/src/Loader/SiteKitLoader.php @@ -33,10 +33,13 @@ class SiteKitLoader implements ResourceLoader */ private ?array $langLocaleMap = null; + private string $resourceBase; + public function __construct( private readonly ResourceBaseLocator $baseLocator, private readonly ResourceChannelFactory $resourceChannelFactory, ) { + $this->resourceBase = $this->baseLocator->locate(); } /** @@ -74,7 +77,7 @@ public function exists(string $location, string $lang = ''): bool private function locationToFile(string $location, string $lang): string { - $file = $this->baseLocator->locate() . '/' . $location; + $file = $this->resourceBase . '/' . $location; $locale = $this->langToLocale($lang); if (empty($locale)) { return $file; From 235f3909447819bcb86fabdc8218ad564b5036ef Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 11 Apr 2024 09:14:39 +0200 Subject: [PATCH 22/31] refactor: simplify code --- src/Loader/SiteKitLoader.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Loader/SiteKitLoader.php b/src/Loader/SiteKitLoader.php index 3351a6f..e59cb07 100644 --- a/src/Loader/SiteKitLoader.php +++ b/src/Loader/SiteKitLoader.php @@ -151,9 +151,7 @@ private function langToLocale(string $lang): string return $lang; } - if ($this->langLocaleMap === null) { - $this->langLocaleMap = $this->createLangLocaleMap(); - } + $this->langLocaleMap ??= $this->createLangLocaleMap(); return $this->langLocaleMap[$lang] ?? ''; } From b08052a5ccb3fce301d49ac7fdcf402b562ff6c4 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 11 Apr 2024 09:15:51 +0200 Subject: [PATCH 23/31] docs: fix doc --- src/ResourceChannel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResourceChannel.php b/src/ResourceChannel.php index ab094a2..1114436 100644 --- a/src/ResourceChannel.php +++ b/src/ResourceChannel.php @@ -10,7 +10,7 @@ * website, but also a preview or intranet channel, for example. * * These channels have certain properties that are mapped in this class. - * are mapped in this class. + * *@codeCoverageIgnore */ class ResourceChannel From 7afc5df5522ab1bdba748f930d0d19fbc8eb93e3 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 11 Apr 2024 09:22:08 +0200 Subject: [PATCH 24/31] refactor: rename ResourceChannel::preview to ResourceChannel:isPreview --- src/ResourceChannel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResourceChannel.php b/src/ResourceChannel.php index 1114436..f989b58 100644 --- a/src/ResourceChannel.php +++ b/src/ResourceChannel.php @@ -23,7 +23,7 @@ public function __construct( public readonly string $name, public readonly string $anchor, public readonly string $serverName, - public readonly bool $preview, + public readonly bool $isPreview, public readonly string $nature, public readonly string $locale, public readonly string $encoding, From 311d7a165eb46ca8f3623cc13596cc92e30e1513 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 11 Apr 2024 09:51:43 +0200 Subject: [PATCH 25/31] style: update newlines --- src/Loader/SiteKitLoader.php | 1 - src/SiteKitResourceChannelFactory.php | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Loader/SiteKitLoader.php b/src/Loader/SiteKitLoader.php index e59cb07..e972104 100644 --- a/src/Loader/SiteKitLoader.php +++ b/src/Loader/SiteKitLoader.php @@ -67,7 +67,6 @@ public function load(string $location, string $lang = ''): Resource ); } - public function exists(string $location, string $lang = ''): bool { return file_exists( diff --git a/src/SiteKitResourceChannelFactory.php b/src/SiteKitResourceChannelFactory.php index 2e19993..343cf33 100644 --- a/src/SiteKitResourceChannelFactory.php +++ b/src/SiteKitResourceChannelFactory.php @@ -76,6 +76,7 @@ private function loadContextPhpFile(): array /** @var ContextPhp $context */ return $context; } + private function findContextPhpFile(): string { $resourceBase = $this->resourceBaseLocator->locate(); From 9bd006871912f7cb0cb8bd3e8431d9e0abe65488 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 11 Apr 2024 09:58:17 +0200 Subject: [PATCH 26/31] refactor: SiteKitResourceChannelFactory::findContextPhpFile() --- src/SiteKitResourceChannelFactory.php | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/SiteKitResourceChannelFactory.php b/src/SiteKitResourceChannelFactory.php index 343cf33..9ce82c1 100644 --- a/src/SiteKitResourceChannelFactory.php +++ b/src/SiteKitResourceChannelFactory.php @@ -80,16 +80,22 @@ private function loadContextPhpFile(): array private function findContextPhpFile(): string { $resourceBase = $this->resourceBaseLocator->locate(); - if (file_exists($resourceBase . '/../context.php')) { - $contextPhpFile = dirname($resourceBase) . '/context.php'; - } else { - $contextPhpFile = $resourceBase . '/WEB-IES/context.php'; + $resourceLayoutContextPhpFile = dirname($resourceBase) . '/context.php'; + + if (file_exists($resourceLayoutContextPhpFile)) { + return $resourceLayoutContextPhpFile; } - if (!file_exists($contextPhpFile)) { + + $documentRootLayoutContextPhpFile = + $resourceBase . '/WEB-IES/context.php'; + + if (!file_exists($documentRootLayoutContextPhpFile)) { throw new RuntimeException( - 'context.php does not exists: ' . $contextPhpFile + 'context.php does not exists: ' . + $resourceLayoutContextPhpFile . ' or ' . + $documentRootLayoutContextPhpFile ); } - return $contextPhpFile; + return $documentRootLayoutContextPhpFile; } } From c1274655af8a40ec960978faa22e35e7104f4299 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Wed, 17 Apr 2024 16:09:44 +0200 Subject: [PATCH 27/31] refactor: remove ResourceBaseLocator --- src/Loader/ServerVarResourceBaseLocator.php | 43 -------- src/Loader/SiteKitLoader.php | 12 +-- src/Loader/StaticResourceBaseLocator.php | 19 ---- src/ResourceBaseLocator.php | 15 --- src/ResourceChannel.php | 3 +- src/SiteKitResourceChannelFactory.php | 35 +++--- .../ServerVarResourceBaseLocatorTest.php | 102 ------------------ test/Loader/SiteKitLoaderTest.php | 12 +-- test/Loader/StaticResourceBaseLocatorTest.php | 24 ----- test/ResourceHierarchyWalkerTest.php | 29 ++++- test/SiteKitResourceChannelFactoryTest.php | 58 +++------- 11 files changed, 66 insertions(+), 286 deletions(-) delete mode 100644 src/Loader/ServerVarResourceBaseLocator.php delete mode 100644 src/Loader/StaticResourceBaseLocator.php delete mode 100644 src/ResourceBaseLocator.php delete mode 100644 test/Loader/ServerVarResourceBaseLocatorTest.php delete mode 100644 test/Loader/StaticResourceBaseLocatorTest.php diff --git a/src/Loader/ServerVarResourceBaseLocator.php b/src/Loader/ServerVarResourceBaseLocator.php deleted file mode 100644 index 04d1d12..0000000 --- a/src/Loader/ServerVarResourceBaseLocator.php +++ /dev/null @@ -1,43 +0,0 @@ -resourceBase !== null) { - return $this->resourceBase; - } - - if (empty($_SERVER[$this->variableName])) { - throw new \RuntimeException( - 'missing server variable ' . $this->variableName - ); - } - - $base = $_SERVER[$this->variableName]; - $baseObjects = $base . DIRECTORY_SEPARATOR . 'objects'; - if (is_dir($baseObjects)) { - return $this->resourceBase = $baseObjects; - } - if (is_dir($base)) { - return $this->resourceBase = $base; - } - throw new RuntimeException( - 'Resource root directory not found: ' . $base - ); - } -} diff --git a/src/Loader/SiteKitLoader.php b/src/Loader/SiteKitLoader.php index e972104..4e16aad 100644 --- a/src/Loader/SiteKitLoader.php +++ b/src/Loader/SiteKitLoader.php @@ -10,6 +10,7 @@ use Atoolo\Resource\Loader\SiteKit\LifecylceStub; use Atoolo\Resource\Resource; use Atoolo\Resource\ResourceBaseLocator; +use Atoolo\Resource\ResourceChannel; use Atoolo\Resource\ResourceChannelFactory; use Atoolo\Resource\ResourceLoader; use Error; @@ -33,13 +34,9 @@ class SiteKitLoader implements ResourceLoader */ private ?array $langLocaleMap = null; - private string $resourceBase; - public function __construct( - private readonly ResourceBaseLocator $baseLocator, - private readonly ResourceChannelFactory $resourceChannelFactory, + private readonly ResourceChannel $resourceChannel ) { - $this->resourceBase = $this->baseLocator->locate(); } /** @@ -76,7 +73,7 @@ public function exists(string $location, string $lang = ''): bool private function locationToFile(string $location, string $lang): string { - $file = $this->resourceBase . '/' . $location; + $file = $this->resourceChannel->resourceDir . '/' . $location; $locale = $this->langToLocale($lang); if (empty($locale)) { return $file; @@ -161,9 +158,8 @@ private function langToLocale(string $lang): string private function createLangLocaleMap(): array { $map = []; - $resourceChannel = $this->resourceChannelFactory->create(); foreach ( - $resourceChannel->translationLocales as $availableLocale + $this->resourceChannel->translationLocales as $availableLocale ) { $primaryLang = Locale::getPrimaryLanguage($availableLocale); $map[$primaryLang] = $availableLocale; diff --git a/src/Loader/StaticResourceBaseLocator.php b/src/Loader/StaticResourceBaseLocator.php deleted file mode 100644 index 821c212..0000000 --- a/src/Loader/StaticResourceBaseLocator.php +++ /dev/null @@ -1,19 +0,0 @@ -resourceBase; - } -} diff --git a/src/ResourceBaseLocator.php b/src/ResourceBaseLocator.php deleted file mode 100644 index d7c3f04..0000000 --- a/src/ResourceBaseLocator.php +++ /dev/null @@ -1,15 +0,0 @@ -resourceChannel !== null) { - return $this->resourceChannel; - } + $this->determinePaths(); $data = $this->loadContextPhpFile(); @@ -44,7 +44,7 @@ public function create(): ResourceChannel '-', $data['publisher']['anchor'] ); - $this->resourceChannel = new ResourceChannel( + return new ResourceChannel( (string)$data['publisher']['id'], $data['publisher']['name'], $data['publisher']['anchor'], @@ -52,12 +52,11 @@ public function create(): ResourceChannel $data['publisher']['preview'], $data['publisher']['nature'], $data['publisher']['locale'] ?? 'de_DE', - $data['publisher']['encoding'] ?? 'UTF-8', + $this->baseDir, + $this->resourceDir, $searchIndex, $data['publisher']['translationLocales'] ?? [], ); - - return $this->resourceChannel; } /** @@ -65,8 +64,7 @@ public function create(): ResourceChannel */ private function loadContextPhpFile(): array { - $contextPhpFile = $this->findContextPhpFile(); - $context = require $contextPhpFile; + $context = require $this->contextPhpFile; if (!is_array($context)) { throw new RuntimeException( 'context.php must return an array' @@ -77,17 +75,18 @@ private function loadContextPhpFile(): array return $context; } - private function findContextPhpFile(): string + private function determinePaths(): void { - $resourceBase = $this->resourceBaseLocator->locate(); - $resourceLayoutContextPhpFile = dirname($resourceBase) . '/context.php'; + $resourceLayoutContextPhpFile = $this->baseDir . '/context.php'; if (file_exists($resourceLayoutContextPhpFile)) { - return $resourceLayoutContextPhpFile; + $this->contextPhpFile = $resourceLayoutContextPhpFile; + $this->resourceDir = $this->baseDir . '/objects'; + return; } $documentRootLayoutContextPhpFile = - $resourceBase . '/WEB-IES/context.php'; + $this->baseDir . '/WEB-IES/context.php'; if (!file_exists($documentRootLayoutContextPhpFile)) { throw new RuntimeException( @@ -96,6 +95,8 @@ private function findContextPhpFile(): string $documentRootLayoutContextPhpFile ); } - return $documentRootLayoutContextPhpFile; + + $this->contextPhpFile = $documentRootLayoutContextPhpFile; + $this->resourceDir = $this->baseDir; } } diff --git a/test/Loader/ServerVarResourceBaseLocatorTest.php b/test/Loader/ServerVarResourceBaseLocatorTest.php deleted file mode 100644 index 8e7ddf7..0000000 --- a/test/Loader/ServerVarResourceBaseLocatorTest.php +++ /dev/null @@ -1,102 +0,0 @@ - - */ - private array $saveServerState; - - public function setUp(): void - { - $this->saveServerState = $_SERVER; - } - - public function tearDown(): void - { - $_SERVER = $this->saveServerState; - } - - public function testWithDocumentRootLayout(): void - { - $baseLocation = - __DIR__ . - '/../resources/Loader/ServerVarResourceBaseLocator' . - '/documentRootLayout'; - $_SERVER['RESOURCE_ROOT'] = $baseLocation; - - $locator = new ServerVarResourceBaseLocator('RESOURCE_ROOT'); - $this->assertEquals( - $baseLocation, - $locator->locate(), - 'unexpected resource base' - ); - } - - public function testWithResourceLayout(): void - { - $baseLocation = - __DIR__ . - '/../resources/Loader/ServerVarResourceBaseLocator' . - '/resourceLayout'; - $_SERVER['RESOURCE_ROOT'] = $baseLocation; - $locator = new ServerVarResourceBaseLocator( - 'RESOURCE_ROOT' - ); - $this->assertEquals( - $baseLocation . '/objects', - $locator->locate(), - 'unexpected resource base' - ); - } - - public function testWithInvalidDirectory(): void - { - $baseLocation = - __DIR__ . - '/../resources/Loader/ServerVarResourceBaseLocator' . - '/invalid'; - $_SERVER['RESOURCE_ROOT'] = $baseLocation; - $locator = new ServerVarResourceBaseLocator( - 'RESOURCE_ROOT' - ); - $this->expectException(RuntimeException::class); - $locator->locate(); - } - - public function testWithMissingSeverVariable(): void - { - $locator = new ServerVarResourceBaseLocator('RESOURCE_ROOT'); - - $this->expectException(RuntimeException::class); - $locator->locate(); - } - - public function testUseCache(): void - { - $baseLocation = - __DIR__ . - '/../resources/Loader/ServerVarResourceBaseLocator' . - '/documentRootLayout'; - $_SERVER['RESOURCE_ROOT'] = $baseLocation; - - $locator = new ServerVarResourceBaseLocator('RESOURCE_ROOT'); - $locator->locate(); - - $this->assertEquals( - $baseLocation, - $locator->locate(), - 'unexpected resource base' - ); - } -} diff --git a/test/Loader/SiteKitLoaderTest.php b/test/Loader/SiteKitLoaderTest.php index 29d2aa1..2bb5768 100644 --- a/test/Loader/SiteKitLoaderTest.php +++ b/test/Loader/SiteKitLoaderTest.php @@ -21,7 +21,7 @@ class SiteKitLoaderTest extends TestCase protected function setUp(): void { - $base = realpath(__DIR__ . '/../resources/Loader/SiteKitLoader'); + $resourceDir = realpath(__DIR__ . '/../resources/Loader/SiteKitLoader'); $channel = new ResourceChannel( '1', 'Test Channel', @@ -30,16 +30,12 @@ protected function setUp(): void false, 'internet', 'de_DE', - 'UTF-8', + '', + $resourceDir, 'test-www', ['en_US'] ); - $channelFactory = $this->createStub(ResourceChannelFactory::class); - $channelFactory->method('create')->willReturn($channel); - $this->loader = new SiteKitLoader( - new StaticResourceBaseLocator($base), - $channelFactory - ); + $this->loader = new SiteKitLoader($channel); } public function testExists(): void diff --git a/test/Loader/StaticResourceBaseLocatorTest.php b/test/Loader/StaticResourceBaseLocatorTest.php deleted file mode 100644 index 09e45ea..0000000 --- a/test/Loader/StaticResourceBaseLocatorTest.php +++ /dev/null @@ -1,24 +0,0 @@ -assertEquals( - 'abc', - $locator->locate(), - 'unexpected resource base' - ); - } -} diff --git a/test/ResourceHierarchyWalkerTest.php b/test/ResourceHierarchyWalkerTest.php index bc8be44..6ef8ac2 100644 --- a/test/ResourceHierarchyWalkerTest.php +++ b/test/ResourceHierarchyWalkerTest.php @@ -409,11 +409,9 @@ public function testNextWithoutInit(): void $this->walker->next(); } - public function testWalk(): void + public function testWalkWithResource(): void { $root = $this->loader->load('/root.php'); - $this->walker->init($root); - $idList = []; $this->walker->walk($root, function ($resource) use (&$idList) { $idList[] = $resource->getId(); @@ -435,4 +433,29 @@ public function testWalk(): void 'unexpected id list' ); } + + public function testWalkWithLocationString(): void + { + $idList = []; + $this->walker->walk('/root.php', function ($resource) use (&$idList) { + $idList[] = $resource->getId(); + }); + + $expected = [ + 'root', + '1', + '1-1', + '1-1-1', + '1-1-1-1', + '2', + '2-1', + '2-2', + ]; + $this->assertEquals( + $expected, + $idList, + 'unexpected id list' + ); + } + } diff --git a/test/SiteKitResourceChannelFactoryTest.php b/test/SiteKitResourceChannelFactoryTest.php index d25134a..72652c5 100644 --- a/test/SiteKitResourceChannelFactoryTest.php +++ b/test/SiteKitResourceChannelFactoryTest.php @@ -15,16 +15,12 @@ class SiteKitResourceChannelFactoryTest extends TestCase { public function testCreateWithResourceLayout(): void { - $resourceBaseLocator = $this->createStub( - ResourceBaseLocator::class - ); - $resourceDir = __DIR__ . + $baseDir = __DIR__ . '/resources/SiteKitResourceChannelFactory' . '/resourceLayout'; - $resourceBaseLocator->method('locate') - ->willReturn($resourceDir . '/objects'); + $resourceDir = $baseDir . '/objects'; - $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); + $factory = new SiteKitResourceChannelFactory($baseDir); $channel = $factory->create(); $expected = new ResourceChannel( @@ -35,7 +31,8 @@ public function testCreateWithResourceLayout(): void true, 'internet', 'de_DE', - 'UTF-8', + $baseDir, + $resourceDir, 'test', [] ); @@ -46,36 +43,14 @@ public function testCreateWithResourceLayout(): void ); } - public function testCreateCache(): void - { - $resourceBaseLocator = $this->createMock( - ResourceBaseLocator::class - ); - $resourceDir = __DIR__ . - '/resources/SiteKitResourceChannelFactory' . - '/resourceLayout'; - $resourceBaseLocator - ->expects($this->once()) - ->method('locate') - ->willReturn($resourceDir . '/objects'); - - $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); - $factory->create(); - $factory->create(); - } - public function testCreateWithDocumentRootLayout(): void { - $resourceBaseLocator = $this->createStub( - ResourceBaseLocator::class - ); - $resourceDir = __DIR__ . + $baseDir = __DIR__ . '/resources/SiteKitResourceChannelFactory' . '/documentRootLayout'; - $resourceBaseLocator->method('locate') - ->willReturn($resourceDir); + $resourceDir = $baseDir; - $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); + $factory = new SiteKitResourceChannelFactory($baseDir); $channel = $factory->create(); $expected = new ResourceChannel( @@ -86,7 +61,8 @@ public function testCreateWithDocumentRootLayout(): void true, 'internet', 'de_DE', - 'UTF-8', + $baseDir, + $resourceDir, 'test', [] ); @@ -99,16 +75,11 @@ public function testCreateWithDocumentRootLayout(): void public function testCreateNonExistsContextPhp(): void { - $resourceBaseLocator = $this->createStub( - ResourceBaseLocator::class - ); $resourceDir = __DIR__ . '/resources/SiteKitResourceChannelFactory' . '/noexists'; - $resourceBaseLocator->method('locate') - ->willReturn($resourceDir); - $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); + $factory = new SiteKitResourceChannelFactory($resourceDir); $this->expectException(\RuntimeException::class); $factory->create(); @@ -116,16 +87,11 @@ public function testCreateNonExistsContextPhp(): void public function testCreateWithInvalidContextPhp(): void { - $resourceBaseLocator = $this->createStub( - ResourceBaseLocator::class - ); $resourceDir = __DIR__ . '/resources/SiteKitResourceChannelFactory' . '/invalid'; - $resourceBaseLocator->method('locate') - ->willReturn($resourceDir . '/objects'); - $factory = new SiteKitResourceChannelFactory($resourceBaseLocator); + $factory = new SiteKitResourceChannelFactory($resourceDir); $this->expectException(\RuntimeException::class); $factory->create(); From e666b511e998d066d9319de3a598b028acb1c1a7 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 18 Apr 2024 09:18:06 +0200 Subject: [PATCH 28/31] refactor: ResourceLocation and ResourceLanguage --- src/Exception/InvalidResourceException.php | 8 +- src/Exception/ResourceNotFoundException.php | 8 +- src/Loader/CachedResourceLoader.php | 20 ++-- src/Loader/SiteKit/ResourceStub.php | 2 +- src/Loader/SiteKitLoader.php | 93 +++++++--------- .../SiteKitNavigationHierarchyLoader.php | 17 +-- src/Loader/SiteKitResourceHierarchyLoader.php | 82 ++++++++------ src/Resource.php | 46 ++------ src/ResourceHierarchyFinder.php | 13 ++- src/ResourceHierarchyLoader.php | 24 +++-- src/ResourceHierarchyWalker.php | 50 ++++----- src/ResourceLanguage.php | 31 ++++++ src/ResourceLoader.php | 4 +- src/ResourceLocation.php | 32 ++++++ test/Exceptions/InvalidResourceTest.php | 8 +- test/Exceptions/ResourceNotFoundTest.php | 7 +- test/Exceptions/RootMissingExceptionTest.php | 3 + test/Loader/CachedResourceLoaderTest.php | 24 +++-- test/Loader/SiteKitLoaderTest.php | 56 ++++++---- .../SiteKitNavigationHierarchyLoaderTest.php | 17 +-- .../SiteKitResourceHierarchyLoaderTest.php | 81 ++++++++------ test/ResourceHierarchyFinderTest.php | 19 ++-- test/ResourceHierarchyWalkerTest.php | 100 +++++++++++------- test/ResourceLanguageTest.php | 58 ++++++++++ test/ResourceLocationTest.php | 62 +++++++++++ test/ResourceTest.php | 100 ++---------------- test/SiteKitResourceChannelFactoryTest.php | 1 - .../withDefaultRoot/dir/a.php | 4 +- .../withDefaultRoot/dir/b.php | 6 +- .../withDefaultRoot/dir/c.php | 6 +- .../withDefaultRoot/dir/index.php | 4 +- .../withDefaultRoot/index.php | 6 +- .../withHomeFlag/a.php | 6 +- .../withHomeFlag/b.php | 6 +- .../withHomeFlag/c.php | 6 +- .../withoutRoot/a.php | 4 +- .../SiteKitResourceHierarchyLoader/a.php | 6 +- .../SiteKitResourceHierarchyLoader/b.php | 6 +- .../SiteKitResourceHierarchyLoader/c.php | 6 +- .../childrenWithInvalidData.php | 6 +- .../firstParentWithNonStringUrl.php | 6 +- .../firstParentWithoutUrl.php | 6 +- .../primaryParentWithInvalidData.php | 6 +- .../primaryParentWithNonStringUrl.php | 6 +- .../primaryParentWithoutUrl.php | 6 +- test/resources/ResourceHierarchyFinder/a.php | 6 +- test/resources/ResourceHierarchyFinder/b.php | 6 +- test/resources/ResourceHierarchyFinder/c.php | 6 +- test/resources/ResourceHierarchyWalker/1.php | 6 +- .../resources/ResourceHierarchyWalker/1/1.php | 6 +- .../ResourceHierarchyWalker/1/1/1.php | 6 +- .../ResourceHierarchyWalker/1/1/1/1.php | 6 +- test/resources/ResourceHierarchyWalker/2.php | 6 +- .../resources/ResourceHierarchyWalker/2/1.php | 6 +- .../resources/ResourceHierarchyWalker/2/2.php | 6 +- .../ResourceHierarchyWalker/root.php | 6 +- 56 files changed, 650 insertions(+), 484 deletions(-) create mode 100644 src/ResourceLanguage.php create mode 100644 src/ResourceLocation.php create mode 100644 test/ResourceLanguageTest.php create mode 100644 test/ResourceLocationTest.php diff --git a/src/Exception/InvalidResourceException.php b/src/Exception/InvalidResourceException.php index 005586c..9deaf25 100644 --- a/src/Exception/InvalidResourceException.php +++ b/src/Exception/InvalidResourceException.php @@ -4,6 +4,8 @@ namespace Atoolo\Resource\Exception; +use Atoolo\Resource\ResourceLocation; + /** * This exception is used when a resource is invalid. This can have the * following reasons: @@ -14,19 +16,19 @@ class InvalidResourceException extends \RuntimeException { public function __construct( - private readonly string $location, + private readonly ResourceLocation $location, string $message = "", int $code = 0, ?\Throwable $previous = null ) { parent::__construct( - $location . ': ' . $message, + $location->__toString() . ': ' . $message, $code, $previous ); } - public function getLocation(): string + public function getLocation(): ResourceLocation { return $this->location; } diff --git a/src/Exception/ResourceNotFoundException.php b/src/Exception/ResourceNotFoundException.php index 8f71da8..f034b0b 100644 --- a/src/Exception/ResourceNotFoundException.php +++ b/src/Exception/ResourceNotFoundException.php @@ -4,6 +4,8 @@ namespace Atoolo\Resource\Exception; +use Atoolo\Resource\ResourceLocation; + /** * This exception is used if no resource could be found via the specified * location. @@ -11,19 +13,19 @@ class ResourceNotFoundException extends \RuntimeException { public function __construct( - private readonly string $location, + private readonly ResourceLocation $location, string $message = "", int $code = 0, ?\Throwable $previous = null ) { parent::__construct( - $location . ': ' . $message, + $location->__toString() . ': ' . $message, $code, $previous ); } - public function getLocation(): string + public function getLocation(): ResourceLocation { return $this->location; } diff --git a/src/Loader/CachedResourceLoader.php b/src/Loader/CachedResourceLoader.php index 1fa7c05..2b89cc4 100644 --- a/src/Loader/CachedResourceLoader.php +++ b/src/Loader/CachedResourceLoader.php @@ -7,7 +7,9 @@ use Atoolo\Resource\Exception\InvalidResourceException; use Atoolo\Resource\Exception\ResourceNotFoundException; use Atoolo\Resource\Resource; +use Atoolo\Resource\ResourceLanguage; use Atoolo\Resource\ResourceLoader; +use Atoolo\Resource\ResourceLocation; /** * The CachedResourceLoader class is used to load resources @@ -29,26 +31,20 @@ public function __construct( * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function load(string $location, string $lang = ''): Resource + public function load(ResourceLocation $location): Resource { - $key = $this->getKey($location, $lang); + $key = $location->__toString(); return $this->cache[$key] ??= $this->resourceLoader->load( - $location, - $lang + $location ); } - public function exists(string $location, string $lang = ''): bool + public function exists(ResourceLocation $location): bool { - $key = $this->getKey($location, $lang); + $key = $location->__toString(); if (isset($this->cache[$key])) { return true; } - return $this->resourceLoader->exists($location, $lang); - } - - private function getKey(string $location, string $lang): string - { - return $lang . ':' . $location; + return $this->resourceLoader->exists($location); } } diff --git a/src/Loader/SiteKit/ResourceStub.php b/src/Loader/SiteKit/ResourceStub.php index 3dcd932..dbe8b53 100644 --- a/src/Loader/SiteKit/ResourceStub.php +++ b/src/Loader/SiteKit/ResourceStub.php @@ -20,7 +20,7 @@ class ResourceStub */ public function init(array $data): void { - $this->data['init'] = $data; + $this->data = array_merge($this->data, $data); } /** diff --git a/src/Loader/SiteKitLoader.php b/src/Loader/SiteKitLoader.php index 4e16aad..f44b8b2 100644 --- a/src/Loader/SiteKitLoader.php +++ b/src/Loader/SiteKitLoader.php @@ -4,28 +4,28 @@ namespace Atoolo\Resource\Loader; +use Atoolo\Resource\DataBag; use Atoolo\Resource\Exception\InvalidResourceException; use Atoolo\Resource\Exception\ResourceNotFoundException; use Atoolo\Resource\Loader\SiteKit\ContextStub; use Atoolo\Resource\Loader\SiteKit\LifecylceStub; use Atoolo\Resource\Resource; -use Atoolo\Resource\ResourceBaseLocator; use Atoolo\Resource\ResourceChannel; -use Atoolo\Resource\ResourceChannelFactory; +use Atoolo\Resource\ResourceLanguage; use Atoolo\Resource\ResourceLoader; +use Atoolo\Resource\ResourceLocation; use Error; use Locale; use ParseError; /** * ResourceLoader that loads resources created with SiteKit aggregators. - * @phpstan-type InitData array{ + * @phpstan-type ResourceData array{ * id: int, * name: string, * objectType: string, * locale: string * } - * @phpstan-type ResourceData array{init: InitData} */ class SiteKitLoader implements ResourceLoader { @@ -43,38 +43,36 @@ public function __construct( * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function load(string $location, string $lang = ''): Resource + public function load(ResourceLocation $location): Resource { - $data = $this->loadRaw($location, $lang); + $data = $this->loadRaw($location); $data = $this->validateData($location, $data); - $init = $data['init']; - - $locale = $init['locale']; - $resourceLang = substr($locale, 0, 2); + $resourceLang = ResourceLanguage::of($data['locale']); return new Resource( - $location, - (string)$init['id'], - $init['name'], - $init['objectType'], + $location->location, + (string)$data['id'], + $data['name'], + $data['objectType'], $resourceLang, - $data + new DataBag($data) ); } - public function exists(string $location, string $lang = ''): bool + public function exists(ResourceLocation $location): bool { return file_exists( - $this->locationToFile($location, $lang) + $this->locationToFile($location) ); } - private function locationToFile(string $location, string $lang): string + private function locationToFile(ResourceLocation $location): string { - $file = $this->resourceChannel->resourceDir . '/' . $location; - $locale = $this->langToLocale($lang); + $file = $this->resourceChannel->resourceDir . '/' . + $location->location; + $locale = $this->langToLocale($location->lang); if (empty($locale)) { return $file; } @@ -87,14 +85,14 @@ private function locationToFile(string $location, string $lang): string * @throws InvalidResourceException * @throws ResourceNotFoundException */ - private function loadRaw(string $location, string $lang): array + private function loadRaw(ResourceLocation $location): array { - $file = $this->locationToFile($location, $lang); + $file = $this->locationToFile($location); /** * $context and $lifecycle must be defined here, because for the SiteKit - * resource PHP files these variables must be provided for the require - * call. + * resource PHP files these variables must be provided for the + * requirement call. */ $context = new ContextStub(); $lifecycle = new LifecylceStub(); @@ -111,7 +109,7 @@ private function loadRaw(string $location, string $lang): array 'The resource should return an array' ); } - /* @var ResourceData $data */ + /** @var ResourceData $data */ return $data; } catch (ParseError $e) { throw new InvalidResourceException( @@ -141,15 +139,15 @@ private function loadRaw(string $location, string $lang): array } } - private function langToLocale(string $lang): string + private function langToLocale(ResourceLanguage $lang): string { - if (empty($lang)) { - return $lang; + if ($lang === ResourceLanguage::default()) { + return ''; } $this->langLocaleMap ??= $this->createLangLocaleMap(); - return $this->langLocaleMap[$lang] ?? ''; + return $this->langLocaleMap[$lang->code] ?? ''; } /** @@ -168,69 +166,58 @@ private function createLangLocaleMap(): array } /** + * @param ResourceLocation $location * @param array $data * @return ResourceData - * @throws InvalidResourceException */ - private function validateData(string $location, array $data): array - { - - /* - * Cannot be passed because this case cannot occur here. This would - * already lead to an error in ResourceStub. But is still included, - * that so no phpstan errors arise. - */ - // @codeCoverageIgnoreStart - if (!isset($data['init']) || !is_array($data['init'])) { - throw new InvalidResourceException($location, 'init field missing'); - } - // @codeCoverageIgnoreEnd - - $init = $data['init']; + private function validateData( + ResourceLocation $location, + array $data + ): array { - if (!isset($init['id'])) { + if (!isset($data['id'])) { throw new InvalidResourceException( $location, 'id field missing' ); } - if (!is_int($init['id'])) { + if (!is_int($data['id'])) { throw new InvalidResourceException( $location, 'id field not an int' ); } - if (!isset($init['name'])) { + if (!isset($data['name'])) { throw new InvalidResourceException( $location, 'name field missing' ); } - if (!is_string($init['name'])) { + if (!is_string($data['name'])) { throw new InvalidResourceException( $location, 'name field not a string' ); } - if (!isset($init['objectType'])) { + if (!isset($data['objectType'])) { throw new InvalidResourceException( $location, 'objectType field missing' ); } - if (!is_string($init['objectType'])) { + if (!is_string($data['objectType'])) { throw new InvalidResourceException( $location, 'objectType field not a string' ); } - if (!isset($init['locale'])) { + if (!isset($data['locale'])) { throw new InvalidResourceException( $location, 'locale field missing' ); } - if (!is_string($init['locale'])) { + if (!is_string($data['locale'])) { throw new InvalidResourceException( $location, 'locale field not a string' diff --git a/src/Loader/SiteKitNavigationHierarchyLoader.php b/src/Loader/SiteKitNavigationHierarchyLoader.php index 021835a..cf8a250 100644 --- a/src/Loader/SiteKitNavigationHierarchyLoader.php +++ b/src/Loader/SiteKitNavigationHierarchyLoader.php @@ -9,6 +9,7 @@ use Atoolo\Resource\Exception\RootMissingException; use Atoolo\Resource\Resource; use Atoolo\Resource\ResourceLoader; +use Atoolo\Resource\ResourceLocation; class SiteKitNavigationHierarchyLoader extends SiteKitResourceHierarchyLoader { @@ -19,7 +20,7 @@ public function __construct(ResourceLoader $resourceLoader) public function isRoot(Resource $resource): bool { - return $resource->getData()->getBool('init.home'); + return $resource->data->getBool('init.home'); } /** @@ -42,17 +43,19 @@ protected function loadPrimaryParentResource(Resource $resource): Resource */ private function loadDefaultRootResource(Resource $resource): Resource { - $location = $resource->getLocation(); + $path = $resource->location; do { - $dir = dirname($location); - if (str_ends_with($location, '/index.php')) { + $dir = dirname($path); + if (str_ends_with($path, '/index.php')) { $dir = dirname($dir); } if ($dir === '/' || $dir === '\\') { - $location = '/index.php'; + $path = '/index.php'; } else { - $location = $dir . '/index.php'; + $path = $dir . '/index.php'; } + + $location = ResourceLocation::of($path, $resource->lang); if ($this->exists($location)) { $root = $this->load($location); if ($this->isRoot($root)) { @@ -62,7 +65,7 @@ private function loadDefaultRootResource(Resource $resource): Resource } while ($dir !== '/' && $dir !== '\\' && $dir !== ''); throw new RootMissingException( - $resource->getLocation(), + $resource->location, 'No default root could be determined for the resource' ); } diff --git a/src/Loader/SiteKitResourceHierarchyLoader.php b/src/Loader/SiteKitResourceHierarchyLoader.php index 2bef790..feb2df0 100644 --- a/src/Loader/SiteKitResourceHierarchyLoader.php +++ b/src/Loader/SiteKitResourceHierarchyLoader.php @@ -9,6 +9,7 @@ use Atoolo\Resource\Resource; use Atoolo\Resource\ResourceHierarchyLoader; use Atoolo\Resource\ResourceLoader; +use Atoolo\Resource\ResourceLocation; class SiteKitResourceHierarchyLoader implements ResourceHierarchyLoader { @@ -22,20 +23,21 @@ public function __construct( * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function load(string $location, string $lang = ''): Resource + public function load(ResourceLocation $location): Resource { - return $this->resourceLoader->load($location, $lang); + return $this->resourceLoader->load($location); } - public function exists(string $location, string $lang = ''): bool + public function exists(ResourceLocation $location): bool { - return $this->resourceLoader->exists($location, $lang); + return $this->resourceLoader->exists($location); } + /** * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function loadRoot(string $location): Resource + public function loadRoot(ResourceLocation $location): Resource { $resource = $this->resourceLoader->load($location); while (!$this->isRoot($resource)) { @@ -49,7 +51,7 @@ public function loadRoot(string $location): Resource * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function loadPrimaryParent(string $location): ?Resource + public function loadPrimaryParent(ResourceLocation $location): ?Resource { $resource = $this->resourceLoader->load($location); if ($this->isRoot($resource)) { @@ -62,8 +64,10 @@ public function loadPrimaryParent(string $location): ?Resource * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function loadParent(string $location, string $parentId): ?Resource - { + public function loadParent( + ResourceLocation $location, + string $parentId + ): ?Resource { $resource = $this->resourceLoader->load($location); if ($this->isRoot($resource)) { return null; @@ -77,7 +81,7 @@ public function loadParent(string $location, string $parentId): ?Resource * parent but is not considered a root. * @throws ResourceNotFoundException */ - public function loadPrimaryPath(string $location): array + public function loadPrimaryPath(ResourceLocation $location): array { $resource = $this->resourceLoader->load($location); $path = [$resource]; @@ -95,7 +99,7 @@ public function loadPrimaryPath(string $location): array * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function loadChildren(string $location): array + public function loadChildren(ResourceLocation $location): array { $resource = $this->resourceLoader->load($location); @@ -118,7 +122,10 @@ protected function loadPrimaryParentResource( $parentLocation = $this->getPrimaryParentLocation($resource); if ($parentLocation === null) { throw new InvalidResourceException( - $resource->getLocation(), + ResourceLocation::of( + $resource->location, + $resource->lang + ), 'the resources should have a parent' ); } @@ -138,7 +145,7 @@ protected function loadParentResource( public function isRoot(Resource $resource): bool { - $parentList = $resource->getData()->getAssociativeArray( + $parentList = $resource->data->getAssociativeArray( 'base.trees.' . $this->treeName . '.parents' ); @@ -147,12 +154,13 @@ public function isRoot(Resource $resource): bool /** * @param Resource $resource - * @return string|null + * @return ResourceLocation|null * @throws InvalidResourceException */ - public function getPrimaryParentLocation(Resource $resource): ?string - { - $parentList = $resource->getData()->getAssociativeArray( + public function getPrimaryParentLocation( + Resource $resource + ): ?ResourceLocation { + $parentList = $resource->data->getAssociativeArray( 'base.trees.' . $this->treeName . '.parents' ); @@ -166,7 +174,7 @@ public function getPrimaryParentLocation(Resource $resource): ?string foreach ($parentList as $parent) { if (!is_array($parent)) { throw new InvalidResourceException( - $resource->getLocation(), + $resource->toLocation(), 'primary parent in ' . 'base.trees.' . $this->treeName . '.parents ' . 'is invalid' @@ -177,7 +185,7 @@ public function getPrimaryParentLocation(Resource $resource): ?string if ($isPrimary === true) { if (!isset($parent['url'])) { throw new InvalidResourceException( - $resource->getLocation(), + $resource->toLocation(), 'primary parent in ' . 'base.trees.' . $this->treeName . '.parents ' . 'as no url' @@ -185,19 +193,22 @@ public function getPrimaryParentLocation(Resource $resource): ?string } if (!is_string($parent['url'])) { throw new InvalidResourceException( - $resource->getLocation(), + $resource->toLocation(), 'url of primary parent in ' . 'base.trees.' . $this->treeName . '.parents ' . 'is not a string' ); } - return $parent['url']; + return ResourceLocation::of( + $parent['url'], + $resource->lang + ); } } if (!isset($firstParent['url'])) { throw new InvalidResourceException( - $resource->getLocation(), + $resource->toLocation(), 'first parent in ' . 'base.trees.' . $this->treeName . '.parents ' . 'has no url' @@ -206,21 +217,24 @@ public function getPrimaryParentLocation(Resource $resource): ?string if (!is_string($firstParent['url'])) { throw new InvalidResourceException( - $resource->getLocation(), + $resource->toLocation(), 'url of first parent in ' . 'base.trees.' . $this->treeName . '.parents ' . 'is not a string' ); } - return $firstParent['url']; + return ResourceLocation::of( + $firstParent['url'], + $resource->lang + ); } public function getParentLocation( Resource $resource, string $parentId - ): ?string { - $parentList = $resource->getData()->getAssociativeArray( + ): ?ResourceLocation { + $parentList = $resource->data->getAssociativeArray( 'base.trees.' . $this->treeName . '.parents' ); @@ -233,14 +247,17 @@ public function getParentLocation( foreach ($parentList as $id => $parent) { if (!is_array($parent)) { throw new InvalidResourceException( - $resource->getLocation(), + $resource->toLocation(), 'parent in ' . 'base.trees.' . $this->treeName . '.parents ' . 'not an array' ); } if ($parentId === (string)$id) { - return $parent['url']; + return ResourceLocation::of( + $parent['url'], + $resource->lang + ); } } @@ -248,11 +265,11 @@ public function getParentLocation( } /** - * @return string[] + * @return ResourceLocation[] */ public function getChildrenLocations(Resource $resource): array { - $childrenList = $resource->getData()->getAssociativeArray( + $childrenList = $resource->data->getAssociativeArray( 'base.trees.' . $this->treeName . '.children' ); @@ -265,13 +282,16 @@ public function getChildrenLocations(Resource $resource): array return array_map(function ($child) use ($resource) { if (!is_array($child)) { throw new InvalidResourceException( - $resource->getLocation(), + $resource->toLocation(), 'children in ' . 'base.trees.' . $this->treeName . '.children ' . 'not an array' ); } - return $child['url']; + return ResourceLocation::of( + $child['url'], + $resource->lang + ); }, $childrenList); } } diff --git a/src/Resource.php b/src/Resource.php index 96607ea..fa99089 100644 --- a/src/Resource.php +++ b/src/Resource.php @@ -10,48 +10,18 @@ */ class Resource { - private readonly DataBag $data; - /** - * @param array $data - */ public function __construct( - private readonly string $location, - private readonly string $id, - private readonly string $name, - private readonly string $objectType, - private readonly string $lang, - array $data, + public readonly string $location, + public readonly string $id, + public readonly string $name, + public readonly string $objectType, + public readonly ResourceLanguage $lang, + public readonly DataBag $data, ) { - $this->data = new DataBag($data); } - public function getLocation(): string + public function toLocation(): ResourceLocation { - return $this->location; - } - - public function getId(): string - { - return $this->id; - } - - public function getName(): string - { - return $this->name; - } - - public function getObjectType(): string - { - return $this->objectType; - } - - public function getLang(): string - { - return $this->lang; - } - - public function getData(): DataBag - { - return $this->data; + return ResourceLocation::of($this->location, $this->lang); } } diff --git a/src/ResourceHierarchyFinder.php b/src/ResourceHierarchyFinder.php index 62173ac..9dc70cd 100644 --- a/src/ResourceHierarchyFinder.php +++ b/src/ResourceHierarchyFinder.php @@ -25,18 +25,21 @@ public function __construct( * The callable function should return true if the current resource is the * one we are looking for. * + * + * @param Resource|ResourceLocation $base The resource to be used initially. + * If `$base` is a ResourceLocation the resource is loaded. * @param callable(Resource): bool $fn * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function findFirst(Resource|string $base, callable $fn): ?Resource - { + public function findFirst( + Resource|ResourceLocation $base, + callable $fn + ): ?Resource { $walker = new ResourceHierarchyWalker($this->loader); - $walker->init($base); - - $current = $walker->getCurrent(); + $current = $walker->init($base); if ($fn($current) === true) { return $current; diff --git a/src/ResourceHierarchyLoader.php b/src/ResourceHierarchyLoader.php index 0d737e7..1d28afc 100644 --- a/src/ResourceHierarchyLoader.php +++ b/src/ResourceHierarchyLoader.php @@ -20,7 +20,9 @@ interface ResourceHierarchyLoader extends ResourceLoader * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function loadRoot(string $location): Resource; + public function loadRoot( + ResourceLocation $location + ): Resource; /** * Determines the primary parent resource via the parent links @@ -28,7 +30,9 @@ public function loadRoot(string $location): Resource; * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function loadPrimaryParent(string $location): ?Resource; + public function loadPrimaryParent( + ResourceLocation $location + ): ?Resource; /** * Determines the path to the root resource via the primary parent links @@ -39,7 +43,9 @@ public function loadPrimaryParent(string $location): ?Resource; * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function loadPrimaryPath(string $location): array; + public function loadPrimaryPath( + ResourceLocation $location + ): array; /** * Determines the children resources via the children links contained in the @@ -48,7 +54,9 @@ public function loadPrimaryPath(string $location): array; * @throws InvalidResourceException * @throws ResourceNotFoundException */ - public function loadChildren(string $location): array; + public function loadChildren( + ResourceLocation $location + ): array; /** * Indicates whether the passed resource is a root resource. @@ -62,7 +70,7 @@ public function isRoot(Resource $resource): bool; * Determines the children locations via the children links contained in the * resource data. * - * @return string[] + * @return ResourceLocation[] */ public function getChildrenLocations(Resource $resource): array; @@ -70,7 +78,9 @@ public function getChildrenLocations(Resource $resource): array; * Determines the primary parent location via the parent links contained in * the resource data. */ - public function getPrimaryParentLocation(Resource $resource): ?string; + public function getPrimaryParentLocation( + Resource $resource + ): ?ResourceLocation; /** * Determines the secondary parent location via the parent links contained @@ -80,5 +90,5 @@ public function getPrimaryParentLocation(Resource $resource): ?string; public function getParentLocation( Resource $resource, string $parentId - ): ?string; + ): ?ResourceLocation; } diff --git a/src/ResourceHierarchyWalker.php b/src/ResourceHierarchyWalker.php index 55fc061..0605fc0 100644 --- a/src/ResourceHierarchyWalker.php +++ b/src/ResourceHierarchyWalker.php @@ -33,11 +33,13 @@ class ResourceHierarchyWalker { private ?Resource $current = null; + private ResourceLanguage $lang; + /** * Contains the children and all parent children * of the levels that have been traversed up to this point. * - * @var array> + * @var array> */ private array $childrenStack = []; @@ -67,19 +69,22 @@ public function __construct( * * If the walker has already worked, it is reset. * - * @param Resource|string $base The resource to be used initially. - * If `$base` is a string it is assumed that it is a location and - * the resource is loaded. + * @param Resource|ResourceLocation $base The resource to be used initially. + * * If `$base` is a ResourceLocation the resource is loaded. */ - public function init(Resource|string $base): void + public function init(Resource|ResourceLocation $base): Resource { - if (is_string($base)) { - $base = $this->load($base); + if ($base instanceof ResourceLocation) { + $this->lang = $base->lang; + $base = $this->load($base->location); } $this->current = $base; + $this->lang = $base->lang; $this->childrenStack = []; $this->childrenStackPointer = []; $this->parentPath = []; + + return $this->current; } /** @@ -112,7 +117,7 @@ public function primaryParent(): ?Resource } $this->init($this->load( - $primaryParentLocation + $primaryParentLocation->location )); return $this->getCurrent(); @@ -148,7 +153,7 @@ public function parent(string $parentId): ?Resource } $this->init($this->load( - $secondaryParentLocation + $secondaryParentLocation->location )); return $this->getCurrent(); @@ -224,7 +229,7 @@ public function nextSibling(): ?Resource } $childLocation = $children[$pointer]; - $child = $this->load($childLocation); + $child = $this->load($childLocation->location); $this->childrenStackPointer[$topStackIndex] = $pointer; $this->current = $child; @@ -262,7 +267,7 @@ public function previousSibling(): ?Resource // $childLocation = $children[$pointer]; - $child = $this->load($childLocation); + $child = $this->load($childLocation->location); $this->childrenStackPointer[$topStackIndex] = $pointer; $this->current = $child; @@ -324,7 +329,7 @@ public function down(): ?Resource } $this->parentPath[] = $this->current; - $this->current = $this->load($children[0]); + $this->current = $this->load($children[0]->location); $this->childrenStack[] = array_values($children); $this->childrenStackPointer[count($this->childrenStack) - 1] = 0; @@ -368,7 +373,7 @@ public function child(string $childId): ?Resource $children = array_values($childrenLocations); $this->parentPath[] = $this->current; - $this->current = $this->load($children[$childPointer]); + $this->current = $this->load($children[$childPointer]->location); $this->childrenStack[] = array_values($children); $this->childrenStackPointer[count($this->childrenStack) - 1] = @@ -414,26 +419,23 @@ public function next(): ?Resource * In the method, `init($base)` is called, which resets the walker * if necessary. Here `next()` is used to traverse the hierarchy. * - * @param Resource|string $base The resource to be used initially. - * * If `$base` is a string it is assumed that it is a location and - * * the resource is loaded. + * @param Resource|ResourceLocation $base The resource to be used initially. + * * If `$base` is a ResourceLocation the resource is loaded. * @param callable(Resource): void $fn The method to be called for each * resource. */ - public function walk(Resource|string $base, callable $fn): void + public function walk(Resource|ResourceLocation $base, callable $fn): void { - if (is_string($base)) { - $base = $this->load($base); - } - $this->init($base); - $fn($base); + $current = $this->init($base); + $fn($current); while ($current = $this->next()) { $fn($current); } } - private function load(string $location, string $lang = ''): Resource + private function load(string $path): Resource { - return $this->hierarchyLoader->load($location, $lang); + $location = ResourceLocation::of($path, $this->lang); + return $this->hierarchyLoader->load($location); } } diff --git a/src/ResourceLanguage.php b/src/ResourceLanguage.php new file mode 100644 index 0000000..26a3525 --- /dev/null +++ b/src/ResourceLanguage.php @@ -0,0 +1,31 @@ +lang->code === '') { + return $this->location; + } + return $this->location . ':' . $this->lang->code; + } +} diff --git a/test/Exceptions/InvalidResourceTest.php b/test/Exceptions/InvalidResourceTest.php index 9d9bdf8..8560a69 100644 --- a/test/Exceptions/InvalidResourceTest.php +++ b/test/Exceptions/InvalidResourceTest.php @@ -5,16 +5,20 @@ namespace Atoolo\Resource\Test\Exceptions; use Atoolo\Resource\Exception\InvalidResourceException; +use Atoolo\Resource\Loader\CachedResourceLoader; +use Atoolo\Resource\ResourceLocation; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +#[CoversClass(InvalidResourceException::class)] class InvalidResourceTest extends TestCase { public function testGetLocation(): void { - $e = new InvalidResourceException('abc'); + $e = new InvalidResourceException(ResourceLocation::of('abc')); $this->assertEquals( 'abc', - $e->getLocation(), + $e->getLocation()->location, 'unexpected location' ); } diff --git a/test/Exceptions/ResourceNotFoundTest.php b/test/Exceptions/ResourceNotFoundTest.php index 98edf8c..e5a3bfe 100644 --- a/test/Exceptions/ResourceNotFoundTest.php +++ b/test/Exceptions/ResourceNotFoundTest.php @@ -6,16 +6,19 @@ use Atoolo\Resource\Exception\InvalidResourceException; use Atoolo\Resource\Exception\ResourceNotFoundException; +use Atoolo\Resource\ResourceLocation; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +#[CoversClass(ResourceNotFoundException::class)] class ResourceNotFoundTest extends TestCase { public function testGetLocation(): void { - $e = new ResourceNotFoundException('abc'); + $e = new ResourceNotFoundException(ResourceLocation::of('abc')); $this->assertEquals( 'abc', - $e->getLocation(), + $e->getLocation()->location, 'unexpected location' ); } diff --git a/test/Exceptions/RootMissingExceptionTest.php b/test/Exceptions/RootMissingExceptionTest.php index 7c4fae3..588d7cd 100644 --- a/test/Exceptions/RootMissingExceptionTest.php +++ b/test/Exceptions/RootMissingExceptionTest.php @@ -5,9 +5,12 @@ namespace Atoolo\Resource\Test\Exceptions; use Atoolo\Resource\Exception\InvalidResourceException; +use Atoolo\Resource\Exception\ResourceNotFoundException; use Atoolo\Resource\Exception\RootMissingException; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +#[CoversClass(RootMissingException::class)] class RootMissingExceptionTest extends TestCase { public function testGetLocation(): void diff --git a/test/Loader/CachedResourceLoaderTest.php b/test/Loader/CachedResourceLoaderTest.php index f5bf601..c14234b 100644 --- a/test/Loader/CachedResourceLoaderTest.php +++ b/test/Loader/CachedResourceLoaderTest.php @@ -7,6 +7,7 @@ use Atoolo\Resource\Loader\CachedResourceLoader; use Atoolo\Resource\Resource; use Atoolo\Resource\ResourceLoader; +use Atoolo\Resource\ResourceLocation; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -15,33 +16,37 @@ class CachedResourceLoaderTest extends TestCase { public function testLoad(): void { + $location = ResourceLocation::of('test'); + $resource = $this->createStub(Resource::class); $loader = $this->createMock(ResourceLoader::class); $loader->expects($this->once()) ->method('load') - ->with('test') + ->with($location) ->willReturn($resource); $cachedLoader = new CachedResourceLoader($loader); - $cachedLoader->load('test'); // cache warmup + $cachedLoader->load($location); // cache warmup $this->assertEquals( $resource, - $cachedLoader->load('test'), + $cachedLoader->load($location), 'Resource should be loaded from cache' ); } public function testExistsUncached(): void { + $location = ResourceLocation::of('test'); + $loader = $this->createMock(ResourceLoader::class); $loader->expects($this->once()) ->method('exists') - ->with('test') + ->with($location) ->willReturn(true); $cachedLoader = new CachedResourceLoader($loader); $this->assertTrue( - $cachedLoader->exists('test'), + $cachedLoader->exists($location), 'Resource should be test from cache' ); } @@ -49,22 +54,23 @@ public function testExistsUncached(): void public function testExistsCached(): void { + $location = ResourceLocation::of('test'); $resource = $this->createStub(Resource::class); $loader = $this->createMock(ResourceLoader::class); $loader->expects($this->once()) ->method('load') - ->with('test') + ->with($location) ->willReturn($resource); $loader->expects($this->exactly(0)) ->method('exists') - ->with('test') + ->with($location) ->willReturn(true); $cachedLoader = new CachedResourceLoader($loader); - $cachedLoader->load('test'); // cache warmup + $cachedLoader->load($location); // cache warmup $this->assertTrue( - $cachedLoader->exists('test'), + $cachedLoader->exists($location), 'Resource should be test from cache' ); } diff --git a/test/Loader/SiteKitLoaderTest.php b/test/Loader/SiteKitLoaderTest.php index 2bb5768..50f1079 100644 --- a/test/Loader/SiteKitLoaderTest.php +++ b/test/Loader/SiteKitLoaderTest.php @@ -7,10 +7,9 @@ use Atoolo\Resource\Exception\InvalidResourceException; use Atoolo\Resource\Exception\ResourceNotFoundException; use Atoolo\Resource\Loader\SiteKitLoader; -use Atoolo\Resource\Loader\StaticResourceBaseLocator; -use Atoolo\Resource\Resource; use Atoolo\Resource\ResourceChannel; -use Atoolo\Resource\ResourceChannelFactory; +use Atoolo\Resource\ResourceLanguage; +use Atoolo\Resource\ResourceLocation; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -40,32 +39,43 @@ protected function setUp(): void public function testExists(): void { - $exists = $this->loader->exists('validResource.php'); + $exists = $this->loader->exists( + ResourceLocation::of('validResource.php') + ); $this->assertTrue($exists, 'resource should exist'); } public function testExistsWithLang(): void { - $exists = $this->loader->exists('validResource.php', 'en'); + $exists = $this->loader->exists( + ResourceLocation::of('validResource.php') + ); $this->assertTrue($exists, 'resource should exist'); } public function testLoadValidResource(): void { - $resource = $this->loader->load('validResource.php'); + $resource = $this->loader->load( + ResourceLocation::of('validResource.php') + ); $this->assertEquals( '1118', - $resource->getId(), + $resource->id, 'unexpected id' ); } public function testLoadValidResourceWithLang(): void { - $resource = $this->loader->load('validResource.php', 'en'); + $resource = $this->loader->load( + ResourceLocation::of( + 'validResource.php', + ResourceLanguage::of('en') + ) + ); $this->assertEquals( '1118', - $resource->getId(), + $resource->id, 'unexpected id' ); } @@ -73,84 +83,84 @@ public function testLoadValidResourceWithLang(): void public function testLoadMissingLocation(): void { $this->expectException(ResourceNotFoundException::class); - $this->loader->load('notfound.php'); + $this->loader->load(ResourceLocation::of('notfound.php')); } public function testLoadResourceWithCompileError(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('compileError.php'); + $this->loader->load(ResourceLocation::of('compileError.php')); } public function testLoadResourceWithCommonError(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('commonError.php'); + $this->loader->load(ResourceLocation::of('commonError.php')); } public function testLoadWithMissingInit(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('missingInitResource.php'); + $this->loader->load(ResourceLocation::of('missingInitResource.php')); } public function testLoadWithInitNotAnArray(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('initNotAnArrayResource.php'); + $this->loader->load(ResourceLocation::of('initNotAnArrayResource.php')); } public function testLoadWithNonIntId(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('nonIntIdResource.php'); + $this->loader->load(ResourceLocation::of('nonIntIdResource.php')); } public function testLoadWithMissingId(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('missingIdResource.php'); + $this->loader->load(ResourceLocation::of('missingIdResource.php')); } public function testLoadWithMissingName(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('missingNameResource.php'); + $this->loader->load(ResourceLocation::of('missingNameResource.php')); } public function testLoadWithNonStringName(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('nonStringNameResource.php'); + $this->loader->load(ResourceLocation::of('nonStringNameResource.php')); } public function testLoadWithMissingObjectType(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('missingObjectTypeResource.php'); + $this->loader->load(ResourceLocation::of('missingObjectTypeResource.php')); } public function testLoadWithNonStringObjectType(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('nonStringObjectTypeResource.php'); + $this->loader->load(ResourceLocation::of('nonStringObjectTypeResource.php')); } public function testLoadWithMissingLocale(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('missingLocaleResource.php'); + $this->loader->load(ResourceLocation::of('missingLocaleResource.php')); } public function testLoadWithNonStringLocale(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('nonStringLocaleResource.php'); + $this->loader->load(ResourceLocation::of('nonStringLocaleResource.php')); } public function testLoadWithNonArrayReturned(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load('nonArrayReturned.php'); + $this->loader->load(ResourceLocation::of('nonArrayReturned.php')); } } diff --git a/test/Loader/SiteKitNavigationHierarchyLoaderTest.php b/test/Loader/SiteKitNavigationHierarchyLoaderTest.php index edc74f2..e801fe9 100644 --- a/test/Loader/SiteKitNavigationHierarchyLoaderTest.php +++ b/test/Loader/SiteKitNavigationHierarchyLoaderTest.php @@ -8,6 +8,7 @@ use Atoolo\Resource\Exception\RootMissingException; use Atoolo\Resource\Loader\SiteKitNavigationHierarchyLoader; use Atoolo\Resource\ResourceLoader; +use Atoolo\Resource\ResourceLocation; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -23,11 +24,11 @@ public function testLoadRootResourceWithHomeFlag(): void ) ); - $root = $treeLoader->loadRoot('/c.php'); + $root = $treeLoader->loadRoot(ResourceLocation::of('/c.php')); $this->assertEquals( 'a', - $root->getId(), + $root->id, 'unexpected root' ); } @@ -41,11 +42,13 @@ public function testLoadRootResourceWithDefaultRoot(): void ) ); - $root = $treeLoader->loadRoot('/dir/c.php'); + $root = $treeLoader->loadRoot( + ResourceLocation::of('/dir/c.php') + ); $this->assertEquals( 'root', - $root->getId(), + $root->id, 'unexpected root' ); } @@ -60,7 +63,7 @@ public function testLoadRootResourceWithoutRoot(): void ); $this->expectException(RootMissingException::class); - $treeLoader->loadRoot('/a.php'); + $treeLoader->loadRoot(ResourceLocation::of('/a.php')); } private function createTreeLoader( @@ -73,13 +76,13 @@ private function createTreeLoader( ->willReturnCallback(static function ($location) use ( $resourceBaseDir ) { - return include $resourceBaseDir . $location; + return include $resourceBaseDir . $location->location; }); $resourceLoader->method('exists') ->willReturnCallback(static function ($location) use ( $resourceBaseDir ) { - return file_exists($resourceBaseDir . $location); + return file_exists($resourceBaseDir . $location->location); }); return new SiteKitNavigationHierarchyLoader( $resourceLoader diff --git a/test/Loader/SiteKitResourceHierarchyLoaderTest.php b/test/Loader/SiteKitResourceHierarchyLoaderTest.php index 2d3cd44..98230d7 100644 --- a/test/Loader/SiteKitResourceHierarchyLoaderTest.php +++ b/test/Loader/SiteKitResourceHierarchyLoaderTest.php @@ -8,6 +8,7 @@ use Atoolo\Resource\Loader\SiteKitResourceHierarchyLoader; use Atoolo\Resource\Resource; use Atoolo\Resource\ResourceLoader; +use Atoolo\Resource\ResourceLocation; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\TestCase; @@ -37,7 +38,9 @@ private function createLoader(string $className) ->willReturnCallback(static function ($location) use ( $resourceBaseDir ) { - return include $resourceBaseDir . $location; + $resource = include $resourceBaseDir . $location->location; + $error = error_get_last(); + return $resource; }); return new $className( @@ -60,7 +63,7 @@ public function testLoad(): void $resourceLoader->expects($this->once()) ->method('load'); - $hierarchyLoader->load('/a.php'); + $hierarchyLoader->load(ResourceLocation::of('/a.php')); } /** @@ -77,7 +80,7 @@ public function testExists(): void $resourceLoader->expects($this->once()) ->method('exists'); - $hierarchyLoader->exists('/a.php'); + $hierarchyLoader->exists(ResourceLocation::of('/a.php')); } public function testLoadPrimaryParentResourceWithoutParent(): void @@ -87,37 +90,43 @@ public function testLoadPrimaryParentResourceWithoutParent(): void TestSiteKitResourceHierarchyLoader::class ); $this->expectException(InvalidResourceException::class); - $loader->loadRoot('/a.php'); + $loader->loadRoot(ResourceLocation::of('/a.php')); } public function testLoadRoot(): void { - $root = $this->hierarchyLoader->loadRoot('/c.php'); + $root = $this->hierarchyLoader->loadRoot( + ResourceLocation::of('/c.php') + ); $this->assertEquals( 'a', - $root->getId(), + $root->id, 'unexpected root' ); } public function testLoadPrimaryParent(): void { - $parent = $this->hierarchyLoader->loadPrimaryParent('/c.php'); + $parent = $this->hierarchyLoader->loadPrimaryParent( + ResourceLocation::of('/c.php') + ); $this->assertEquals( 'b', - $parent->getId(), + $parent->id, 'unexpected parent' ); } public function testLoadChildren(): void { - $children = $this->hierarchyLoader->loadChildren('/b.php'); + $children = $this->hierarchyLoader->loadChildren( + ResourceLocation::of('/b.php') + ); $childrenIdList = array_map(function ($child) { - return $child->getId(); + return $child->id; }, $children); $this->assertEquals( @@ -130,14 +139,16 @@ public function testLoadChildren(): void public function testLoadChildrenWithInvalidData(): void { $this->expectException(InvalidResourceException::class); - $children = $this->hierarchyLoader->loadChildren( - '/childrenWithInvalidData.php' + $this->hierarchyLoader->loadChildren( + ResourceLocation::of('/childrenWithInvalidData.php') ); } public function testLoadWithoutChildren(): void { - $children = $this->hierarchyLoader->loadChildren('/c.php'); + $children = $this->hierarchyLoader->loadChildren( + ResourceLocation::of('/c.php') + ); $this->assertCount( 0, @@ -148,10 +159,12 @@ public function testLoadWithoutChildren(): void public function testLoadPrimaryPath(): void { - $path = $this->hierarchyLoader->loadPrimaryPath('/c.php'); + $path = $this->hierarchyLoader->loadPrimaryPath( + ResourceLocation::of('/c.php') + ); $pathIdList = array_map(function ($resource) { - return $resource->getId(); + return $resource->id; }, $path); $this->assertEquals( @@ -163,7 +176,9 @@ public function testLoadPrimaryPath(): void public function testLoadPrimaryParentWithoutParent(): void { - $parent = $this->hierarchyLoader->loadPrimaryParent('/a.php'); + $parent = $this->hierarchyLoader->loadPrimaryParent( + ResourceLocation::of('/a.php') + ); $this->assertNull($parent, 'parent should be null'); } @@ -171,7 +186,7 @@ public function testLoadRootResourcePrimaryParentWithoutUrl(): void { $this->expectException(InvalidResourceException::class); $this->hierarchyLoader->loadPrimaryParent( - '/primaryParentWithoutUrl.php' + ResourceLocation::of('/primaryParentWithoutUrl.php') ); } @@ -179,7 +194,7 @@ public function testLoadRootResourcePrimaryParentWithInvalidData(): void { $this->expectException(InvalidResourceException::class); $this->hierarchyLoader->loadPrimaryParent( - '/primaryParentWithInvalidData.php' + ResourceLocation::of('/primaryParentWithInvalidData.php') ); } @@ -187,7 +202,7 @@ public function testLoadRootResourcePrimaryParentWithNonStringUrl(): void { $this->expectException(InvalidResourceException::class); $this->hierarchyLoader->loadPrimaryParent( - '/primaryParentWithNonStringUrl.php' + ResourceLocation::of('/primaryParentWithNonStringUrl.php') ); } @@ -195,7 +210,7 @@ public function testLoadRootResourceFirstParentWithoutUrl(): void { $this->expectException(InvalidResourceException::class); $this->hierarchyLoader->loadPrimaryParent( - '/firstParentWithoutUrl.php' + ResourceLocation::of('/firstParentWithoutUrl.php') ); } @@ -203,19 +218,19 @@ public function testLoadRootResourceFirstParentWithNonStringUrl(): void { $this->expectException(InvalidResourceException::class); $this->hierarchyLoader->loadPrimaryParent( - '/firstParentWithNonStringUrl.php' + ResourceLocation::of('/firstParentWithNonStringUrl.php') ); } public function testLoadParent(): void { $parent = $this->hierarchyLoader->loadParent( - '/b.php', + ResourceLocation::of('/b.php'), 'a' ); $this->assertEquals( 'a', - $parent->getId(), + $parent->id, 'unexpected parent' ); } @@ -223,7 +238,7 @@ public function testLoadParent(): void public function testLoadParentIdNotFound(): void { $parent = $this->hierarchyLoader->loadParent( - '/b.php', + ResourceLocation::of('/b.php'), 'x' ); $this->assertNull( @@ -235,7 +250,7 @@ public function testLoadParentIdNotFound(): void public function testLoadParentOfRoot(): void { $parent = $this->hierarchyLoader->loadParent( - '/a.php', + ResourceLocation::of('/a.php'), 'x' ); $this->assertNull( @@ -251,8 +266,8 @@ public function testGetParentLocationWithoutParents(): void '', '', '', - '', - [] + \Atoolo\Resource\ResourceLanguage::default(), + new \Atoolo\Resource\DataBag([]) ); $parent = $this->hierarchyLoader->getParentLocation( $resource, @@ -271,8 +286,8 @@ public function testGetParentLocationWithInvalidData(): void '', '', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::default(), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -282,7 +297,7 @@ public function testGetParentLocationWithInvalidData(): void ] ] ] - ] + ]) ); $this->expectException(InvalidResourceException::class); @@ -299,8 +314,8 @@ public function testGetParentLocationWithParentIdNotFound(): void '', '', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::default(), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -313,7 +328,7 @@ public function testGetParentLocationWithParentIdNotFound(): void ] ] ] - ] + ]) ); $parent = $this->hierarchyLoader->getParentLocation( diff --git a/test/ResourceHierarchyFinderTest.php b/test/ResourceHierarchyFinderTest.php index 13b3cfa..b7dbec5 100644 --- a/test/ResourceHierarchyFinderTest.php +++ b/test/ResourceHierarchyFinderTest.php @@ -7,6 +7,7 @@ use Atoolo\Resource\Loader\SiteKitResourceHierarchyLoader; use Atoolo\Resource\ResourceHierarchyFinder; use Atoolo\Resource\ResourceLoader; +use Atoolo\Resource\ResourceLocation; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -30,7 +31,7 @@ public function setUp(): void ->willReturnCallback(static function ($location) use ( $resourceBaseDir ) { - return include $resourceBaseDir . $location; + return include $resourceBaseDir . $location->location; }); $hierarchyLoader = new SiteKitResourceHierarchyLoader( @@ -45,15 +46,15 @@ public function setUp(): void public function testFindFirst(): void { $resource = $this->finder->findFirst( - '/a.php', + ResourceLocation::of('/a.php'), static function ($resource) { - return $resource->getId() === 'c'; + return $resource->id === 'c'; } ); $this->assertEquals( 'c', - $resource->getId(), + $resource->id, 'Resource c should be found' ); } @@ -61,15 +62,15 @@ static function ($resource) { public function testFindFirstFindBase(): void { $resource = $this->finder->findFirst( - '/a.php', + ResourceLocation::of('/a.php'), static function ($resource) { - return $resource->getId() === 'a'; + return $resource->id === 'a'; } ); $this->assertEquals( 'a', - $resource->getId(), + $resource->id, 'Resource a should be found' ); } @@ -77,9 +78,9 @@ static function ($resource) { public function testFindFirstNotFound(): void { $resource = $this->finder->findFirst( - '/a.php', + ResourceLocation::of('/a.php'), static function ($resource) { - return $resource->getId() === 'x'; + return $resource->id === 'x'; } ); diff --git a/test/ResourceHierarchyWalkerTest.php b/test/ResourceHierarchyWalkerTest.php index 6ef8ac2..a73e81b 100644 --- a/test/ResourceHierarchyWalkerTest.php +++ b/test/ResourceHierarchyWalkerTest.php @@ -9,6 +9,7 @@ use Atoolo\Resource\ResourceHierarchyLoader; use Atoolo\Resource\ResourceHierarchyWalker; use Atoolo\Resource\ResourceLoader; +use Atoolo\Resource\ResourceLocation; use LogicException; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\MockObject\Exception; @@ -37,7 +38,7 @@ public function setUp(): void ->willReturnCallback(static function ($location) use ( $resourceBaseDir ) { - return include $resourceBaseDir . $location; + return include $resourceBaseDir . $location->location; }); $hierarchyLoader = new SiteKitResourceHierarchyLoader( @@ -52,11 +53,11 @@ public function setUp(): void public function testInitWithLocation(): void { - $this->walker->init('/1.php'); + $this->walker->init(ResourceLocation::of('/1.php')); $this->assertEquals( '1', - $this->walker->getCurrent()->getId(), + $this->walker->getCurrent()->id, 'base resource should be found' ); } @@ -69,26 +70,26 @@ public function testGetCurrentWithoutInit(): void public function testInitWithResource(): void { - $base = $this->loader->load('/1.php'); + $base = $this->loader->load(ResourceLocation::of('/1.php')); $this->walker->init($base); $this->assertEquals( '1', - $this->walker->getCurrent()->getId(), + $this->walker->getCurrent()->id, 'base resource should be found' ); } public function testPrimaryParent(): void { - $base = $this->loader->load('/1/1.php'); + $base = $this->loader->load(ResourceLocation::of('/1/1.php')); $this->walker->init($base); $this->walker->primaryParent(); $this->assertEquals( '1', - $this->walker->getCurrent()->getId(), + $this->walker->getCurrent()->id, 'unexpected primary parent' ); } @@ -101,7 +102,7 @@ public function testPrimaryParentWithoutInit(): void public function testPrimaryParentOfRoot(): void { - $base = $this->loader->load('/root.php'); + $base = $this->loader->load(ResourceLocation::of('/root.php')); $this->walker->init($base); $this->assertNull( @@ -124,7 +125,14 @@ public function testPrimaryParentWithoutPrimaryParent(): void $walker = new ResourceHierarchyWalker( $hierarchyLoader ); - $base = $this->createStub(Resource::class); + $base = new \Atoolo\Resource\Resource( + '', + '', + '', + '', + \Atoolo\Resource\ResourceLanguage::default(), + new \Atoolo\Resource\DataBag([]) + ); $walker->init($base); @@ -136,14 +144,14 @@ public function testPrimaryParentWithoutPrimaryParent(): void public function testParent(): void { - $base = $this->loader->load('/1/1.php'); + $base = $this->loader->load(ResourceLocation::of('/1/1.php')); $this->walker->init($base); $this->walker->parent('2'); $this->assertEquals( '2', - $this->walker->getCurrent()->getId(), + $this->walker->getCurrent()->id, 'unexpected secondary parent' ); } @@ -156,7 +164,7 @@ public function testParentWithoutInit(): void public function testParentOfRoot(): void { - $base = $this->loader->load('/root.php'); + $base = $this->loader->load(ResourceLocation::of('/root.php')); $this->walker->init($base); $this->assertNull( @@ -179,7 +187,14 @@ public function testParentWithoutPrimaryParent(): void $walker = new ResourceHierarchyWalker( $hierarchyLoader ); - $base = $this->createStub(Resource::class); + $base = new \Atoolo\Resource\Resource( + '', + '', + '', + '', + \Atoolo\Resource\ResourceLanguage::default(), + new \Atoolo\Resource\DataBag([]) + ); $walker->init($base); @@ -191,7 +206,7 @@ public function testParentWithoutPrimaryParent(): void public function testGetLevel(): void { - $base = $this->loader->load('/1.php'); + $base = $this->loader->load(ResourceLocation::of('/1.php')); $this->walker->init($base); $this->walker->down(); @@ -204,7 +219,7 @@ public function testGetLevel(): void public function testGetPath(): void { - $base = $this->loader->load('/1.php'); + $base = $this->loader->load(ResourceLocation::of('/1.php')); $this->walker->init($base); $this->walker->down(); @@ -213,7 +228,7 @@ public function testGetPath(): void $this->assertEquals( $expected, array_map( - static fn($resource) => $resource->getId(), + static fn($resource) => $resource->id, $this->walker->getPath() ), 'unexpected path' @@ -230,14 +245,14 @@ public function testGetPathWithoutInit(): void public function testNextSibling(): void { - $base = $this->loader->load('/root.php'); + $base = $this->loader->load(ResourceLocation::of('/root.php')); $this->walker->init($base); $this->walker->down(); $this->walker->nextSibling(); $this->assertEquals( '2', - $this->walker->getCurrent()->getId(), + $this->walker->getCurrent()->id, 'unexpected sibling' ); } @@ -252,7 +267,7 @@ public function testNextSiblingWithoutInit(): void public function testPreviousSibling(): void { - $base = $this->loader->load('/root.php'); + $base = $this->loader->load(ResourceLocation::of('/root.php')); $this->walker->init($base); $this->walker->down(); $this->walker->nextSibling(); @@ -260,7 +275,7 @@ public function testPreviousSibling(): void $this->assertEquals( '1', - $this->walker->getCurrent()->getId(), + $this->walker->getCurrent()->id, 'unexpected sibling' ); } @@ -275,7 +290,7 @@ public function testPreviousSiblingWithoutInit(): void public function testPreviousSiblingWithFirstChild(): void { - $base = $this->loader->load('/root.php'); + $base = $this->loader->load(ResourceLocation::of('/root.php')); $this->walker->init($base); $this->walker->down(); $this->walker->previousSibling(); @@ -288,14 +303,14 @@ public function testPreviousSiblingWithFirstChild(): void public function testUp(): void { - $base = $this->loader->load('/root.php'); + $base = $this->loader->load(ResourceLocation::of('/root.php')); $this->walker->init($base); $this->walker->down(); $this->walker->up(); $this->assertEquals( 'root', - $this->walker->getCurrent()->getId(), + $this->walker->getCurrent()->id, 'unexpected current resource' ); } @@ -308,7 +323,7 @@ public function testUpWithoutInit(): void public function testUpForFirstLevel(): void { - $base = $this->loader->load('/root.php'); + $base = $this->loader->load(ResourceLocation::of('/root.php')); $this->walker->init($base); $this->assertNull( @@ -319,13 +334,13 @@ public function testUpForFirstLevel(): void public function testDown(): void { - $base = $this->loader->load('/root.php'); + $base = $this->loader->load(ResourceLocation::of('/root.php')); $this->walker->init($base); $this->walker->down(); $this->assertEquals( '1', - $this->walker->getCurrent()->getId(), + $this->walker->getCurrent()->id, 'unexpected current resource' ); } @@ -338,20 +353,20 @@ public function testDownWithoutInit(): void public function testChild(): void { - $base = $this->loader->load('/root.php'); + $base = $this->loader->load(ResourceLocation::of('/root.php')); $this->walker->init($base); $this->walker->child('2'); $this->assertEquals( '2', - $this->walker->getCurrent()->getId(), + $this->walker->getCurrent()->id, 'unexpected current resource' ); } public function testChildNotFound(): void { - $base = $this->loader->load('/root.php'); + $base = $this->loader->load(ResourceLocation::of('/root.php')); $this->walker->init($base); $this->assertNull( @@ -380,7 +395,14 @@ public function testChildWithoutChildren(): void $walker = new ResourceHierarchyWalker( $hierarchyLoader ); - $base = $this->createStub(Resource::class); + $base = new Resource( + '', + '', + '', + '', + \Atoolo\Resource\ResourceLanguage::default(), + new \Atoolo\Resource\DataBag([]) + ); $walker->init($base); @@ -392,13 +414,13 @@ public function testChildWithoutChildren(): void public function testNext(): void { - $base = $this->loader->load('/root.php'); + $base = $this->loader->load(ResourceLocation::of('/root.php')); $this->walker->init($base); $this->walker->next(); $this->assertEquals( '1', - $this->walker->getCurrent()->getId(), + $this->walker->getCurrent()->id, 'unexpected current resource' ); } @@ -411,10 +433,10 @@ public function testNextWithoutInit(): void public function testWalkWithResource(): void { - $root = $this->loader->load('/root.php'); + $root = $this->loader->load(ResourceLocation::of('/root.php')); $idList = []; $this->walker->walk($root, function ($resource) use (&$idList) { - $idList[] = $resource->getId(); + $idList[] = $resource->id; }); $expected = [ @@ -437,9 +459,12 @@ public function testWalkWithResource(): void public function testWalkWithLocationString(): void { $idList = []; - $this->walker->walk('/root.php', function ($resource) use (&$idList) { - $idList[] = $resource->getId(); - }); + $this->walker->walk( + ResourceLocation::of('/root.php'), + function ($resource) use (&$idList) { + $idList[] = $resource->id; + } + ); $expected = [ 'root', @@ -457,5 +482,4 @@ public function testWalkWithLocationString(): void 'unexpected id list' ); } - } diff --git a/test/ResourceLanguageTest.php b/test/ResourceLanguageTest.php new file mode 100644 index 0000000..00f102e --- /dev/null +++ b/test/ResourceLanguageTest.php @@ -0,0 +1,58 @@ +assertSame('', $language->code); + } + + public function testOfOnlyLang(): void + { + $language = ResourceLanguage::of('en'); + $this->assertSame('en', $language->code); + } + + public function testOfWithLocale(): void + { + $language = ResourceLanguage::of('en_US'); + $this->assertSame('en', $language->code); + } + + public function testOfWithISO_639_1(): void + { + $language = ResourceLanguage::of('de-at'); + $this->assertSame('de', $language->code); + } + + public function testOfWithNull(): void + { + $language = ResourceLanguage::of(null); + $this->assertSame('', $language->code); + } + + public function testOfWithEmptyString(): void + { + $language = ResourceLanguage::of(''); + $this->assertSame('', $language->code); + } + + + /* + public function testOfWithISO_639_2(): void + { + $language = ResourceLanguage::of('ger'); + $this->assertSame('de', $language->code); + } + */ +} diff --git a/test/ResourceLocationTest.php b/test/ResourceLocationTest.php new file mode 100644 index 0000000..ddda103 --- /dev/null +++ b/test/ResourceLocationTest.php @@ -0,0 +1,62 @@ +assertEquals( + '/path', + $location->location, + 'unexpected location' + ); + } + public function testOfWithLang(): void + { + $location = ResourceLocation::of( + '', + ResourceLanguage::of('en') + ); + $this->assertEquals( + ResourceLanguage::of('en'), + $location->lang, + 'unexpected lang' + ); + } + + public function testToString(): void + { + $location = ResourceLocation::of( + '/path', + ); + $this->assertEquals( + '/path', + $location->__toString(), + 'unexpected string' + ); + } + + public function testToStringWithLang(): void + { + $location = ResourceLocation::of( + '/path', + ResourceLanguage::of('en') + ); + $this->assertEquals( + '/path:en', + $location->__toString(), + 'unexpected string' + ); + } + +} diff --git a/test/ResourceTest.php b/test/ResourceTest.php index 709dd12..39cb7e5 100644 --- a/test/ResourceTest.php +++ b/test/ResourceTest.php @@ -6,110 +6,30 @@ use Atoolo\Resource\DataBag; use Atoolo\Resource\Resource; +use Atoolo\Resource\ResourceLanguage; +use Atoolo\Resource\ResourceLocation; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; #[CoversClass(Resource::class)] class ResourceTest extends TestCase { - public function testGetLocation(): void + public function testToLocation(): void { $resource = new Resource( 'path', '', '', '', - '', - [] - ); - $this->assertEquals( - 'path', - $resource->getLocation(), - 'unexpected location' - ); - } - - public function testGetId(): void - { - $resource = new Resource( - '', - '123', - '', - '', - '', - [] - ); - $this->assertEquals( - '123', - $resource->getId(), - 'unexpected id' - ); - } - - public function testGetName(): void - { - $resource = new Resource( - '', - '', - 'Content-Page', - '', - '', - [] - ); - $this->assertEquals( - 'Content-Page', - $resource->getName(), - 'unexpected name' - ); - } - - public function testGetObjectType(): void - { - $resource = new Resource( - '', - '', - '', - 'content', - '', - [] - ); - $this->assertEquals( - 'content', - $resource->getObjectType(), - 'unexpected content' - ); - } - - public function testGetLang(): void - { - $resource = new Resource( - '', - '', - '', - 'content', - 'en', - [] - ); - $this->assertEquals( - 'en', - $resource->getLang(), - 'unexpected lang' - ); - } - - public function testGetData(): void - { - $resource = new Resource( - '', - '', - '', - '', - '', - ['field' => 'value'] + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([]) ); $this->assertEquals( - 'value', - $resource->getData()->getString('field'), + ResourceLocation::of( + 'path', + \Atoolo\Resource\ResourceLanguage::of('en') + ), + $resource->toLocation(), 'unexpected data value' ); } diff --git a/test/SiteKitResourceChannelFactoryTest.php b/test/SiteKitResourceChannelFactoryTest.php index 72652c5..f4bf66a 100644 --- a/test/SiteKitResourceChannelFactoryTest.php +++ b/test/SiteKitResourceChannelFactoryTest.php @@ -4,7 +4,6 @@ namespace Atoolo\Resource\Test; -use Atoolo\Resource\ResourceBaseLocator; use Atoolo\Resource\ResourceChannel; use Atoolo\Resource\SiteKitResourceChannelFactory; use PHPUnit\Framework\Attributes\CoversClass; diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/a.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/a.php index 6f106c6..7e6ae65 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/a.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/a.php @@ -5,6 +5,6 @@ 'a', 'a', '', - 'de_DE', - [] + \Atoolo\Resource\ResourceLanguage::default(), + new \Atoolo\Resource\DataBag([]) ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php index fc56006..9d24829 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php @@ -5,8 +5,8 @@ 'b', 'b', '', - 'de_DE', - [ + \Atoolo\Resource\ResourceLanguage::of('de_DE'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'navigation' => [ @@ -18,5 +18,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php index cead96f..8de8e6b 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php @@ -5,8 +5,8 @@ 'c', 'c', '', - 'de_DE', - [ + \Atoolo\Resource\ResourceLanguage::of('de_DE'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'navigation' => [ @@ -22,5 +22,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php index 381d6aa..b33db91 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php @@ -5,6 +5,6 @@ 'dir-index', 'dir-index', '', - 'de_DE', - [] + \Atoolo\Resource\ResourceLanguage::of('de_DE'), + new \Atoolo\Resource\DataBag([]) ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php index ee5e89c..db994eb 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php @@ -5,10 +5,10 @@ 'root', 'root', '', - 'de_DE', - [ + \Atoolo\Resource\ResourceLanguage::of('de_DE'), + new \Atoolo\Resource\DataBag([ 'init' => [ 'home' => true ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php index b346f43..0d11734 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php @@ -5,10 +5,10 @@ 'a', 'a', '', - 'de_DE', - [ + \Atoolo\Resource\ResourceLanguage::of('de_DE'), + new \Atoolo\Resource\DataBag([ 'init' => [ 'home' => true ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php index 43919d7..bd6340c 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php @@ -5,8 +5,8 @@ 'b', 'b', '', - 'de_DE', - [ + \Atoolo\Resource\ResourceLanguage::of('de_DE'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'navigation' => [ @@ -18,5 +18,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php index 9ef8307..a5cff8f 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php @@ -5,8 +5,8 @@ 'c', 'c', '', - 'de_DE', - [ + \Atoolo\Resource\ResourceLanguage::of('de_DE'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'navigation' => [ @@ -22,5 +22,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php index 960770d..0e63894 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php @@ -5,6 +5,6 @@ 'a', 'a', '', - 'de_DE', - [] + \Atoolo\Resource\ResourceLanguage::of('de_DE'), + new \Atoolo\Resource\DataBag([]) ); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php index 09dc5fd..04da459 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php @@ -7,8 +7,8 @@ 'a', 'a', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::default(), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -21,5 +21,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php index a5625c3..311fe53 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php @@ -7,8 +7,8 @@ 'b', 'b', '', - 'en', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -26,5 +26,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php index ea950b0..ccc9ae7 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php @@ -7,8 +7,8 @@ 'c', 'c', '', - 'en', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -24,5 +24,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php index a1bd1e0..3d2b8f5 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php @@ -7,8 +7,8 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', - 'en', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -18,5 +18,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php index 34ad2e2..8489f97 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php @@ -7,8 +7,8 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', - 'en', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -20,5 +20,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php index 4c104cb..3aaae34 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php @@ -7,8 +7,8 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', - 'en', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -19,5 +19,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php index 6b0cd82..4c8fbac 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php @@ -7,8 +7,8 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', - 'en', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -18,5 +18,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php index c2b30fb..f2f0e00 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php @@ -7,8 +7,8 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', - 'en', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -21,5 +21,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php index 1084fd6..e891ee5 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php @@ -7,8 +7,8 @@ 'primaryParentWithoutUrl', 'primaryParentWithoutUrl', '', - 'en', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -20,5 +20,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/ResourceHierarchyFinder/a.php b/test/resources/ResourceHierarchyFinder/a.php index 09dc5fd..9200999 100644 --- a/test/resources/ResourceHierarchyFinder/a.php +++ b/test/resources/ResourceHierarchyFinder/a.php @@ -7,8 +7,8 @@ 'a', 'a', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -21,5 +21,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/ResourceHierarchyFinder/b.php b/test/resources/ResourceHierarchyFinder/b.php index 7761dc7..311fe53 100644 --- a/test/resources/ResourceHierarchyFinder/b.php +++ b/test/resources/ResourceHierarchyFinder/b.php @@ -7,8 +7,8 @@ 'b', 'b', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -26,5 +26,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/ResourceHierarchyFinder/c.php b/test/resources/ResourceHierarchyFinder/c.php index 3d30934..ccc9ae7 100644 --- a/test/resources/ResourceHierarchyFinder/c.php +++ b/test/resources/ResourceHierarchyFinder/c.php @@ -7,8 +7,8 @@ 'c', 'c', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -24,5 +24,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/ResourceHierarchyWalker/1.php b/test/resources/ResourceHierarchyWalker/1.php index 42a776e..2e052e2 100644 --- a/test/resources/ResourceHierarchyWalker/1.php +++ b/test/resources/ResourceHierarchyWalker/1.php @@ -7,8 +7,8 @@ '1', '1', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -26,5 +26,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/ResourceHierarchyWalker/1/1.php b/test/resources/ResourceHierarchyWalker/1/1.php index 009c581..9165877 100644 --- a/test/resources/ResourceHierarchyWalker/1/1.php +++ b/test/resources/ResourceHierarchyWalker/1/1.php @@ -7,8 +7,8 @@ '1-1', '1-1', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -29,5 +29,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/ResourceHierarchyWalker/1/1/1.php b/test/resources/ResourceHierarchyWalker/1/1/1.php index 430e73f..f9782c8 100644 --- a/test/resources/ResourceHierarchyWalker/1/1/1.php +++ b/test/resources/ResourceHierarchyWalker/1/1/1.php @@ -7,8 +7,8 @@ '1-1-1', '1-1-1', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -26,5 +26,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/ResourceHierarchyWalker/1/1/1/1.php b/test/resources/ResourceHierarchyWalker/1/1/1/1.php index 178cc7e..7234fa6 100644 --- a/test/resources/ResourceHierarchyWalker/1/1/1/1.php +++ b/test/resources/ResourceHierarchyWalker/1/1/1/1.php @@ -7,8 +7,8 @@ '1-1-1-1', '1-1-1-1', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -20,5 +20,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/ResourceHierarchyWalker/2.php b/test/resources/ResourceHierarchyWalker/2.php index 534f3fd..184a871 100644 --- a/test/resources/ResourceHierarchyWalker/2.php +++ b/test/resources/ResourceHierarchyWalker/2.php @@ -7,8 +7,8 @@ '2', '2', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -30,5 +30,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/ResourceHierarchyWalker/2/1.php b/test/resources/ResourceHierarchyWalker/2/1.php index ee1b720..e13ccf3 100644 --- a/test/resources/ResourceHierarchyWalker/2/1.php +++ b/test/resources/ResourceHierarchyWalker/2/1.php @@ -7,8 +7,8 @@ '2-1', '2-1', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -20,5 +20,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/ResourceHierarchyWalker/2/2.php b/test/resources/ResourceHierarchyWalker/2/2.php index 0606e97..8836103 100644 --- a/test/resources/ResourceHierarchyWalker/2/2.php +++ b/test/resources/ResourceHierarchyWalker/2/2.php @@ -7,8 +7,8 @@ '2-2', '2-2', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -20,5 +20,5 @@ ] ] ] - ] + ]) ); diff --git a/test/resources/ResourceHierarchyWalker/root.php b/test/resources/ResourceHierarchyWalker/root.php index 867b32d..c181713 100644 --- a/test/resources/ResourceHierarchyWalker/root.php +++ b/test/resources/ResourceHierarchyWalker/root.php @@ -7,8 +7,8 @@ 'root', 'root', '', - '', - [ + \Atoolo\Resource\ResourceLanguage::of('en'), + new \Atoolo\Resource\DataBag([ 'base' => [ 'trees' => [ 'category' => [ @@ -25,5 +25,5 @@ ] ] ] - ] + ]) ); From 584fee87f6cb6093d02e45370229c32da1f54a0d Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 18 Apr 2024 09:33:53 +0200 Subject: [PATCH 29/31] fix: phpcs fixes --- test/Loader/SiteKitLoaderTest.php | 16 ++++++++++++---- test/ResourceLanguageTest.php | 5 ++--- test/ResourceLocationTest.php | 1 - 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/test/Loader/SiteKitLoaderTest.php b/test/Loader/SiteKitLoaderTest.php index 50f1079..8c17fb7 100644 --- a/test/Loader/SiteKitLoaderTest.php +++ b/test/Loader/SiteKitLoaderTest.php @@ -137,25 +137,33 @@ public function testLoadWithNonStringName(): void public function testLoadWithMissingObjectType(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load(ResourceLocation::of('missingObjectTypeResource.php')); + $this->loader->load( + ResourceLocation::of('missingObjectTypeResource.php') + ); } public function testLoadWithNonStringObjectType(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load(ResourceLocation::of('nonStringObjectTypeResource.php')); + $this->loader->load( + ResourceLocation::of('nonStringObjectTypeResource.php') + ); } public function testLoadWithMissingLocale(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load(ResourceLocation::of('missingLocaleResource.php')); + $this->loader->load( + ResourceLocation::of('missingLocaleResource.php') + ); } public function testLoadWithNonStringLocale(): void { $this->expectException(InvalidResourceException::class); - $this->loader->load(ResourceLocation::of('nonStringLocaleResource.php')); + $this->loader->load( + ResourceLocation::of('nonStringLocaleResource.php') + ); } public function testLoadWithNonArrayReturned(): void diff --git a/test/ResourceLanguageTest.php b/test/ResourceLanguageTest.php index 00f102e..02f47f1 100644 --- a/test/ResourceLanguageTest.php +++ b/test/ResourceLanguageTest.php @@ -29,7 +29,7 @@ public function testOfWithLocale(): void $this->assertSame('en', $language->code); } - public function testOfWithISO_639_1(): void + public function testOfWithISO639part1(): void { $language = ResourceLanguage::of('de-at'); $this->assertSame('de', $language->code); @@ -47,9 +47,8 @@ public function testOfWithEmptyString(): void $this->assertSame('', $language->code); } - /* - public function testOfWithISO_639_2(): void + public function testOfWithISO639part2(): void { $language = ResourceLanguage::of('ger'); $this->assertSame('de', $language->code); diff --git a/test/ResourceLocationTest.php b/test/ResourceLocationTest.php index ddda103..5338d6f 100644 --- a/test/ResourceLocationTest.php +++ b/test/ResourceLocationTest.php @@ -58,5 +58,4 @@ public function testToStringWithLang(): void 'unexpected string' ); } - } From 9194073e31b3719f2ae4392f5475f03e9a4f4ad1 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 18 Apr 2024 15:03:37 +0200 Subject: [PATCH 30/31] test: refactor resource creation --- src/Loader/CachedResourceLoader.php | 1 - .../SiteKitNavigationHierarchyLoader.php | 2 +- test/DataBagTest.php | 1 - test/Exceptions/InvalidResourceTest.php | 1 - test/Exceptions/ResourceNotFoundTest.php | 1 - test/Exceptions/RootMissingExceptionTest.php | 2 - .../SiteKitNavigationHierarchyLoaderTest.php | 17 ++++- .../SiteKitResourceHierarchyLoaderTest.php | 71 ++++++++----------- test/ResourceHierarchyWalkerTest.php | 9 +-- test/ResourceTest.php | 14 ++-- test/TestResourceFactory.php | 24 +++++++ .../withDefaultRoot/dir/a.php | 18 ++--- .../withDefaultRoot/dir/b.php | 33 ++++----- .../withDefaultRoot/dir/c.php | 41 +++++------ .../withDefaultRoot/dir/index.php | 18 ++--- .../withDefaultRoot/index.php | 4 +- .../withHomeFlag/a.php | 4 +- .../withHomeFlag/b.php | 33 ++++----- .../withHomeFlag/c.php | 41 +++++------ .../withoutRoot/a.php | 18 ++--- .../SiteKitResourceHierarchyLoader/a.php | 33 +++++---- .../SiteKitResourceHierarchyLoader/b.php | 43 ++++++----- .../SiteKitResourceHierarchyLoader/c.php | 39 +++++----- .../childrenWithInvalidData.php | 29 ++++---- .../firstParentWithNonStringUrl.php | 31 ++++---- .../firstParentWithoutUrl.php | 29 ++++---- .../primaryParentWithInvalidData.php | 29 ++++---- .../primaryParentWithNonStringUrl.php | 33 +++++---- .../primaryParentWithoutUrl.php | 31 ++++---- test/resources/ResourceHierarchyFinder/a.php | 33 +++++---- test/resources/ResourceHierarchyFinder/b.php | 43 ++++++----- test/resources/ResourceHierarchyFinder/c.php | 39 +++++----- test/resources/ResourceHierarchyWalker/1.php | 43 ++++++----- .../resources/ResourceHierarchyWalker/1/1.php | 47 ++++++------ .../ResourceHierarchyWalker/1/1/1.php | 43 ++++++----- .../ResourceHierarchyWalker/1/1/1/1.php | 35 +++++---- test/resources/ResourceHierarchyWalker/2.php | 49 +++++++------ .../resources/ResourceHierarchyWalker/2/1.php | 31 ++++---- .../resources/ResourceHierarchyWalker/2/2.php | 31 ++++---- .../ResourceHierarchyWalker/root.php | 41 ++++++----- 40 files changed, 541 insertions(+), 544 deletions(-) create mode 100644 test/TestResourceFactory.php diff --git a/src/Loader/CachedResourceLoader.php b/src/Loader/CachedResourceLoader.php index 2b89cc4..1bd83a9 100644 --- a/src/Loader/CachedResourceLoader.php +++ b/src/Loader/CachedResourceLoader.php @@ -7,7 +7,6 @@ use Atoolo\Resource\Exception\InvalidResourceException; use Atoolo\Resource\Exception\ResourceNotFoundException; use Atoolo\Resource\Resource; -use Atoolo\Resource\ResourceLanguage; use Atoolo\Resource\ResourceLoader; use Atoolo\Resource\ResourceLocation; diff --git a/src/Loader/SiteKitNavigationHierarchyLoader.php b/src/Loader/SiteKitNavigationHierarchyLoader.php index cf8a250..46f9e42 100644 --- a/src/Loader/SiteKitNavigationHierarchyLoader.php +++ b/src/Loader/SiteKitNavigationHierarchyLoader.php @@ -20,7 +20,7 @@ public function __construct(ResourceLoader $resourceLoader) public function isRoot(Resource $resource): bool { - return $resource->data->getBool('init.home'); + return $resource->data->getBool('home'); } /** diff --git a/test/DataBagTest.php b/test/DataBagTest.php index 3026615..a9ae6ef 100644 --- a/test/DataBagTest.php +++ b/test/DataBagTest.php @@ -5,7 +5,6 @@ namespace Atoolo\Resource\Test; use Atoolo\Resource\DataBag; -use Atoolo\Resource\Resource; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; diff --git a/test/Exceptions/InvalidResourceTest.php b/test/Exceptions/InvalidResourceTest.php index 8560a69..892a7fe 100644 --- a/test/Exceptions/InvalidResourceTest.php +++ b/test/Exceptions/InvalidResourceTest.php @@ -5,7 +5,6 @@ namespace Atoolo\Resource\Test\Exceptions; use Atoolo\Resource\Exception\InvalidResourceException; -use Atoolo\Resource\Loader\CachedResourceLoader; use Atoolo\Resource\ResourceLocation; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; diff --git a/test/Exceptions/ResourceNotFoundTest.php b/test/Exceptions/ResourceNotFoundTest.php index e5a3bfe..99d6617 100644 --- a/test/Exceptions/ResourceNotFoundTest.php +++ b/test/Exceptions/ResourceNotFoundTest.php @@ -4,7 +4,6 @@ namespace Atoolo\Resource\Test\Exceptions; -use Atoolo\Resource\Exception\InvalidResourceException; use Atoolo\Resource\Exception\ResourceNotFoundException; use Atoolo\Resource\ResourceLocation; use PHPUnit\Framework\Attributes\CoversClass; diff --git a/test/Exceptions/RootMissingExceptionTest.php b/test/Exceptions/RootMissingExceptionTest.php index 588d7cd..10ce23a 100644 --- a/test/Exceptions/RootMissingExceptionTest.php +++ b/test/Exceptions/RootMissingExceptionTest.php @@ -4,8 +4,6 @@ namespace Atoolo\Resource\Test\Exceptions; -use Atoolo\Resource\Exception\InvalidResourceException; -use Atoolo\Resource\Exception\ResourceNotFoundException; use Atoolo\Resource\Exception\RootMissingException; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; diff --git a/test/Loader/SiteKitNavigationHierarchyLoaderTest.php b/test/Loader/SiteKitNavigationHierarchyLoaderTest.php index e801fe9..6b7d9b8 100644 --- a/test/Loader/SiteKitNavigationHierarchyLoaderTest.php +++ b/test/Loader/SiteKitNavigationHierarchyLoaderTest.php @@ -4,17 +4,32 @@ namespace Atoolo\Resource\Test\Loader; -use Atoolo\Resource\Exception\InvalidResourceException; use Atoolo\Resource\Exception\RootMissingException; use Atoolo\Resource\Loader\SiteKitNavigationHierarchyLoader; use Atoolo\Resource\ResourceLoader; use Atoolo\Resource\ResourceLocation; +use Atoolo\Resource\Test\TestResourceFactory; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; #[CoversClass(SiteKitNavigationHierarchyLoader::class)] class SiteKitNavigationHierarchyLoaderTest extends TestCase { + public function testIsRoot(): void + { + $treeLoader = $this->createTreeLoader(''); + + $root = TestResourceFactory::create([ + 'home' => true + ]); + + $isRoot = $treeLoader->isRoot($root); + $this->assertTrue( + $isRoot, + 'should be root' + ); + } + public function testLoadRootResourceWithHomeFlag(): void { $treeLoader = $this->createTreeLoader( diff --git a/test/Loader/SiteKitResourceHierarchyLoaderTest.php b/test/Loader/SiteKitResourceHierarchyLoaderTest.php index 98230d7..bcb75af 100644 --- a/test/Loader/SiteKitResourceHierarchyLoaderTest.php +++ b/test/Loader/SiteKitResourceHierarchyLoaderTest.php @@ -9,6 +9,7 @@ use Atoolo\Resource\Resource; use Atoolo\Resource\ResourceLoader; use Atoolo\Resource\ResourceLocation; +use Atoolo\Resource\Test\TestResourceFactory; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\TestCase; @@ -106,6 +107,17 @@ public function testLoadRoot(): void ); } + public function testIsRoot(): void + { + $root = TestResourceFactory::create([]); + $isRoot = $this->hierarchyLoader->isRoot($root); + + $this->assertTrue( + $isRoot, + 'should be root' + ); + } + public function testLoadPrimaryParent(): void { $parent = $this->hierarchyLoader->loadPrimaryParent( @@ -261,14 +273,7 @@ public function testLoadParentOfRoot(): void public function testGetParentLocationWithoutParents(): void { - $resource = new Resource( - '', - '', - '', - '', - \Atoolo\Resource\ResourceLanguage::default(), - new \Atoolo\Resource\DataBag([]) - ); + $resource = TestResourceFactory::create([]); $parent = $this->hierarchyLoader->getParentLocation( $resource, 'x' @@ -281,24 +286,17 @@ public function testGetParentLocationWithoutParents(): void public function testGetParentLocationWithInvalidData(): void { - $resource = new Resource( - '', - '', - '', - '', - \Atoolo\Resource\ResourceLanguage::default(), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'a' => 'invalid' - ] + $resource = TestResourceFactory::create([ + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => 'invalid' ] ] ] - ]) - ); + ] + ]); $this->expectException(InvalidResourceException::class); $this->hierarchyLoader->getParentLocation( @@ -309,27 +307,20 @@ public function testGetParentLocationWithInvalidData(): void public function testGetParentLocationWithParentIdNotFound(): void { - $resource = new Resource( - '', - '', - '', - '', - \Atoolo\Resource\ResourceLanguage::default(), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'a' => [ - 'id' => 'a', - 'url' => '/a.php' - ] + $resource = TestResourceFactory::create([ + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => [ + 'id' => 'a', + 'url' => '/a.php' ] ] ] ] - ]) - ); + ] + ]); $parent = $this->hierarchyLoader->getParentLocation( $resource, diff --git a/test/ResourceHierarchyWalkerTest.php b/test/ResourceHierarchyWalkerTest.php index a73e81b..c5ba543 100644 --- a/test/ResourceHierarchyWalkerTest.php +++ b/test/ResourceHierarchyWalkerTest.php @@ -395,14 +395,7 @@ public function testChildWithoutChildren(): void $walker = new ResourceHierarchyWalker( $hierarchyLoader ); - $base = new Resource( - '', - '', - '', - '', - \Atoolo\Resource\ResourceLanguage::default(), - new \Atoolo\Resource\DataBag([]) - ); + $base = TestResourceFactory::create([]); $walker->init($base); diff --git a/test/ResourceTest.php b/test/ResourceTest.php index 39cb7e5..45d5978 100644 --- a/test/ResourceTest.php +++ b/test/ResourceTest.php @@ -4,9 +4,7 @@ namespace Atoolo\Resource\Test; -use Atoolo\Resource\DataBag; use Atoolo\Resource\Resource; -use Atoolo\Resource\ResourceLanguage; use Atoolo\Resource\ResourceLocation; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -16,14 +14,10 @@ class ResourceTest extends TestCase { public function testToLocation(): void { - $resource = new Resource( - 'path', - '', - '', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([]) - ); + $resource = TestResourceFactory::create([ + 'url' => 'path', + 'locale' => 'en_US' + ]); $this->assertEquals( ResourceLocation::of( 'path', diff --git a/test/TestResourceFactory.php b/test/TestResourceFactory.php new file mode 100644 index 0000000..f139c1c --- /dev/null +++ b/test/TestResourceFactory.php @@ -0,0 +1,24 @@ + '/dir/a.php', + 'id' => 'a', + 'name' => 'a', + 'locale' => 'en_US', +]); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php index 9d24829..37285f0 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/b.php @@ -1,22 +1,23 @@ [ - 'trees' => [ - 'navigation' => [ - 'parents' => [ - 'a' => [ - 'url' => '/dir/a.php' - ] +declare(strict_types=1); + +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/dir/a.php', + 'id' => 'a', + 'name' => 'a', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'navigation' => [ + 'parents' => [ + 'a' => [ + 'url' => '/dir/a.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php index 8de8e6b..12f8b5f 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/c.php @@ -1,26 +1,27 @@ [ - 'trees' => [ - 'navigation' => [ - 'parents' => [ - 'b' => [ - 'isPrimary' => true, - 'url' => '/dir/b.php' - ], - 'a' => [ - 'url' => '/dir/a.php' - ] +declare(strict_types=1); + +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/dir/c.php', + 'id' => 'c', + 'name' => 'c', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'navigation' => [ + 'parents' => [ + 'b' => [ + 'isPrimary' => true, + 'url' => '/dir/b.php' + ], + 'a' => [ + 'url' => '/dir/a.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php index b33db91..8ea34a5 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/dir/index.php @@ -1,10 +1,12 @@ '/dir/index.php', + 'id' => 'dir-index', + 'name' => 'dir-index', + 'locale' => 'en_US', +]); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php index db994eb..84f03b4 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withDefaultRoot/index.php @@ -7,8 +7,6 @@ '', \Atoolo\Resource\ResourceLanguage::of('de_DE'), new \Atoolo\Resource\DataBag([ - 'init' => [ - 'home' => true - ] + 'home' => true ]) ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php index 0d11734..edce0d1 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/a.php @@ -7,8 +7,6 @@ '', \Atoolo\Resource\ResourceLanguage::of('de_DE'), new \Atoolo\Resource\DataBag([ - 'init' => [ - 'home' => true - ] + 'home' => true ]) ); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php index bd6340c..94b1b5d 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/b.php @@ -1,22 +1,23 @@ [ - 'trees' => [ - 'navigation' => [ - 'parents' => [ - 'a' => [ - 'url' => '/a.php' - ] +declare(strict_types=1); + +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/b.php', + 'id' => 'b', + 'name' => 'b', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'navigation' => [ + 'parents' => [ + 'a' => [ + 'url' => '/a.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php index a5cff8f..40750a2 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withHomeFlag/c.php @@ -1,26 +1,27 @@ [ - 'trees' => [ - 'navigation' => [ - 'parents' => [ - 'b' => [ - 'isPrimary' => true, - 'url' => '/b.php' - ], - 'a' => [ - 'url' => '/a.php' - ] +declare(strict_types=1); + +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/c.php', + 'id' => 'c', + 'name' => 'c', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'navigation' => [ + 'parents' => [ + 'b' => [ + 'isPrimary' => true, + 'url' => '/b.php' + ], + 'a' => [ + 'url' => '/a.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php index 0e63894..5f75513 100644 --- a/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php +++ b/test/resources/Loader/SiteKitNavigationHierarchyLoader/withoutRoot/a.php @@ -1,10 +1,12 @@ '/a.php', + 'id' => 'a', + 'name' => 'a', + 'locale' => 'en_US', +]); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php index 04da459..e7e5bd3 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/a.php @@ -2,24 +2,23 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/a.php', - 'a', - 'a', - '', - \Atoolo\Resource\ResourceLanguage::default(), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'children' => [ - 'b' => [ - 'id' => 'b', - 'url' => '/b.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/a.php', + 'id' => 'a', + 'name' => 'a', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'children' => [ + 'b' => [ + 'id' => 'b', + 'url' => '/b.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php index 311fe53..5e26c1a 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/b.php @@ -2,29 +2,28 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/b.php', - 'b', - 'b', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'a' => [ - 'url' => '/a.php' - ] - ], - 'children' => [ - 'c' => [ - 'id' => 'c', - 'url' => '/c.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/b.php', + 'id' => 'b', + 'name' => 'b', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => [ + 'url' => '/a.php' + ] + ], + 'children' => [ + 'c' => [ + 'id' => 'c', + 'url' => '/c.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php index ccc9ae7..eb83457 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/c.php @@ -2,27 +2,26 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/c.php', - 'c', - 'c', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'b' => [ - 'isPrimary' => true, - 'url' => '/b.php' - ], - 'a' => [ - 'url' => '/a.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/c.php', + 'id' => 'c', + 'name' => 'c', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'b' => [ + 'isPrimary' => true, + 'url' => '/b.php' + ], + 'a' => [ + 'url' => '/a.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php index 3d2b8f5..bd718f8 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/childrenWithInvalidData.php @@ -2,21 +2,20 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/primaryParentWithoutUrl.php', - 'primaryParentWithoutUrl', - 'primaryParentWithoutUrl', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'children' => [ - 'a' => 'invalid' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/childrenWithInvalidData.php', + 'id' => 'childrenWithInvalidData', + 'name' => 'childrenWithInvalidData', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'children' => [ + 'a' => 'invalid' ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php index 8489f97..f3b4790 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithNonStringUrl.php @@ -2,23 +2,22 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/primaryParentWithoutUrl.php', - 'primaryParentWithoutUrl', - 'primaryParentWithoutUrl', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'a' => [ - 'url' => false - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/firstParentWithNonStringUrl.php', + 'id' => 'firstParentWithNonStringUrl', + 'name' => 'firstParentWithNonStringUrl', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => [ + 'url' => false ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php index 3aaae34..4af24d2 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/firstParentWithoutUrl.php @@ -2,22 +2,21 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/primaryParentWithoutUrl.php', - 'primaryParentWithoutUrl', - 'primaryParentWithoutUrl', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'a' => [ - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/firstParentWithoutUrl.php', + 'id' => 'firstParentWithoutUrl', + 'name' => 'firstParentWithoutUrl', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => [ ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php index 4c8fbac..6e51e22 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithInvalidData.php @@ -2,21 +2,20 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/primaryParentWithoutUrl.php', - 'primaryParentWithoutUrl', - 'primaryParentWithoutUrl', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'a' => 'invalid' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/primaryParentWithInvalidData.php', + 'id' => 'primaryParentWithInvalidData', + 'name' => 'primaryParentWithInvalidData', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => 'invalid' ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php index f2f0e00..a3f023b 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithNonStringUrl.php @@ -2,24 +2,23 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/primaryParentWithoutUrl.php', - 'primaryParentWithoutUrl', - 'primaryParentWithoutUrl', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'a' => [ - 'isPrimary' => true, - 'url' => false - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/primaryParentWithNonStringUrl.php', + 'id' => 'primaryParentWithNonStringUrl', + 'name' => 'primaryParentWithNonStringUrl', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => [ + 'isPrimary' => true, + 'url' => false ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php index e891ee5..33659be 100644 --- a/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php +++ b/test/resources/Loader/SiteKitResourceHierarchyLoader/primaryParentWithoutUrl.php @@ -2,23 +2,22 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/primaryParentWithoutUrl.php', - 'primaryParentWithoutUrl', - 'primaryParentWithoutUrl', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'a' => [ - 'isPrimary' => true, - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/primaryParentWithoutUrl.php', + 'id' => 'primaryParentWithoutUrl', + 'name' => 'primaryParentWithoutUrl', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => [ + 'isPrimary' => true, ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/ResourceHierarchyFinder/a.php b/test/resources/ResourceHierarchyFinder/a.php index 9200999..e7e5bd3 100644 --- a/test/resources/ResourceHierarchyFinder/a.php +++ b/test/resources/ResourceHierarchyFinder/a.php @@ -2,24 +2,23 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/a.php', - 'a', - 'a', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'children' => [ - 'b' => [ - 'id' => 'b', - 'url' => '/b.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/a.php', + 'id' => 'a', + 'name' => 'a', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'children' => [ + 'b' => [ + 'id' => 'b', + 'url' => '/b.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/ResourceHierarchyFinder/b.php b/test/resources/ResourceHierarchyFinder/b.php index 311fe53..5e26c1a 100644 --- a/test/resources/ResourceHierarchyFinder/b.php +++ b/test/resources/ResourceHierarchyFinder/b.php @@ -2,29 +2,28 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/b.php', - 'b', - 'b', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'a' => [ - 'url' => '/a.php' - ] - ], - 'children' => [ - 'c' => [ - 'id' => 'c', - 'url' => '/c.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/b.php', + 'id' => 'b', + 'name' => 'b', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'a' => [ + 'url' => '/a.php' + ] + ], + 'children' => [ + 'c' => [ + 'id' => 'c', + 'url' => '/c.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/ResourceHierarchyFinder/c.php b/test/resources/ResourceHierarchyFinder/c.php index ccc9ae7..eb83457 100644 --- a/test/resources/ResourceHierarchyFinder/c.php +++ b/test/resources/ResourceHierarchyFinder/c.php @@ -2,27 +2,26 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/c.php', - 'c', - 'c', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'b' => [ - 'isPrimary' => true, - 'url' => '/b.php' - ], - 'a' => [ - 'url' => '/a.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/c.php', + 'id' => 'c', + 'name' => 'c', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'b' => [ + 'isPrimary' => true, + 'url' => '/b.php' + ], + 'a' => [ + 'url' => '/a.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/ResourceHierarchyWalker/1.php b/test/resources/ResourceHierarchyWalker/1.php index 2e052e2..63df4ec 100644 --- a/test/resources/ResourceHierarchyWalker/1.php +++ b/test/resources/ResourceHierarchyWalker/1.php @@ -2,29 +2,28 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/1.php', - '1', - '1', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'root' => [ - 'url' => '/root.php' - ] - ], - 'children' => [ - '1-1' => [ - 'id' => '1-1', - 'url' => '/1/1.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/1.php', + 'id' => '1', + 'name' => '1', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'root' => [ + 'url' => '/root.php' + ] + ], + 'children' => [ + '1-1' => [ + 'id' => '1-1', + 'url' => '/1/1.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/ResourceHierarchyWalker/1/1.php b/test/resources/ResourceHierarchyWalker/1/1.php index 9165877..58e6fa1 100644 --- a/test/resources/ResourceHierarchyWalker/1/1.php +++ b/test/resources/ResourceHierarchyWalker/1/1.php @@ -2,32 +2,31 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/1/1.php', - '1-1', - '1-1', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - '1' => [ - 'url' => '/1.php' - ], - '2' => [ - 'url' => '/2.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/1/1.php', + 'id' => '1-1', + 'name' => '1-1', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + '1' => [ + 'url' => '/1.php' ], - 'children' => [ - '1-1-1' => [ - 'id' => '1-1-1', - 'url' => '/1/1/1.php' - ] + '2' => [ + 'url' => '/2.php' + ] + ], + 'children' => [ + '1-1-1' => [ + 'id' => '1-1-1', + 'url' => '/1/1/1.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/ResourceHierarchyWalker/1/1/1.php b/test/resources/ResourceHierarchyWalker/1/1/1.php index f9782c8..c11feac 100644 --- a/test/resources/ResourceHierarchyWalker/1/1/1.php +++ b/test/resources/ResourceHierarchyWalker/1/1/1.php @@ -2,29 +2,28 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/1/1/1.php', - '1-1-1', - '1-1-1', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - '1-1' => [ - 'url' => '/1/1.php' - ] - ], - 'children' => [ - '1-1-1-1' => [ - 'id' => '1-1-1-1', - 'url' => '/1/1/1/1.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/1/1/1.php', + 'id' => '1-1-1', + 'name' => '1-1-1', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + '1-1' => [ + 'url' => '/1/1.php' + ] + ], + 'children' => [ + '1-1-1-1' => [ + 'id' => '1-1-1-1', + 'url' => '/1/1/1/1.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/ResourceHierarchyWalker/1/1/1/1.php b/test/resources/ResourceHierarchyWalker/1/1/1/1.php index 7234fa6..33a9e75 100644 --- a/test/resources/ResourceHierarchyWalker/1/1/1/1.php +++ b/test/resources/ResourceHierarchyWalker/1/1/1/1.php @@ -2,23 +2,22 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/1-1-1-1.php', - '1-1-1-1', - '1-1-1-1', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - '1-1-1' => [ - 'url' => '/1/1/1.php' - ] - ], - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/1/1/1/1.php', + 'id' => '1-1-1-1', + 'name' => '1-1-1-1', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + '1-1-1' => [ + 'url' => '/1/1/1.php' + ] + ], ] ] - ]) -); + ] +]); diff --git a/test/resources/ResourceHierarchyWalker/2.php b/test/resources/ResourceHierarchyWalker/2.php index 184a871..72e3dd8 100644 --- a/test/resources/ResourceHierarchyWalker/2.php +++ b/test/resources/ResourceHierarchyWalker/2.php @@ -2,33 +2,32 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/2.php', - '2', - '2', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - 'root' => [ - 'url' => '/root.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/2.php', + 'id' => '2', + 'name' => '2', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + 'root' => [ + 'url' => '/root.php' + ] + ], + 'children' => [ + '2-1' => [ + 'id' => '2-1', + 'url' => '/2/1.php' ], - 'children' => [ - '2-1' => [ - 'id' => '2-1', - 'url' => '/2/1.php' - ], - '2-2' => [ - 'id' => '2-2', - 'url' => '/2/2.php' - ] + '2-2' => [ + 'id' => '2-2', + 'url' => '/2/2.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/ResourceHierarchyWalker/2/1.php b/test/resources/ResourceHierarchyWalker/2/1.php index e13ccf3..11478d4 100644 --- a/test/resources/ResourceHierarchyWalker/2/1.php +++ b/test/resources/ResourceHierarchyWalker/2/1.php @@ -2,23 +2,22 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/2/1.php', - '2-1', - '2-1', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - '2' => [ - 'url' => '/2.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/2/1.php', + 'id' => '2-1', + 'name' => '2-1', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + '2' => [ + 'url' => '/2.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/ResourceHierarchyWalker/2/2.php b/test/resources/ResourceHierarchyWalker/2/2.php index 8836103..461c759 100644 --- a/test/resources/ResourceHierarchyWalker/2/2.php +++ b/test/resources/ResourceHierarchyWalker/2/2.php @@ -2,23 +2,22 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/2/2.php', - '2-2', - '2-2', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'parents' => [ - '2' => [ - 'url' => '/2.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/2/2.php', + 'id' => '2-2', + 'name' => '2-2', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'parents' => [ + '2' => [ + 'url' => '/2.php' ] ] ] ] - ]) -); + ] +]); diff --git a/test/resources/ResourceHierarchyWalker/root.php b/test/resources/ResourceHierarchyWalker/root.php index c181713..fd66c38 100644 --- a/test/resources/ResourceHierarchyWalker/root.php +++ b/test/resources/ResourceHierarchyWalker/root.php @@ -2,28 +2,27 @@ declare(strict_types=1); -return new \Atoolo\Resource\Resource( - '/root.php', - 'root', - 'root', - '', - \Atoolo\Resource\ResourceLanguage::of('en'), - new \Atoolo\Resource\DataBag([ - 'base' => [ - 'trees' => [ - 'category' => [ - 'children' => [ - '1 1' => [ - 'id' => '1', - 'url' => '/1.php' - ], - '2' => [ - 'id' => '2', - 'url' => '/2.php' - ] +use Atoolo\Resource\Test\TestResourceFactory; + +return TestResourceFactory::create([ + 'url' => '/root.php', + 'id' => 'root', + 'name' => 'root', + 'locale' => 'en_US', + 'base' => [ + 'trees' => [ + 'category' => [ + 'children' => [ + '1 1' => [ + 'id' => '1', + 'url' => '/1.php' + ], + '2' => [ + 'id' => '2', + 'url' => '/2.php' ] ] ] ] - ]) -); + ] +]); From 3feb7f302e47a88613007204e1f3c82dbccc83a3 Mon Sep 17 00:00:00 2001 From: Holger Veltrup Date: Thu, 18 Apr 2024 15:43:30 +0200 Subject: [PATCH 31/31] refactor: code review suggestion --- src/Loader/SiteKitResourceHierarchyLoader.php | 5 +---- src/ResourceHierarchyWalker.php | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Loader/SiteKitResourceHierarchyLoader.php b/src/Loader/SiteKitResourceHierarchyLoader.php index feb2df0..0965cb9 100644 --- a/src/Loader/SiteKitResourceHierarchyLoader.php +++ b/src/Loader/SiteKitResourceHierarchyLoader.php @@ -122,10 +122,7 @@ protected function loadPrimaryParentResource( $parentLocation = $this->getPrimaryParentLocation($resource); if ($parentLocation === null) { throw new InvalidResourceException( - ResourceLocation::of( - $resource->location, - $resource->lang - ), + $resource->toLocation(), 'the resources should have a parent' ); } diff --git a/src/ResourceHierarchyWalker.php b/src/ResourceHierarchyWalker.php index 0605fc0..e87a57b 100644 --- a/src/ResourceHierarchyWalker.php +++ b/src/ResourceHierarchyWalker.php @@ -75,8 +75,7 @@ public function __construct( public function init(Resource|ResourceLocation $base): Resource { if ($base instanceof ResourceLocation) { - $this->lang = $base->lang; - $base = $this->load($base->location); + $base = $this->hierarchyLoader->load($base); } $this->current = $base; $this->lang = $base->lang;