From 83529316c319fb6310ae1b021977310cbb69f2a8 Mon Sep 17 00:00:00 2001 From: lukinovec Date: Mon, 10 Feb 2025 09:27:33 +0100 Subject: [PATCH] Pass tenant parameter using defaults in UrlGeneratorBootstrapper, update tests accordingly (wip) --- .../UrlGeneratorBootstrapper.php | 12 ++++++-- src/Overrides/TenancyUrlGenerator.php | 5 ++-- .../UrlGeneratorBootstrapperTest.php | 30 +++++++++++-------- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/Bootstrappers/UrlGeneratorBootstrapper.php b/src/Bootstrappers/UrlGeneratorBootstrapper.php index 15116760..cc3db2be 100644 --- a/src/Bootstrappers/UrlGeneratorBootstrapper.php +++ b/src/Bootstrappers/UrlGeneratorBootstrapper.php @@ -10,6 +10,7 @@ use Illuminate\Support\Facades\URL; use Stancl\Tenancy\Contracts\TenancyBootstrapper; use Stancl\Tenancy\Contracts\Tenant; use Stancl\Tenancy\Overrides\TenancyUrlGenerator; +use Stancl\Tenancy\Resolvers\PathTenantResolver; /** * Makes the app use TenancyUrlGenerator (instead of Illuminate\Routing\UrlGenerator) which: @@ -32,7 +33,7 @@ class UrlGeneratorBootstrapper implements TenancyBootstrapper { URL::clearResolvedInstances(); - $this->useTenancyUrlGenerator(); + $this->useTenancyUrlGenerator($tenant); } public function revert(): void @@ -45,7 +46,7 @@ class UrlGeneratorBootstrapper implements TenancyBootstrapper * * @see \Illuminate\Routing\RoutingServiceProvider registerUrlGenerator() */ - protected function useTenancyUrlGenerator(): void + protected function useTenancyUrlGenerator(Tenant $tenant): void { $newGenerator = new TenancyUrlGenerator( $this->app['router']->getRoutes(), @@ -53,7 +54,12 @@ class UrlGeneratorBootstrapper implements TenancyBootstrapper $this->app['config']->get('app.asset_url'), ); - $newGenerator->defaults($this->originalUrlGenerator->getDefaultParameters()); + $defaultParameters = array_merge( + $this->originalUrlGenerator->getDefaultParameters(), + [PathTenantResolver::tenantParameterName() => $tenant->getTenantKey()] + ); + + $newGenerator->defaults($defaultParameters); $newGenerator->setSessionResolver(function () { return $this->app['session'] ?? null; diff --git a/src/Overrides/TenancyUrlGenerator.php b/src/Overrides/TenancyUrlGenerator.php index 7c0a7879..f99478b4 100644 --- a/src/Overrides/TenancyUrlGenerator.php +++ b/src/Overrides/TenancyUrlGenerator.php @@ -41,11 +41,10 @@ class TenancyUrlGenerator extends UrlGenerator /** * Determine if the tenant parameter should get passed * to the links generated by `route()` or `temporarySignedRoute()` whenever available - * (enabled by default – works with both path and query string identification). * - * With path identification, you can disable this and use URL::defaults() instead (as an alternative solution). + * With path identification, you can keep this disabled since the parameter is passed automatically by URL::defaults() in the UrlGeneratorBootstrapper */ - public static bool $passTenantParameterToRoutes = true; + public static bool $passTenantParameterToRoutes = false; /** * Override the route() method so that the route name gets prefixed diff --git a/tests/Bootstrappers/UrlGeneratorBootstrapperTest.php b/tests/Bootstrappers/UrlGeneratorBootstrapperTest.php index 8ef3169d..be501760 100644 --- a/tests/Bootstrappers/UrlGeneratorBootstrapperTest.php +++ b/tests/Bootstrappers/UrlGeneratorBootstrapperTest.php @@ -19,12 +19,12 @@ beforeEach(function () { Event::listen(TenancyInitialized::class, BootstrapTenancy::class); Event::listen(TenancyEnded::class, RevertToCentralContext::class); TenancyUrlGenerator::$prefixRouteNames = false; - TenancyUrlGenerator::$passTenantParameterToRoutes = true; + TenancyUrlGenerator::$passTenantParameterToRoutes = false; }); afterEach(function () { TenancyUrlGenerator::$prefixRouteNames = false; - TenancyUrlGenerator::$passTenantParameterToRoutes = true; + TenancyUrlGenerator::$passTenantParameterToRoutes = false; }); test('url generator bootstrapper swaps the url generator instance correctly', function() { @@ -41,7 +41,7 @@ test('url generator bootstrapper swaps the url generator instance correctly', fu ->not()->toBeInstanceOf(TenancyUrlGenerator::class); }); -test('url generator bootstrapper can prefix route names passed to the route helper', function() { +test('url generator bootstrapper can prefix route names passed to the route helper and automatically pass tenant query parameter to it', function() { Route::get('/central/home', fn () => route('home'))->name('home'); // Tenant route name prefix is 'tenant.' by default Route::get('/{tenant}/home', fn () => route('tenant.home'))->name('tenant.home')->middleware(['tenant', InitializeTenancyByPath::class]); @@ -57,16 +57,18 @@ test('url generator bootstrapper can prefix route names passed to the route help tenancy()->initialize($tenant); // Route names don't get prefixed when TenancyUrlGenerator::$prefixRouteNames is false - expect(route('home'))->not()->toBe($centralRouteUrl); - // When TenancyUrlGenerator::$passTenantParameterToRoutes is true (default) + expect(route('home'))->toBe($centralRouteUrl); + + TenancyUrlGenerator::$passTenantParameterToRoutes = true; + // When TenancyUrlGenerator::$passTenantParameter is true // The route helper receives the tenant parameter // So in order to generate central URL, we have to pass the bypass parameter expect(route('home', ['bypassParameter' => true]))->toBe($centralRouteUrl); - TenancyUrlGenerator::$prefixRouteNames = true; + TenancyUrlGenerator::$passTenantParameterToRoutes = false; // No need to have this enabled with path identification // The $prefixRouteNames property is true - // The route name passed to the route() helper ('home') gets prefixed prefixed with 'tenant.' automatically + // The route name passed to the route() helper ('home') gets prefixed with 'tenant.' automatically expect(route('home'))->toBe($tenantRouteUrl); // The 'tenant.home' route name doesn't get prefixed because it is already prefixed with 'tenant.' @@ -121,25 +123,27 @@ test('url generator bootstrapper can make route helper generate links with the t $pathCentralUrl = route('path'); $pathTenantUrl = route('tenant.path', ['tenant' => $tenantKey]); - // Makes the route helper receive the tenant parameter whenever available - // Unless the bypass parameter is true - TenancyUrlGenerator::$passTenantParameterToRoutes = true; - TenancyUrlGenerator::$bypassParameter = 'bypassParameter'; config(['tenancy.bootstrappers' => [UrlGeneratorBootstrapper::class]]); expect(route('path'))->toBe($pathCentralUrl); - // Tenant parameter required, but not passed since tenancy wasn't initialized expect(fn () => route('tenant.path'))->toThrow(UrlGenerationException::class); tenancy()->initialize($tenant); - // Tenant parameter is passed automatically + // Tenant parameter is passed automatically using defaults (with path identification) + // To add the parameter as a query string, TenancyUrlGenerator::$passTenantParameterToRoutes has to be set to true + TenancyUrlGenerator::$passTenantParameterToRoutes = true; expect(route('path'))->not()->toBe($pathCentralUrl); // Parameter added as query string – bypassParameter needed expect(route('path', ['bypassParameter' => true]))->toBe($pathCentralUrl); + + // Testing path identification here, we can make $passTenantParameterToRoutes false + TenancyUrlGenerator::$passTenantParameterToRoutes = false; expect(route('tenant.path'))->toBe($pathTenantUrl); + // Query string identification, make $passTenantParameterToRoutes true to add the query parameter to the URL automatically + TenancyUrlGenerator::$passTenantParameterToRoutes = true; expect(route('query_string'))->toBe($queryStringTenantUrl)->toContain('tenant='); expect(route('query_string', ['bypassParameter' => 'true']))->toBe($queryStringCentralUrl)->not()->toContain('tenant=');