From 410165e7bafb95f322caa9b0d221b609d86e2311 Mon Sep 17 00:00:00 2001 From: lukinovec Date: Tue, 3 Jun 2025 12:09:26 +0200 Subject: [PATCH] Handle nested cloning flags in CloneRoutesAsTenant --- src/Actions/CloneRoutesAsTenant.php | 53 +++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/src/Actions/CloneRoutesAsTenant.php b/src/Actions/CloneRoutesAsTenant.php index 38841d24..7e07ec43 100644 --- a/src/Actions/CloneRoutesAsTenant.php +++ b/src/Actions/CloneRoutesAsTenant.php @@ -132,16 +132,7 @@ class CloneRoutesAsTenant /** @var array $middleware */ $middleware = $action->get('middleware') ?? []; - - $middleware = collect($middleware) - ->merge(['tenant']) // Add 'tenant' flag - // todo0 what if 'clone' is within some middleware group - not top level? this should be handled similarly - // to tenancy()->routeHasMiddleware() - use the same traversal depth. only issue is that in such a case, we - // *do* want the other middleware from the group, so we'd have to extract them from the group and include them - // directly - not using the containing group - just with 'clone' / cloneRoutesWithMiddleware removed. - // start by seeing if this can be reproduced in a reasonable scenario in a regression test - ->filter(fn (string $middleware) => ! in_array($middleware, $this->cloneRoutesWithMiddleware)) - ->toArray(); + $middleware = $this->processMiddlewareForCloning($middleware); $tenantRouteNamePrefix = PathTenantResolver::tenantRouteNamePrefix(); @@ -174,4 +165,46 @@ class CloneRoutesAsTenant ->withTrashed($originalRoute->allowsTrashedBindings()) ->setDefaults($originalRoute->defaults); } + + /** + * Process middleware for cloning, handling middleware groups properly. + * This extracts middleware from groups (up to 3 levels deep), filters out + * cloneRoutesWithMiddleware, and adds the 'tenant' middleware. + * + * Uses approach similar to getRouteMiddleware() in DealsWithRouteContexts for consistency. + */ + protected function processMiddlewareForCloning(array $middlewares): array + { + $middlewareGroups = $this->router->getMiddlewareGroups(); + + $unpackGroupMiddleware = function (array $middleware) use ($middlewareGroups) { + $innerMiddleware = []; + + foreach ($middleware as $inner) { + if (isset($middlewareGroups[$inner])) { + $innerMiddleware = array_merge($innerMiddleware, $middlewareGroups[$inner]); + } else { + // Actual middleware, not a group + $innerMiddleware[] = $inner; + } + } + + return $innerMiddleware; + }; + + // Extract all middleware from groups (up to 3 levels deep) + $firstLevelUnpacked = $unpackGroupMiddleware($middlewares); + $secondLevelUnpacked = $unpackGroupMiddleware($firstLevelUnpacked); + $thirdLevelUnpacked = $unpackGroupMiddleware($secondLevelUnpacked); + + // Filter out MW in cloneRoutesWithMiddleware and add the 'tenant' flag + $processedMiddleware = array_filter( + $thirdLevelUnpacked, + fn ($mw) => ! in_array($mw, $this->cloneRoutesWithMiddleware) + ); + + $processedMiddleware[] = 'tenant'; + + return array_unique($processedMiddleware); + } }