diff --git a/lib/UrlGenerator.php b/lib/UrlGenerator.php index 04989cc..03a3361 100644 --- a/lib/UrlGenerator.php +++ b/lib/UrlGenerator.php @@ -11,33 +11,19 @@ namespace ICanBoogie\Routing; -use ICanBoogie\Routing\Exception\RouteNotFound; -use ICanBoogie\Routing\RouteProvider\ByIdOrAction; - -use function is_string; - -class UrlGenerator +interface UrlGenerator { - public function __construct( - private readonly RouteProvider $routes - ) { - } - /** * @phpstan-param string|(callable(Route): bool) $predicate_or_id_or_action * - * @param array|object|null $params + * @param array|object|null $path_params * Parameters that reference placeholders in the route pattern. + * @param array|object|null $query_params + * Parameters for the query string. */ - public function generate_url(string|callable $predicate_or_id_or_action, array|object|null $params = null): string - { - $predicate = is_string($predicate_or_id_or_action) - ? new ByIdOrAction($predicate_or_id_or_action) - : $predicate_or_id_or_action; - - $route = $this->routes->route_for_predicate($predicate) - ?? throw new RouteNotFound(predicate: $predicate); - - return $route->pattern->format($params); - } + public function generate_url( + string|callable $predicate_or_id_or_action, + array|object|null $path_params = null, + array|object $query_params = null, + ): string; } diff --git a/lib/UrlGenerator/UrlGeneratorWithRouteProvider.php b/lib/UrlGenerator/UrlGeneratorWithRouteProvider.php new file mode 100644 index 0000000..f99568d --- /dev/null +++ b/lib/UrlGenerator/UrlGeneratorWithRouteProvider.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ICanBoogie\Routing\UrlGenerator; + +use ICanBoogie\Routing\Exception\RouteNotFound; +use ICanBoogie\Routing\RouteProvider; +use ICanBoogie\Routing\RouteProvider\ByIdOrAction; + +use ICanBoogie\Routing\UrlGenerator; + +use function http_build_query; +use function is_string; + +class UrlGeneratorWithRouteProvider implements UrlGenerator +{ + public function __construct( + private readonly RouteProvider $routes + ) { + } + + public function generate_url( + string|callable $predicate_or_id_or_action, + array|object|null $path_params = null, + array|object|null $query_params = null, + ): string { + $predicate = is_string($predicate_or_id_or_action) + ? new ByIdOrAction($predicate_or_id_or_action) + : $predicate_or_id_or_action; + + $route = $this->routes->route_for_predicate($predicate) + ?? throw new RouteNotFound(predicate: $predicate); + + $url = $route->pattern->format($path_params); + + if ($query_params) { + $url .= '?' . http_build_query($query_params); + } + + return $url; + } +} diff --git a/tests/UrlGeneratorTest.php b/tests/UrlGenerator/UrlGeneratorTest.php similarity index 61% rename from tests/UrlGeneratorTest.php rename to tests/UrlGenerator/UrlGeneratorTest.php index bb0d9b4..dfce389 100644 --- a/tests/UrlGeneratorTest.php +++ b/tests/UrlGenerator/UrlGeneratorTest.php @@ -9,10 +9,10 @@ * file that was distributed with this source code. */ -namespace Test\ICanBoogie\Routing; +namespace Test\ICanBoogie\Routing\UrlGenerator; use ICanBoogie\Routing\RouteCollection; -use ICanBoogie\Routing\UrlGenerator; +use ICanBoogie\Routing\UrlGenerator\UrlGeneratorWithRouteProvider; use PHPUnit\Framework\TestCase; final class UrlGeneratorTest extends TestCase @@ -22,9 +22,12 @@ public function test_generate_url(): void $routes = new RouteCollection(); $routes->resource('articles'); - $generator = new UrlGenerator($routes); - $url = $generator->generate_url('articles:show', [ 'id' => 123 ]); + $generator = new UrlGeneratorWithRouteProvider($routes); + $url = $generator->generate_url('articles:show', [ 'id' => 123, 'title' => 'madonna' ]); $this->assertEquals("/articles/123", $url); + + $url = $generator->generate_url('articles:list', query_params: [ 'page' => 1, 'order' => '-date' ]); + $this->assertEquals("/articles?page=1&order=-date", $url); } }