mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-13 00:34:03 +00:00
Improve route cloning action (#8)
* Allow cloning routes when only kernel identification is used, explicitly enable specific cloning modes * Explicitly enable needed clone modes in tests, use "clone" instead of "reregister" * Fix code style (php-cs-fixer) * Use "cloning" instead of "re-registration" in UniversalRouteTest * Only clone routes using path identification * Revert clone mode changes * Fix code style (php-cs-fixer) * Update comment * Skip cloning 'stancl.tenancy.asset' by default * Decide which routes should get cloned in the filtering step, improve method organization * Return `RouteMode::UNIVERSAL` in getMiddlewareContext if route is universal * Give universal route the path ID MW so that it gets cloned * Fix code style (php-cs-fixer) * Simplify UsableWithEarlyIdentification code * Handle universal route mode in ForgetTenantParameter * Fix code style (php-cs-fixer) * Rename getMiddlewareContext to getRouteMode * Append '/' to the route prefix * Rename variable * Wrap part of condition in parentheses * Refresh name lookups after cloning routes * Test giving tenant flag to cloned routes * Add routeIsUniversal method * Correct ForgetTenantParameter condition * Improve tenant flag giving logic * Improve test name * Delete leftover testing code * Put part of condition into `()` * Improve CloneRoutesAsTenant code + comments * Extract route mode-related code into methods, refactor and improve code * Improve ForgetTenantParameter, test tenant parameter removing in universal routes * Fix code style (php-cs-fixer) * Fix test * Simplify adding tenant flag * Don't skip stancl.tenancy.asset route cloning * clean up comment * fix in_array() argument * Fix code style (php-cs-fixer) --------- Co-authored-by: PHP CS Fixer <phpcsfixer@example.com> Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
This commit is contained in:
parent
4d4639450e
commit
f7d9f02fd4
9 changed files with 222 additions and 111 deletions
|
|
@ -5,42 +5,61 @@ declare(strict_types=1);
|
|||
namespace Stancl\Tenancy\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Http\Kernel;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Route;
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Route as RouteFacade;
|
||||
use Stancl\Tenancy\Enums\Context;
|
||||
use Stancl\Tenancy\Enums\RouteMode;
|
||||
|
||||
// todo1 Name – maybe DealsWithMiddlewareContexts?
|
||||
trait DealsWithEarlyIdentification
|
||||
{
|
||||
/**
|
||||
* Get route's middleware context (tenant or central).
|
||||
* Get route's middleware context (tenant, central or universal).
|
||||
* The context is determined by the route's middleware.
|
||||
*
|
||||
* If the route has the 'central' middleware, the context is central.
|
||||
* If the route has the 'tenant' middleware, or any tenancy identification middleware, the context is tenant.
|
||||
* If the route has the 'tenant' middleware, or any tenancy identification middleware (and the route isn't flagged as universal), the context is tenant.
|
||||
*
|
||||
* If the route doesn't have any of the mentioned middleware,
|
||||
* the context is determined by the `tenancy.default_route_mode` config.
|
||||
*/
|
||||
public static function getMiddlewareContext(Route $route): RouteMode
|
||||
public static function getRouteMode(Route $route): RouteMode
|
||||
{
|
||||
if (static::routeHasMiddleware($route, 'central')) {
|
||||
return RouteMode::CENTRAL;
|
||||
}
|
||||
|
||||
$defaultRouteMode = config('tenancy.default_route_mode');
|
||||
$routeIsUniversal = $defaultRouteMode === RouteMode::UNIVERSAL || static::routeHasMiddleware($route, 'universal');
|
||||
$routeIsUniversal = static::routeIsUniversal($route);
|
||||
|
||||
// If a route has identification middleware AND the route isn't universal, don't consider the context tenant
|
||||
if (static::routeHasMiddleware($route, 'tenant') || static::routeHasIdentificationMiddleware($route) && ! $routeIsUniversal) {
|
||||
// If the route is flagged as tenant, consider it tenant
|
||||
// If the route has an identification middleware and the route is not universal, consider it tenant
|
||||
if (
|
||||
static::routeHasMiddleware($route, 'tenant') ||
|
||||
(static::routeHasIdentificationMiddleware($route) && ! $routeIsUniversal)
|
||||
) {
|
||||
return RouteMode::TENANT;
|
||||
}
|
||||
|
||||
return $defaultRouteMode;
|
||||
// If the route is universal, you have to determine its actual context using
|
||||
// The identification middleware's determineUniversalRouteContextFromRequest
|
||||
if ($routeIsUniversal) {
|
||||
return RouteMode::UNIVERSAL;
|
||||
}
|
||||
|
||||
return config('tenancy.default_route_mode');
|
||||
}
|
||||
|
||||
public static function routeIsUniversal(Route $route): bool
|
||||
{
|
||||
$routeFlaggedAsTenantOrCentral = static::routeHasMiddleware($route, 'tenant') || static::routeHasMiddleware($route, 'central');
|
||||
$routeFlaggedAsUniversal = static::routeHasMiddleware($route, 'universal');
|
||||
$universalFlagUsedInGlobalStack = app(Kernel::class)->hasMiddleware('universal');
|
||||
$defaultRouteModeIsUniversal = config('tenancy.default_route_mode') === RouteMode::UNIVERSAL;
|
||||
|
||||
return ! $routeFlaggedAsTenantOrCentral && ($routeFlaggedAsUniversal || $universalFlagUsedInGlobalStack || $defaultRouteModeIsUniversal);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -93,6 +112,31 @@ trait DealsWithEarlyIdentification
|
|||
return in_array($middleware, static::getRouteMiddleware($route));
|
||||
}
|
||||
|
||||
public function routeIdentificationMiddleware(Route $route): string|null
|
||||
{
|
||||
foreach (static::getRouteMiddleware($route) as $routeMiddleware) {
|
||||
if (in_array($routeMiddleware, static::middleware())) {
|
||||
return $routeMiddleware;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function kernelIdentificationMiddleware(): string|null
|
||||
{
|
||||
/** @var Kernel $kernel */
|
||||
$kernel = app(Kernel::class);
|
||||
|
||||
foreach (static::middleware() as $identificationMiddleware) {
|
||||
if ($kernel->hasMiddleware($identificationMiddleware)) {
|
||||
return $identificationMiddleware;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a route has identification middleware.
|
||||
*/
|
||||
|
|
@ -107,6 +151,14 @@ trait DealsWithEarlyIdentification
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if route uses kernel identification (identification middleare 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) && static::kernelIdentificationMiddleware();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a route uses domain identification.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -29,21 +29,13 @@ trait UsableWithEarlyIdentification
|
|||
{
|
||||
/**
|
||||
* Skip middleware if the route is universal and uses path identification or if the route is universal and the context should be central.
|
||||
* Universal routes using path identification should get re-registered using ReregisterRoutesAsTenant.
|
||||
* Universal routes using path identification should get cloned using CloneRoutesAsTenant.
|
||||
*
|
||||
* @see \Stancl\Tenancy\Actions\CloneRoutesAsTenant
|
||||
*/
|
||||
protected function shouldBeSkipped(Route $route): bool
|
||||
{
|
||||
$routeMiddleware = tenancy()->getRouteMiddleware($route);
|
||||
$universalFlagUsed = in_array('universal', $routeMiddleware);
|
||||
$defaultToUniversalRoutes = config('tenancy.default_route_mode') === RouteMode::UNIVERSAL;
|
||||
|
||||
// Route is universal only if it doesn't have the central/tenant flag
|
||||
$routeIsUniversal = ($universalFlagUsed || $defaultToUniversalRoutes) &&
|
||||
! (in_array('central', $routeMiddleware) || in_array('tenant', $routeMiddleware));
|
||||
|
||||
if ($routeIsUniversal && $this instanceof IdentificationMiddleware) {
|
||||
if (tenancy()->routeIsUniversal($route) && $this instanceof IdentificationMiddleware) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
throw_unless($this instanceof UsableWithUniversalRoutes, MiddlewareNotUsableWithUniversalRoutesException::class);
|
||||
|
||||
|
|
@ -71,10 +63,15 @@ trait UsableWithEarlyIdentification
|
|||
|
||||
// Check if this is the identification middleware the route should be using
|
||||
// Route-level identification middleware is prioritized
|
||||
$middlewareUsed = tenancy()->routeHasMiddleware($route, static::class) || ! tenancy()->routeHasIdentificationMiddleware($route) && static::inGlobalStack();
|
||||
$globalIdentificationUsed = ! tenancy()->routeHasIdentificationMiddleware($route) && static::inGlobalStack();
|
||||
$routeLevelIdentificationUsed = tenancy()->routeHasMiddleware($route, static::class);
|
||||
|
||||
/** @var UsableWithUniversalRoutes $this */
|
||||
return $middlewareUsed && $this->requestHasTenant($request) ? Context::TENANT : Context::CENTRAL;
|
||||
if (($globalIdentificationUsed || $routeLevelIdentificationUsed) && $this->requestHasTenant($request)) {
|
||||
return Context::TENANT;
|
||||
}
|
||||
|
||||
return Context::CENTRAL;
|
||||
}
|
||||
|
||||
protected function shouldIdentificationMiddlewareBeSkipped(Route $route): bool
|
||||
|
|
@ -88,10 +85,9 @@ trait UsableWithEarlyIdentification
|
|||
if (! $request->attributes->get('_tenancy_kernel_identification_skipped')) {
|
||||
if (
|
||||
// Skip identification if the current route is central
|
||||
// The route is central if defaulting is set to central and the route isn't flagged as tenant or it doesn't have identification middleware
|
||||
tenancy()->getMiddlewareContext($route) === RouteMode::CENTRAL
|
||||
// Don't skip identification if the central route is considered universal
|
||||
&& (config('tenancy.default_route_mode') !== RouteMode::UNIVERSAL || ! tenancy()->routeHasMiddleware($route, 'universal'))
|
||||
// The route is central if it's flagged as central
|
||||
// Or if it isn't flagged and the default route mode is set to central
|
||||
tenancy()->getRouteMode($route) === RouteMode::CENTRAL
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue