From bf0b18abdef5c85f3ee99a25c4884fdbbfc83686 Mon Sep 17 00:00:00 2001 From: Ollie Read Date: Wed, 6 Nov 2024 23:06:11 +0000 Subject: [PATCH 1/2] feat: Add initial resolution stage support in using resolution hooks --- resources/config/sprout.php | 18 +++++----- src/Exceptions/MisconfigurationException.php | 14 ++++++++ src/Http/Middleware/TenantRoutes.php | 36 +++++++++++++++----- src/Sprout.php | 18 ++++++++++ src/SproutServiceProvider.php | 3 +- src/Support/ResolutionHelper.php | 11 +++++- tests/SproutTest.php | 5 +-- 7 files changed, 85 insertions(+), 20 deletions(-) diff --git a/resources/config/sprout.php b/resources/config/sprout.php index 85da994..e609f12 100644 --- a/resources/config/sprout.php +++ b/resources/config/sprout.php @@ -4,19 +4,21 @@ /* |-------------------------------------------------------------------------- - | Should Sprout listen for routing? + | Enabled hooks |-------------------------------------------------------------------------- | - | This value decides whether Sprout listens for the RouteMatched event to - | identify tenants. - | - | Setting it to false will disable the pre-middleware identification, - | which in turn will make tenant-aware dependency injection no longer - | functionality. + | This value contains an array of resolution hooks that should be enabled. + | The handling of each hook is different, but if a hook is missing from + | here, some things, such as listeners, may not be registered. | */ - 'listen_for_routing' => true, + 'hooks' => [ + // \Sprout\Support\ResolutionHook::Bootstrapping, + // \Sprout\Support\ResolutionHook::Booting, + \Sprout\Support\ResolutionHook::Routing, + \Sprout\Support\ResolutionHook::Middleware, + ], /* |-------------------------------------------------------------------------- diff --git a/src/Exceptions/MisconfigurationException.php b/src/Exceptions/MisconfigurationException.php index 877d2f1..59439a1 100644 --- a/src/Exceptions/MisconfigurationException.php +++ b/src/Exceptions/MisconfigurationException.php @@ -3,6 +3,8 @@ namespace Sprout\Exceptions; +use Sprout\Support\ResolutionHook; + /** * Misconfiguration Exception * @@ -81,4 +83,16 @@ public static function noDefault(string $type): self { return new self('There is no default ' . $type . ' set'); } + + /** + * Create a new exception for when a resolution hook is not supported + * + * @param \Sprout\Support\ResolutionHook $hook + * + * @return self + */ + public static function unsupportedHook(ResolutionHook $hook): self + { + return new self('The resolution hook [' . $hook->name . '] is not supported'); + } } diff --git a/src/Http/Middleware/TenantRoutes.php b/src/Http/Middleware/TenantRoutes.php index a03dc87..f5c847f 100644 --- a/src/Http/Middleware/TenantRoutes.php +++ b/src/Http/Middleware/TenantRoutes.php @@ -6,6 +6,7 @@ use Closure; use Illuminate\Http\Request; use Illuminate\Http\Response; +use Sprout\Sprout; use Sprout\Support\ResolutionHelper; use Sprout\Support\ResolutionHook; @@ -25,6 +26,21 @@ final class TenantRoutes */ public const ALIAS = 'sprout.tenanted'; + /** + * @var \Sprout\Sprout + */ + private Sprout $sprout; + + /** + * Create a new instance of the middleware + * + * @param \Sprout\Sprout $sprout + */ + public function __construct(Sprout $sprout) + { + $this->sprout = $sprout; + } + /** * Handle the request * @@ -35,17 +51,21 @@ final class TenantRoutes * @return \Illuminate\Http\Response * * @throws \Sprout\Exceptions\NoTenantFound + * @throws \Illuminate\Contracts\Container\BindingResolutionException + * @throws \Sprout\Exceptions\MisconfigurationException */ public function handle(Request $request, Closure $next, string ...$options): Response { - [$resolverName, $tenancyName] = ResolutionHelper::parseOptions($options); - - ResolutionHelper::handleResolution( - $request, - ResolutionHook::Middleware, - $resolverName, - $tenancyName, - ); + if ($this->sprout->supportsHook(ResolutionHook::Middleware)) { + [$resolverName, $tenancyName] = ResolutionHelper::parseOptions($options); + + ResolutionHelper::handleResolution( + $request, + ResolutionHook::Middleware, + $resolverName, + $tenancyName, + ); + } return $next($request); } diff --git a/src/Sprout.php b/src/Sprout.php index 41f6a3b..e40d860 100644 --- a/src/Sprout.php +++ b/src/Sprout.php @@ -9,6 +9,7 @@ use Sprout\Managers\IdentityResolverManager; use Sprout\Managers\ProviderManager; use Sprout\Managers\TenancyManager; +use Sprout\Support\ResolutionHook; /** * Sprout @@ -192,4 +193,21 @@ public function getOverrides(): array { return $this->overrides; } + + /** + * Check if a resolution hook is enabled + * + * @param \Sprout\Support\ResolutionHook $hook + * + * @return bool + * + * @throws \Illuminate\Contracts\Container\BindingResolutionException + */ + public function supportsHook(ResolutionHook $hook): bool + { + /** @var array $enabledHooks */ + $enabledHooks = $this->config('hooks', []); + + return in_array($hook, $enabledHooks, true); + } } diff --git a/src/SproutServiceProvider.php b/src/SproutServiceProvider.php index ef00f74..897b2f4 100644 --- a/src/SproutServiceProvider.php +++ b/src/SproutServiceProvider.php @@ -17,6 +17,7 @@ use Sprout\Managers\IdentityResolverManager; use Sprout\Managers\ProviderManager; use Sprout\Managers\TenancyManager; +use Sprout\Support\ResolutionHook; /** * Sprout Service Provider @@ -120,7 +121,7 @@ private function registerEventListeners(): void $events = $this->app->make(Dispatcher::class); // If we should be listening for routing - if ($this->sprout->shouldListenForRouting()) { + if ($this->sprout->supportsHook(ResolutionHook::Routing)) { $events->listen(RouteMatched::class, IdentifyTenantOnRouting::class); } } diff --git a/src/Support/ResolutionHelper.php b/src/Support/ResolutionHelper.php index 4953ff7..d53af3a 100644 --- a/src/Support/ResolutionHelper.php +++ b/src/Support/ResolutionHelper.php @@ -5,6 +5,7 @@ use Illuminate\Http\Request; use Sprout\Contracts\IdentityResolverUsesParameters; +use Sprout\Exceptions\MisconfigurationException; use Sprout\Exceptions\NoTenantFound; use Sprout\Sprout; @@ -38,12 +39,20 @@ public static function parseOptions(array $options): array * * @return bool * + * @throws \Illuminate\Contracts\Container\BindingResolutionException + * @throws \Sprout\Exceptions\MisconfigurationException * @throws \Sprout\Exceptions\NoTenantFound */ public static function handleResolution(Request $request, ResolutionHook $hook, ?string $resolverName = null, ?string $tenancyName = null, bool $throw = true): bool { /** @var \Sprout\Sprout $sprout */ - $sprout = app(Sprout::class); + $sprout = app(Sprout::class); + + // If the resolution hook is disabled, throw an exception + if (! $sprout->supportsHook($hook)) { + throw MisconfigurationException::unsupportedHook($hook); + } + $resolver = $sprout->resolvers()->get($resolverName); $tenancy = $sprout->tenancies()->get($tenancyName); diff --git a/tests/SproutTest.php b/tests/SproutTest.php index c04a53a..ea32025 100644 --- a/tests/SproutTest.php +++ b/tests/SproutTest.php @@ -10,6 +10,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\Test; use Sprout\Sprout; +use Sprout\Support\ResolutionHook; use Workbench\App\Models\TenantModel; #[Group('core')] @@ -49,13 +50,13 @@ public function hasHelperForListeningToRoutingEvents(): void $this->assertFalse($sprout->config('listen_for_routing')); $this->assertFalse(config('sprout.listen_for_routing')); - $this->assertFalse($sprout->shouldListenForRouting()); + $this->assertFalse($sprout->supportsHook(ResolutionHook::Routing)); app()['config']->set('sprout.listen_for_routing', true); $this->assertTrue($sprout->config('listen_for_routing')); $this->assertTrue(config('sprout.listen_for_routing')); - $this->assertTrue($sprout->shouldListenForRouting()); + $this->assertTrue($sprout->supportsHook(ResolutionHook::Routing)); } #[Test] From bad8b1fc675c283dcb01e2daeeb26433a445017d Mon Sep 17 00:00:00 2001 From: Ollie Read Date: Thu, 7 Nov 2024 09:38:29 +0000 Subject: [PATCH 2/2] chore: Tidy up --- src/Listeners/SetCurrentTenantContext.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Listeners/SetCurrentTenantContext.php b/src/Listeners/SetCurrentTenantContext.php index 7ac412c..06d9074 100644 --- a/src/Listeners/SetCurrentTenantContext.php +++ b/src/Listeners/SetCurrentTenantContext.php @@ -5,7 +5,6 @@ use Illuminate\Support\Facades\Context; use Sprout\Events\CurrentTenantChanged; -use Sprout\Sprout; /** * Set Current Tenant Context @@ -28,7 +27,7 @@ final class SetCurrentTenantContext public function handle(CurrentTenantChanged $event): void { $contextKey = 'sprout.tenants'; - $context = []; + $context = []; if (Context::has($contextKey)) { /** @var array $context */