diff --git a/assets/config.php b/assets/config.php index 5e231f2a..ba503aad 100644 --- a/assets/config.php +++ b/assets/config.php @@ -93,11 +93,14 @@ return [ * Identification middleware tenancy recognizes as path identification middleware. * * This is used for determining if a path identification middleware is used - * during operations specific to path identification, e.g. forgetting the tenant parameter in ForgetTenantParameter. + * during operations specific to path identification. + * + * This is used for forgetting the tenant parameter using the ForgetTenantParameter listener. + * The listener only has an effect when path identification middleware + * is used in the global middleware stack and certain other conditions are met. * * If you're using a custom path identification middleware, add it here. * - * @see \Stancl\Tenancy\Actions\CloneRoutesAsTenant * @see \Stancl\Tenancy\Listeners\ForgetTenantParameter */ 'path_identification_middleware' => [ diff --git a/src/Listeners/ForgetTenantParameter.php b/src/Listeners/ForgetTenantParameter.php index 0b1d1440..d159b967 100644 --- a/src/Listeners/ForgetTenantParameter.php +++ b/src/Listeners/ForgetTenantParameter.php @@ -11,18 +11,18 @@ use Stancl\Tenancy\Resolvers\PathTenantResolver; // todo@earlyIdReview /** - * Remove the tenant parameter from the matched route when path identification is used globally. + * Conditionally removes the tenant parameter from matched routes when using kernel path identification. * - * While initializing tenancy, we forget the tenant parameter (in PathTenantResolver), - * so that the route actions don't have to accept it. + * When path identification middleware is in the global stack, + * the tenant parameter is initially forgotten during tenancy initialization in PathTenantResolver. + * However, because kernel identification occurs before route matching, the route still contains + * the tenant parameter when RouteMatched is fired. This listener removes it to prevent route + * actions from needing to accept an unwanted tenant parameter. * - * With kernel identification, tenancy gets initialized before the route gets matched. - * The matched route gets the tenant parameter again, so we have to forget the parameter again on RouteMatched. - * - * We remove the {tenant} parameter from the matched route when - * 1) the InitializeTenancyByPath middleware is in the global stack, AND - * 2) the matched route does not have identification middleware (so that {tenant} isn't forgotten when using route-level identification), AND - * 3) the route isn't in the central context (so that {tenant} doesn't get accidentally removed from central routes). + * The {tenant} parameter is removed from the matched route only when ALL of these conditions are met: + * 1) A path identification middleware is in the global middleware stack (kernel identification) + * 2) The matched route does NOT have its own identification middleware (route-level identification takes precedence) + * 3) The route is in tenant or universal context (central routes keep their tenant parameter) */ class ForgetTenantParameter { diff --git a/src/TenancyServiceProvider.php b/src/TenancyServiceProvider.php index 4059479e..22a81624 100644 --- a/src/TenancyServiceProvider.php +++ b/src/TenancyServiceProvider.php @@ -20,6 +20,8 @@ use Stancl\Tenancy\Resolvers\DomainTenantResolver; class TenancyServiceProvider extends ServiceProvider { public static Closure|null $configure = null; + public static bool $registerForgetTenantParameterListener = true; + public static bool $migrateFreshOverride = true; /* Register services. */ public function register(): void @@ -104,9 +106,11 @@ class TenancyServiceProvider extends ServiceProvider Commands\CreateUserWithRLSPolicies::class, ]); - $this->app->extend(FreshCommand::class, function ($_, $app) { - return new Commands\MigrateFreshOverride($app['migrator']); - }); + if (static::$migrateFreshOverride) { + $this->app->extend(FreshCommand::class, function ($_, $app) { + return new Commands\MigrateFreshOverride($app['migrator']); + }); + } $this->publishes([ __DIR__ . '/../assets/config.php' => config_path('tenancy.php'), @@ -152,6 +156,14 @@ class TenancyServiceProvider extends ServiceProvider Route::middlewareGroup('tenant', []); Route::middlewareGroup('central', []); - Event::listen(RouteMatched::class, ForgetTenantParameter::class); + if (static::$registerForgetTenantParameterListener) { + // Ideally, this listener would only be registered when kernel-level + // path identification is used, however doing that check reliably + // at this point in the lifecycle isn't feasible. For that reason, + // rather than doing an "outer" check, we do an "inner" check within + // that listener. That also means the listener needs to be registered + // always. We allow for this to be controlled using a static property. + Event::listen(RouteMatched::class, ForgetTenantParameter::class); + } } }