diff --git a/src/Overrides/TenancyUrlGenerator.php b/src/Overrides/TenancyUrlGenerator.php index af307021..274930b8 100644 --- a/src/Overrides/TenancyUrlGenerator.php +++ b/src/Overrides/TenancyUrlGenerator.php @@ -53,7 +53,24 @@ class TenancyUrlGenerator extends UrlGenerator { [$name, $parameters] = $this->prepareRouteInputs($name, Arr::wrap($parameters)); - return parent::route($name, $parameters, $absolute); + $url = parent::route($name, $parameters, $absolute); + + if (isset($parameters[PathTenantResolver::tenantParameterName()])) { + // Ensure the tenant key is present in the URL just once + // This is necessary when using UrlGeneratorBootstrapper with RootUrlBootstrapper + $tenantId = $parameters[PathTenantResolver::tenantParameterName()]; + $afterTenant = str($url)->afterLast($tenantId)->toString(); + $beforeTenant = str($url)->before($tenantId)->toString(); + + if (! $absolute && str(url('/'))->contains($tenantId)) { + // If the URL should be relative and the tenant key is already present in the full URL, don't add it again + return $afterTenant; + } + + return $beforeTenant . $tenantId . $afterTenant; + } + + return $url; } /** diff --git a/tests/Bootstrappers/RootUrlBootstrapperTest.php b/tests/Bootstrappers/RootUrlBootstrapperTest.php index ee17a802..91ab608d 100644 --- a/tests/Bootstrappers/RootUrlBootstrapperTest.php +++ b/tests/Bootstrappers/RootUrlBootstrapperTest.php @@ -10,18 +10,23 @@ use Stancl\Tenancy\Listeners\BootstrapTenancy; use Stancl\Tenancy\Listeners\RevertToCentralContext; use Stancl\Tenancy\Bootstrappers\RootUrlBootstrapper; use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain; +use Stancl\Tenancy\Bootstrappers\UrlGeneratorBootstrapper; +use Stancl\Tenancy\Middleware\InitializeTenancyByPath; +use Stancl\Tenancy\Overrides\TenancyUrlGenerator; beforeEach(function () { Event::listen(TenancyInitialized::class, BootstrapTenancy::class); Event::listen(TenancyEnded::class, RevertToCentralContext::class); RootUrlBootstrapper::$rootUrlOverride = null; + RootUrlBootstrapper::$rootUrlOverrideInTests = true; }); afterEach(function () { RootUrlBootstrapper::$rootUrlOverride = null; + RootUrlBootstrapper::$rootUrlOverrideInTests = false; }); -test('root url bootstrapper overrides the root url when tenancy gets initialized and reverts the url to the central one after tenancy ends', function() { +test('root url bootstrapper overrides the root url when tenancy gets initialized and reverts the url to the central one when ending tenancy', function() { config(['tenancy.bootstrappers' => [RootUrlBootstrapper::class]]); Route::group([ @@ -65,3 +70,34 @@ test('root url bootstrapper overrides the root url when tenancy gets initialized expect(URL::to('/'))->toBe($baseUrl); expect(config('app.url'))->toBe($baseUrl); }); + +test('root url bootstrapper can be used with url generator bootstrapper', function() { + config(['tenancy.bootstrappers' => [RootUrlBootstrapper::class, UrlGeneratorBootstrapper::class]]); + + TenancyUrlGenerator::$prefixRouteNames = true; + TenancyUrlGenerator::$passTenantParameterToRoutes = true; + + Route::get('/', function () { + return true; + })->name('home'); + + Route::get('/{tenant}', function () { + return true; + })->name('tenant.home')->middleware(InitializeTenancyByPath::class); + + $rootUrlOverride = function (Tenant $tenant, string $originalRootUrl) { + return str($originalRootUrl)->beforeLast($tenant->getTenantKey())->toString() . '/' . $tenant->getTenantKey(); + }; + + $tenant = Tenant::create(); + + $tenantUrl = $rootUrlOverride($tenant, url('/')); + + RootUrlBootstrapper::$rootUrlOverride = $rootUrlOverride; + + expect(route('home'))->toBe(url('/')); + + tenancy()->initialize($tenant); + + expect(route('home'))->toBe($tenantUrl); +});