From 495aa203e78a6bfc85fbb081935926524179090f Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Mon, 14 Jun 2021 13:01:17 +0100 Subject: [PATCH] feature: dynamic path matching --- src/Path/FileMatch/BasicFileMatch.php | 8 +++-- src/Path/FileMatch/DynamicFileMatch.php | 7 ---- src/Path/FileMatch/FileMatch.php | 29 ++++++++++++++++ src/Path/FileMatch/MagicFileMatch.php | 7 ++-- .../Path/FileMatch/BasicFileMatchTest.php | 33 +++++++++++++++++++ .../Path/FileMatch/MagicFileMatchTest.php | 8 +++++ 6 files changed, 79 insertions(+), 13 deletions(-) delete mode 100644 src/Path/FileMatch/DynamicFileMatch.php diff --git a/src/Path/FileMatch/BasicFileMatch.php b/src/Path/FileMatch/BasicFileMatch.php index 7564dbc..73e5c9f 100644 --- a/src/Path/FileMatch/BasicFileMatch.php +++ b/src/Path/FileMatch/BasicFileMatch.php @@ -3,14 +3,16 @@ /** * A "Basic" FileMatch is one that directly matches a Uri path to a - * file path by name. Uris are + * file path by name. */ class BasicFileMatch extends FileMatch { public function matches(string $uriPath):bool { $uriPath = trim($uriPath, "/"); - $uriPathIndex = trim("$uriPath/index", "/"); - + $uriPathParts = explode("/", $uriPath); $filePathTrimmed = $this->getTrimmedFilePath(); + $uriPathParts = $this->filterDynamicPathParts($filePathTrimmed, $uriPathParts); + $uriPath = implode("/", $uriPathParts); + $uriPathIndex = trim("$uriPath/index", "/"); if($uriPath === $filePathTrimmed || $uriPathIndex === $filePathTrimmed) { diff --git a/src/Path/FileMatch/DynamicFileMatch.php b/src/Path/FileMatch/DynamicFileMatch.php deleted file mode 100644 index 789b0cc..0000000 --- a/src/Path/FileMatch/DynamicFileMatch.php +++ /dev/null @@ -1,7 +0,0 @@ -filePath, PATHINFO_DIRNAME), pathinfo($this->filePath, PATHINFO_FILENAME), ]); + $filePathTrimmed = preg_replace( + "/\/@[^\/]+/", + "/@", + $filePathTrimmed + ); if($includeBaseDir) { return $filePathTrimmed; @@ -28,4 +33,28 @@ protected function getTrimmedFilePath( ); } } + + /** + * @param string $filePath + * @param string[] $uriPathParts + * @return string[] + */ + protected function filterDynamicPathParts( + string $filePath, + array $uriPathParts + ):array { + $filePathParts = explode("/", $filePath); + foreach($uriPathParts as $i => $uriPathPart) { + if(!isset($filePathParts[$i])) { + break; + } + + $filePathPart = $filePathParts[$i]; + if($filePathPart === "@") { + $uriPathParts[$i] = "@"; + } + } + + return $uriPathParts; + } } diff --git a/src/Path/FileMatch/MagicFileMatch.php b/src/Path/FileMatch/MagicFileMatch.php index d9e636c..b4d0a5c 100644 --- a/src/Path/FileMatch/MagicFileMatch.php +++ b/src/Path/FileMatch/MagicFileMatch.php @@ -12,12 +12,13 @@ public function matches(string $uriPath):bool { $uriPath = trim($uriPath, "/"); $uriPathParts = explode("/", $uriPath); - $filePathTrimmed = $this->getTrimmedFilePath(true); + $filePathTrimmed = $this->getTrimmedFilePath(); + $uriPathParts = $this->filterDynamicPathParts($filePathTrimmed, $uriPathParts); - $searchDir = $this->baseDir; + $searchDir = ""; foreach($uriPathParts as $pathPart) { foreach(self::MAGIC_FILENAME_ARRAY as $magicFilename) { - $searchFilepath = "$searchDir/$magicFilename"; + $searchFilepath = trim("$searchDir/$magicFilename", "/"); if($searchFilepath === $filePathTrimmed) { return true; } diff --git a/test/phpunit/Path/FileMatch/BasicFileMatchTest.php b/test/phpunit/Path/FileMatch/BasicFileMatchTest.php index 5636500..cc37ecb 100644 --- a/test/phpunit/Path/FileMatch/BasicFileMatchTest.php +++ b/test/phpunit/Path/FileMatch/BasicFileMatchTest.php @@ -2,6 +2,7 @@ namespace Gt\Routing\Test\Path\FileMatch; use Gt\Routing\Path\FileMatch\BasicFileMatch; +use Gt\Routing\Path\FileMatch\FileMatch; use PHPUnit\Framework\TestCase; class BasicFileMatchTest extends TestCase { @@ -44,4 +45,36 @@ public function testMatches_shouldMatchIndexNoNesting():void { ); self::assertTrue($sut->matches("/")); } + + public function testMatches_dynamicDir():void { + $sut = new BasicFileMatch( + "page/shop/@category/@item.html", + "page" + ); + self::assertTrue($sut->matches("/shop/cakes/chocolate")); + } + + public function testMatches_dynamicDir_doesNotMatchIndex():void { + $sut = new BasicFileMatch( + "page/shop/@category/@item.html", + "page" + ); + self::assertFalse($sut->matches("/shop/cakes")); + } + + public function testMatches_dynamicDir_doesNotMatchDeeper():void { + $sut = new BasicFileMatch( + "page/shop/@category/@item.html", + "page" + ); + self::assertFalse($sut->matches("/shop/cakes/chocolate/nothing")); + } + + public function testMatches_dynamicDir_matchesIndex():void { + $sut = new BasicFileMatch( + "page/shop/@category/index.html", + "page" + ); + self::assertTrue($sut->matches("/shop/cakes")); + } } diff --git a/test/phpunit/Path/FileMatch/MagicFileMatchTest.php b/test/phpunit/Path/FileMatch/MagicFileMatchTest.php index d342cfc..5872e28 100644 --- a/test/phpunit/Path/FileMatch/MagicFileMatchTest.php +++ b/test/phpunit/Path/FileMatch/MagicFileMatchTest.php @@ -44,4 +44,12 @@ public function testMatches_ancestorDir():void { ); self::assertTrue($sut->matches("/something/very/deeply/nested")); } + + public function testMatches_dynamicDir():void { + $sut = new MagicFileMatch( + "basedir/something/@dynamic/_common.php", + "basedir" + ); + self::assertTrue($sut->matches("/something/this-is-dynamic/test")); + } }