From 131946a10c9554e572d11c0285d612e34e2b1488 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Thu, 19 Oct 2023 12:00:53 +0100 Subject: [PATCH] Fix for dynamic sibling files (#56) * feature: deeper dynamic pages closes #4 * build: upgrade build packages for downstream deps * tweak: phpstorm analysis * wip: isolate and work on #55 * fix: fix logic comparing sibling files closes #55 --- src/Path/FileMatch/FileMatch.php | 39 ++++++++++++++++++- .../Path/FileMatch/BasicFileMatchTest.php | 13 +++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/Path/FileMatch/FileMatch.php b/src/Path/FileMatch/FileMatch.php index 3404ec7..295b6e9 100644 --- a/src/Path/FileMatch/FileMatch.php +++ b/src/Path/FileMatch/FileMatch.php @@ -2,10 +2,39 @@ namespace Gt\Routing\Path\FileMatch; abstract class FileMatch { + /** @var array> An array of paths parts for the siblings of the file path */ + protected array $siblingFilePathParts; + + /** @param null|array $siblingFiles Sibling files on disk to the current file path */ public function __construct( protected string $filePath, protected string $baseDir, + ?array $siblingFiles = null, ) { + $dirname = dirname($this->filePath); + $ext = pathinfo($this->filePath, PATHINFO_EXTENSION); + + $this->siblingFilePathParts = []; + foreach($siblingFiles ?? glob("$dirname/*.$ext") as $filePath) { + $filePathNoBaseDir = substr($filePath, strlen($this->baseDir . "/")); + $pathParts = explode("/", $filePathNoBaseDir); + foreach($pathParts as $i => $pathPart) { + if(str_contains($pathPart, "@")) { + $pathParts[$i] = "@"; + } + else { + $dotPos = strpos($pathPart, "."); + if($dotPos !== false) { + $pathParts[$i] = substr($pathPart, 0, $dotPos); + } + } + } + + array_push( + $this->siblingFilePathParts, + $pathParts, + ); + } } abstract public function matches(string $uriPath):bool; @@ -44,14 +73,20 @@ protected function filterDynamicPathParts( array $uriPathParts ):array { $filePathParts = explode("/", $filePath); + $matchingSibling = in_array($uriPathParts, $this->siblingFilePathParts); + foreach($uriPathParts as $i => $uriPathPart) { if(!isset($filePathParts[$i])) { break; } $filePathPart = $filePathParts[$i]; - if($filePathPart === "@") { - $uriPathParts[$i] = "@"; + +// On the last iteration, don't convert if there's a sibling match. + if(isset($filePathParts[$i + 1]) || !$matchingSibling) { + if($filePathPart === "@") { + $uriPathParts[$i] = "@"; + } } } diff --git a/test/phpunit/Path/FileMatch/BasicFileMatchTest.php b/test/phpunit/Path/FileMatch/BasicFileMatchTest.php index cc37ecb..d4270e8 100644 --- a/test/phpunit/Path/FileMatch/BasicFileMatchTest.php +++ b/test/phpunit/Path/FileMatch/BasicFileMatchTest.php @@ -77,4 +77,17 @@ public function testMatches_dynamicDir_matchesIndex():void { ); self::assertTrue($sut->matches("/shop/cakes")); } + + public function testMatches_dynamicPath_siblingMatchesIndex():void { + $sut = new BasicFileMatch( + "page/request/@request-id.html", + "page", + [ + "page/request/index.html", + "page/request/secrets.html", + ] + ); + self::assertTrue($sut->matches("/request/dynamic-example")); + self::assertFalse($sut->matches("/request/secrets")); + } }