hasMiddleware('universal'); $defaultRouteModeIsUniversal = config('tenancy.default_route_mode') === RouteMode::UNIVERSAL; return $routeFlaggedAsUniversal || $universalFlagUsedInGlobalStack || $defaultRouteModeIsUniversal; } /** * Get middleware of the passed route (without controller middleware and middleware from the global stack). * * First, get the surface-level route middleware (`$route->middleware()`). * The surface-level middleware could contain middleware groups, * and to accurately get all the specific middleware, we need to unpack them. * The unpacked middleware groups could also have middleware groups inside them, * so we further unpack these, three times. * * For example, a route has a 'surface' middleware group. * The 'surface' group has a 'first-level' group, and that group has a 'second-level' group (three middleware group layers). * The 'second-level' group has a specific middleware (e.g. SomeMiddleware). * Using the getRouteMiddleware method on that route will get you all the middleware the route has, including SomeMiddleware. * * Note that the unpacking doesn't go further than three layers – if 'second-level' had 'third-level' that would have ThirdLevelMiddleware, * the middleware returned by this method won't include ThirdLevelMiddleware because the 'third-level' group won't get unpacked. */ public static function getRouteMiddleware(Route $route): array { $routeMiddleware = $route->middleware(); $controllerClass = $route->getControllerClass(); if ($controllerClass && is_a($controllerClass, HasMiddleware::class, true)) { $routeMiddleware = array_merge($routeMiddleware, $route->controllerMiddleware()); } $middlewareGroups = RouteFacade::getMiddlewareGroups(); $unpackGroupMiddleware = function (array $middleware) use ($middlewareGroups) { $innerMiddleware = []; foreach ($middleware as $inner) { if (! $inner instanceof Closure && isset($middlewareGroups[$inner])) { $innerMiddleware = Arr::wrap($middlewareGroups[$inner]); } } return $innerMiddleware; }; return array_unique(array_merge( $routeMiddleware, $firstLevelUnpackedGroupMiddleware = $unpackGroupMiddleware($routeMiddleware), $secondLevelUnpackedGroupMiddleware = $unpackGroupMiddleware($firstLevelUnpackedGroupMiddleware), $unpackGroupMiddleware($secondLevelUnpackedGroupMiddleware) )); } /** * Checks whether any of the passed middleware are present in the route's middleware stack. */ public static function routeHasMiddleware(Route $route, string|array $middlewares): bool { $routeMiddleware = static::getRouteMiddleware($route); foreach (Arr::wrap($middlewares) as $middleware) { if (in_array($middleware, $routeMiddleware)) { return true; } } return false; } /** * Check if a route has identification middleware. */ public static function routeHasIdentificationMiddleware(Route $route): bool { return static::routeHasMiddleware($route, static::middleware()); } /** * Check if route uses kernel identification (identification middleware is in the global stack and the route doesn't have route-level identification middleware). */ public static function routeUsesKernelIdentification(Route $route): bool { return ! static::routeHasIdentificationMiddleware($route) && tenancy()->globalStackHasMiddleware(static::middleware()); } /** * Checks whether any of the passed middleware are present in the global middleware stack. * * @param class-string|array $identificationMiddleware */ public static function globalStackHasMiddleware(string|array $identificationMiddleware = []): bool { /** @var Kernel $kernel */ $kernel = app(Kernel::class); foreach (Arr::wrap($identificationMiddleware) as $middleware) { if ($kernel->hasMiddleware($middleware)) { return true; } } return false; } /** * Obtain route from the passed request. * If the route isn't directly available on the request, * find the route that matches the passed request. */ public static function getRoute(Request $request): Route { /** @var ?Route $route */ $route = $request->route(); if (! $route) { /** @var Router $router */ $router = app(Router::class); $route = $router->getRoutes()->match($request); } return $route; } }