From b388a2676590347925247f71778ad13e59dc9508 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Sat, 13 Jan 2024 10:17:38 -0700 Subject: [PATCH] fixed alias issue, levenshtein recommendations and coverage-check --- .gitignore | 3 ++- composer.json | 5 +++-- flight/net/Router.php | 32 +++++++++++++++++++++++++------- tests/RouterTest.php | 9 ++++++++- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 6014b459..d3386f10 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ composer.lock coverage/ .vscode/settings.json *.sublime-workspace -.vscode/ \ No newline at end of file +.vscode/ +clover.xml \ No newline at end of file diff --git a/composer.json b/composer.json index 767db450..41543c37 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,8 @@ "ext-pdo_sqlite": "*", "phpunit/phpunit": "^9.5", "phpstan/phpstan": "^1.10", - "phpstan/extension-installer": "^1.3" + "phpstan/extension-installer": "^1.3", + "rregeer/phpunit-coverage-check": "^0.3.1" }, "config": { "allow-plugins": { @@ -45,7 +46,7 @@ }, "scripts": { "test": "phpunit", - "test-coverage": "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html=coverage", + "test-coverage": "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html=coverage --coverage-clover=clover.xml && vendor/bin/coverage-check clover.xml 100", "lint": "phpstan --no-progress -cphpstan.neon" }, "suggest": { diff --git a/flight/net/Router.php b/flight/net/Router.php index f8256165..542e7f7b 100644 --- a/flight/net/Router.php +++ b/flight/net/Router.php @@ -190,14 +190,32 @@ public function route(Request $request) * @return string */ public function getUrlByAlias(string $alias, array $params = []): string { - while ($route = $this->current()) { - if ($route->matchAlias($alias)) { - return $route->hydrateUrl($params); - } - $this->next(); - } + $potential_aliases = []; + foreach($this->routes as $route) { + $potential_aliases[] = $route->alias; + if ($route->matchAlias($alias)) { + return $route->hydrateUrl($params); + } + + } + + // use a levenshtein to find the closest match and make a recommendation + $closest_match = ''; + $closest_match_distance = 0; + foreach($potential_aliases as $potential_alias) { + $levenshtein_distance = levenshtein($alias, $potential_alias); + if($levenshtein_distance > $closest_match_distance) { + $closest_match = $potential_alias; + $closest_match_distance = $levenshtein_distance; + } + } + + $exception_message = 'No route found with alias: \'' . $alias . '\'.'; + if($closest_match !== '') { + $exception_message .= ' Did you mean \'' . $closest_match . '\'?'; + } - throw new Exception('No route found with alias: ' . $alias); + throw new Exception($exception_message); } /** diff --git a/tests/RouterTest.php b/tests/RouterTest.php index 6125f53d..52d8acac 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -468,6 +468,13 @@ public function testGroupNestedRoutesWithCustomMethods() $this->request->method = 'POST'; $this->check('123abc'); } + + public function testGetUrlByAliasBadReferenceButCatchRecommendation() { + $this->router->map('/path1', [$this, 'ok'], false, 'path1'); + $this->expectException(\Exception::class); + $this->expectExceptionMessage('No route found with alias: \'path2\'. Did you mean \'path1\'?'); + $this->router->getUrlByAlias('path2'); + } public function testRewindAndValid() { $this->router->map('/path1', [$this, 'ok']); @@ -491,7 +498,7 @@ public function testRewindAndValid() { public function testGetUrlByAliasNoMatches() { $this->router->map('/path1', [$this, 'ok'], false, 'path1'); $this->expectException(\Exception::class); - $this->expectExceptionMessage('No route found with alias: path2'); + $this->expectExceptionMessage('No route found with alias: \'path2\''); $this->router->getUrlByAlias('path2'); }