From 127945190ee60cba00e81dbf6bab3133495428a3 Mon Sep 17 00:00:00 2001 From: lukinovec Date: Fri, 28 Aug 2026 16:08:15 +0200 Subject: [PATCH] Correct and simplify tenantScopedPath() Instead of using the normalized path in the returned result, use the actual configured path (keeping its original separators). The separator normalization got removed completely. Accepting either separator at the prefix boundary (`str($configuredPath)->startsWith([$centralPath . '/', $centralPath . '\\'])`) covers what the normalization was there for, e.g. a path configured as `storage_path() . '/framework/foo_sessions'` while `storage_path()` joins the segments with `\` on Windows. Note that this does not cover the case where the configured path uses different separators than the original (central) path. For example, `C:\app\storage\framework\cache` while `storage_path()` is `C:/app/storage`. A case like this would need a `replace()` in the check. --- .../FilesystemTenancyBootstrapper.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Bootstrappers/FilesystemTenancyBootstrapper.php b/src/Bootstrappers/FilesystemTenancyBootstrapper.php index 01686915..dfe8848f 100644 --- a/src/Bootstrappers/FilesystemTenancyBootstrapper.php +++ b/src/Bootstrappers/FilesystemTenancyBootstrapper.php @@ -238,22 +238,20 @@ class FilesystemTenancyBootstrapper implements TenancyBootstrapper */ protected function tenantScopedPath(string $configuredPath, string $suffix): string { - // Normalize the paths to use the separator of the current OS. - $configuredPath = str_replace('/', DIRECTORY_SEPARATOR, $configuredPath); - $storagePath = str_replace('/', DIRECTORY_SEPARATOR, $this->originalStoragePath); + $centralPath = rtrim($this->originalStoragePath, '/\\'); - if (str_starts_with($configuredPath, $storagePath . DIRECTORY_SEPARATOR)) { - // Swap the central storage path prefix for the tenant's. + if (str($configuredPath)->startsWith([$centralPath . '/', $centralPath . '\\'])) { + // Swap the central storage path prefix for the tenant's, keeping the configured separators. // For example, storage_path('framework/cache/data') becomes storage_path('tenant1/framework/cache/data'). return str($configuredPath) - ->after($storagePath . DIRECTORY_SEPARATOR) - ->prepend($this->tenantStoragePath($suffix) . DIRECTORY_SEPARATOR) + ->after($centralPath) + ->prepend($this->tenantStoragePath($suffix)) ->toString(); } // Otherwise $configuredPath isn't necessarily storage_path()-based, so just append the // suffix as a subdirectory, e.g. '/var/cache/foo' becomes '/var/cache/foo/tenant1'. - return rtrim($configuredPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $suffix; + return rtrim($configuredPath, '/\\') . DIRECTORY_SEPARATOR . $suffix; } public function scopeSessions(string|false $suffix): void