diff --git a/framework/core/src/Http/RouteCollection.php b/framework/core/src/Http/RouteCollection.php index 78c6998e2..6b19b9df9 100644 --- a/framework/core/src/Http/RouteCollection.php +++ b/framework/core/src/Http/RouteCollection.php @@ -121,11 +121,17 @@ class RouteCollection return $this->dataGenerator->getData(); } - protected function fixPathPart(&$part, $key, array $parameters) + protected function fixPathPart($part, array $parameters, string $routeName) { - if (is_array($part) && array_key_exists($part[0], $parameters)) { - $part = $parameters[$part[0]]; + if (! is_array($part)) { + return $part; } + + if (! array_key_exists($part[0], $parameters)) { + throw new \InvalidArgumentException("Could not generate URL for route '$routeName': no value provided for required part '$part[0]'."); + } + + return $parameters[$part[0]]; } public function getPath($name, array $parameters = []) @@ -151,9 +157,11 @@ class RouteCollection } } - array_walk($matchingParts, [$this, 'fixPathPart'], $parameters); + $fixedParts = array_map(function ($part) use ($parameters, $name) { + return $this->fixPathPart($part, $parameters, $name); + }, $matchingParts); - return '/'.ltrim(implode('', $matchingParts), '/'); + return '/'.ltrim(implode('', $fixedParts), '/'); } throw new \RuntimeException("Route $name not found"); diff --git a/framework/core/tests/unit/Http/RouteCollectionTest.php b/framework/core/tests/unit/Http/RouteCollectionTest.php index 968ed9340..00db58d5f 100644 --- a/framework/core/tests/unit/Http/RouteCollectionTest.php +++ b/framework/core/tests/unit/Http/RouteCollectionTest.php @@ -44,4 +44,41 @@ class RouteCollectionTest extends TestCase $this->assertEquals('/posts', $routeCollection->getPath('forum.posts.delete')); } + + /** @test */ + public function must_provide_required_parameters() + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage("Could not generate URL for route 'user': no value provided for required part 'user'."); + + $routeCollection = (new RouteCollection)->addRoute('GET', '/user/{user}', 'user', function () { + echo 'user'; + }); + + $routeCollection->getPath('user', []); + } + + /** @test */ + public function dont_need_to_provide_optional_parameters() + { + $routeCollection = (new RouteCollection)->addRoute('GET', '/user/{user}[/{test}]', 'user', function () { + echo 'user'; + }); + + $path = $routeCollection->getPath('user', ['user' => 'SomeUser']); + + $this->assertEquals('/user/SomeUser', $path); + } + + /** @test */ + public function can_provide_optional_parameters() + { + $routeCollection = (new RouteCollection)->addRoute('GET', '/user/{user}[/{test}]', 'user', function () { + echo 'user'; + }); + + $path = $routeCollection->getPath('user', ['user' => 'SomeUser', 'test' => 'Flarum']); + + $this->assertEquals('/user/SomeUser/Flarum', $path); + } }