Skip to content

Commit

Permalink
Add optional default host and scheme to UrlGenerator (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
vjik committed Mar 19, 2024
1 parent 77da24c commit 27787bb
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 41 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,7 @@

## 3.0.2 under development

- New #144: Add optional default host and scheme to `UrlGenerator` (@vjik)
- Enh #139: Add support for `psr/http-message` version `^2.0` (@vjik)

## 3.0.1 December 24, 2023
Expand Down
30 changes: 21 additions & 9 deletions src/UrlGenerator.php
Expand Up @@ -34,7 +34,9 @@ final class UrlGenerator implements UrlGeneratorInterface
public function __construct(
private RouteCollectionInterface $routeCollection,
private ?CurrentRoute $currentRoute = null,
RouteParser $parser = null
?RouteParser $parser = null,
private ?string $scheme = null,
private ?string $host = null,
) {
$this->routeParser = $parser ?? new RouteParser\Std();
}
Expand Down Expand Up @@ -88,24 +90,31 @@ public function generateAbsolute(
string $name,
array $arguments = [],
array $queryParameters = [],
string $scheme = null,
string $host = null
?string $scheme = null,
?string $host = null
): string {
$url = $this->generate($name, $arguments, $queryParameters);
$route = $this->routeCollection->getRoute($name);
$uri = $this->currentRoute && $this->currentRoute->getUri() !== null ? $this->currentRoute->getUri() : null;
$lastRequestScheme = $uri?->getScheme();

if ($host !== null || ($host = $route->getData('host')) !== null) {
if ($scheme === null && !$this->isRelative($host)) {
$host ??= $route->getData('host') ?? $this->host ?? null;
if ($host !== null) {
$isRelativeHost = $this->isRelative($host);

$scheme ??= $isRelativeHost
? $this->scheme ?? $lastRequestScheme
: null;

if ($scheme === null && !$isRelativeHost) {
return rtrim($host, '/') . $url;
}

if ((empty($scheme) || $lastRequestScheme === null) && $host !== '' && $this->isRelative($host)) {
if ($host !== '' && $isRelativeHost) {
$host = '//' . $host;
}

return $this->ensureScheme(rtrim($host, '/') . $url, $scheme ?? $lastRequestScheme);
return $this->ensureScheme(rtrim($host, '/') . $url, $scheme);

Check warning on line 117 in src/UrlGenerator.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "UnwrapRtrim": --- Original +++ New @@ @@ if ($host !== '' && $isRelativeHost) { $host = '//' . $host; } - return $this->ensureScheme(rtrim($host, '/') . $url, $scheme); + return $this->ensureScheme($host . $url, $scheme); } return $uri === null ? $url : $this->generateAbsoluteFromLastMatchedRequest($url, $uri, $scheme); }
}

return $uri === null ? $url : $this->generateAbsoluteFromLastMatchedRequest($url, $uri, $scheme);
Expand All @@ -114,8 +123,11 @@ public function generateAbsolute(
/**
* {@inheritdoc}
*/
public function generateFromCurrent(array $replacedArguments, array $queryParameters = [], string $fallbackRouteName = null): string
{
public function generateFromCurrent(
array $replacedArguments,
array $queryParameters = [],
?string $fallbackRouteName = null,
): string {
if ($this->currentRoute === null || $this->currentRoute->getName() === null) {
if ($fallbackRouteName !== null) {
return $this->generate($fallbackRouteName, $replacedArguments);
Expand Down
125 changes: 93 additions & 32 deletions tests/UrlGeneratorTest.php
Expand Up @@ -187,7 +187,7 @@ public function testQueryParametersAddedAsQueryString(): void
{
$routes = [
Route::get('/test/{name}')
->name('test'),
->name('test'),
];

$url = $this
Expand All @@ -200,7 +200,7 @@ public function testQueryParametersAddedAsQueryStringWithEmptyValues(): void
{
$routes = [
Route::get('/test/{name}')
->name('test'),
->name('test'),
];

$url = $this
Expand All @@ -213,7 +213,7 @@ public function testQueryParametersOverrideExtraArguments(): void
{
$routes = [
Route::get('/test/{name}')
->name('test'),
->name('test'),
];

$url = $this
Expand All @@ -226,7 +226,7 @@ public function testNotSubstitutedArgumentsRemove(): void
{
$routes = [
Route::get('/test/{name}')
->name('test'),
->name('test'),
];

$url = $this
Expand All @@ -239,8 +239,8 @@ public function testDefaultNotUsedForOptionalArgument(): void
{
$routes = [
Route::get('/[{name}]')
->name('defaults')
->defaults(['name' => 'default']),
->name('defaults')
->defaults(['name' => 'default']),
];

$url = $this
Expand All @@ -253,8 +253,8 @@ public function testValueUsedForOptionalArgument(): void
{
$routes = [
Route::get('/[{name}]')
->name('defaults')
->defaults(['name' => 'default']),
->name('defaults')
->defaults(['name' => 'default']),
];

$url = $this
Expand All @@ -267,8 +267,8 @@ public function testDefaultNotUsedForRequiredParameter(): void
{
$routes = [
Route::get('/{name}')
->name('defaults')
->defaults(['name' => 'default']),
->name('defaults')
->defaults(['name' => 'default']),
];

$this->expectExceptionMessage('Route `defaults` expects at least argument values for [name], but received []');
Expand All @@ -284,8 +284,8 @@ public function testAbsoluteUrlHostOverride(): void
{
$routes = [
Route::get('/home/index')
->name('index')
->host('http://test.com'),
->name('index')
->host('http://test.com'),
];
$url = $this
->createUrlGenerator($routes)
Expand All @@ -301,8 +301,8 @@ public function testAbsoluteUrlHostOverrideWithTrailingSlash(): void
{
$routes = [
Route::get('/home/index')
->name('index')
->host('http://test.com'),
->name('index')
->host('http://test.com'),
];
$url = $this
->createUrlGenerator($routes)
Expand All @@ -318,8 +318,8 @@ public function testAbsoluteUrlSchemeOverrideHostInRouteScheme(): void
{
$routes = [
Route::get('/home/index')
->name('index')
->host('http://test.com'),
->name('index')
->host('http://test.com'),
];
$url = $this
->createUrlGenerator($routes)
Expand Down Expand Up @@ -368,8 +368,8 @@ public function testAbsoluteUrlWithHostInRoute(): void
{
$routes = [
Route::get('/home/index')
->name('index')
->host('http://test.com'),
->name('index')
->host('http://test.com'),
];
$url = $this
->createUrlGenerator($routes)
Expand All @@ -385,8 +385,8 @@ public function testAbsoluteUrlWithTrailingSlashHostInRoute(): void
{
$routes = [
Route::get('/home/index')
->name('index')
->host('http://test.com/'),
->name('index')
->host('http://test.com/'),
];
$url = $this
->createUrlGenerator($routes)
Expand Down Expand Up @@ -443,8 +443,8 @@ public function testHostInRouteWithProtocolRelativeSchemeAbsoluteUrl(): void
$request = new ServerRequest('GET', 'http://test.com/home/index');
$routes = [
Route::get('/home/index')
->name('index')
->host('//test.com'),
->name('index')
->host('//test.com'),
];

$currentRoute = new CurrentRoute();
Expand All @@ -465,8 +465,8 @@ public function testHostInMethodWithProtocolRelativeSchemeAbsoluteUrl(): void
$request = new ServerRequest('GET', 'http://test.com/home/index');
$routes = [
Route::get('/home/index')
->name('index')
->host('//mysite.com'),
->name('index')
->host('//mysite.com'),
];

$currentRoute = new CurrentRoute();
Expand All @@ -483,11 +483,11 @@ public function testHostInRouteProtocolRelativeSchemeAbsoluteUrl(): void
$request = new ServerRequest('GET', 'http://test.com/home/index');
$routes = [
Route::get('/home/index')
->name('index')
->host('http://test.com'),
->name('index')
->host('http://test.com'),
Route::get('/home/view')
->name('view')
->host('test.com'),
->name('view')
->host('test.com'),
];

$currentRoute = new CurrentRoute();
Expand All @@ -508,8 +508,8 @@ public function testHostInMethodProtocolRelativeSchemeAbsoluteUrl(): void
$request = new ServerRequest('GET', 'http://test.com/home/index');
$routes = [
Route::get('/home/index')
->name('index')
->host('//mysite.com'),
->name('index')
->host('//mysite.com'),
];

$currentRoute = new CurrentRoute();
Expand Down Expand Up @@ -560,8 +560,8 @@ public function testHostInRouteWithoutSchemeAbsoluteUrl(): void
$request = new ServerRequest('GET', 'http://example.com/home/index');
$routes = [
Route::get('/home/index')
->name('index')
->host('example.com'),
->name('index')
->host('example.com'),
];

$currentRoute = new CurrentRoute();
Expand Down Expand Up @@ -853,6 +853,67 @@ public function testNotFoundRoutes(): void
$urlGenerator->generate('index');
}

public function testDefaultHostAndScheme(): void
{
$urlGenerator = new UrlGenerator(
$this->createRouteCollection([Route::get('/home/index')->name('index')]),
scheme: 'https',
host: 'example.com',
);

$url = $urlGenerator->generateAbsolute('index');

$this->assertSame('https://example.com/home/index', $url);
}

public function testOverrideDefaultHostAndSchemeFromMethodArguments(): void
{
$urlGenerator = new UrlGenerator(
$this->createRouteCollection([Route::get('/home/index')->name('index')]),
scheme: 'https',
host: 'example.com',
);

$url = $urlGenerator->generateAbsolute('index', scheme: 'http', host: 'example.yii');

$this->assertSame('http://example.yii/home/index', $url);
}

public function testOverrideDefaultHostAndSchemeFromRoute(): void
{
$urlGenerator = new UrlGenerator(
$this->createRouteCollection([
Route::get('/home/index')
->host('//test.yii')
->name('index'),
]),
scheme: 'https',
host: 'example.com',
);

$url = $urlGenerator->generateAbsolute('index');

$this->assertSame('//test.yii/home/index', $url);
}

public function testDefaultHostAndSchemeWithUri(): void
{
$request = new ServerRequest('GET', 'http://test.com/home/index');
$currentRoute = new CurrentRoute();
$currentRoute->setUri($request->getUri());

$urlGenerator = new UrlGenerator(
$this->createRouteCollection([Route::get('/home/index')->name('index')]),
$currentRoute,
scheme: 'https',
host: 'example.com',
);

$url = $urlGenerator->generateAbsolute('index');

$this->assertSame('https://example.com/home/index', $url);
}

private function createUrlGenerator(
array $routes,
CurrentRoute $currentRoute = null,
Expand Down

0 comments on commit 27787bb

Please sign in to comment.