mirror of
https://github.com/archtechx/tenancy.git
synced 2026-09-20 14:14:03 +00:00
Refactor remove symlinks action, add static::$removeNestedDirectories
In removeLink(), return early if the symlink doesn't exist. The nested directory deletion is now controlled by the $removeNestedDirectories static property. It's disabled by default. public_path() and dirname($publicPath) are now normalized using realpath() before the nested dir deletion. The delete loop now checks if the directory-to-be-deleted is *inside* the public root instead of checking if it's not equal to to the public root.
This commit is contained in:
parent
b2b8d50edb
commit
1e1e2efb8c
2 changed files with 37 additions and 7 deletions
|
|
@ -15,6 +15,15 @@ class RemoveStorageSymlinksAction
|
||||||
{
|
{
|
||||||
use DealsWithTenantSymlinks;
|
use DealsWithTenantSymlinks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should the directories created for nested symlinks be removed along with the symlink.
|
||||||
|
*
|
||||||
|
* Before enabling this, make sure you understand the removeLink() method and its implications.
|
||||||
|
*
|
||||||
|
* @see CreateStorageSymlinksAction
|
||||||
|
*/
|
||||||
|
public static bool $removeNestedDirectories = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Tenant|Collection<covariant int|string, Tenant&\Illuminate\Database\Eloquent\Model>|LazyCollection<covariant int|string, Tenant&\Illuminate\Database\Eloquent\Model> $tenants
|
* @param Tenant|Collection<covariant int|string, Tenant&\Illuminate\Database\Eloquent\Model>|LazyCollection<covariant int|string, Tenant&\Illuminate\Database\Eloquent\Model> $tenants
|
||||||
*/
|
*/
|
||||||
|
|
@ -32,21 +41,32 @@ class RemoveStorageSymlinksAction
|
||||||
|
|
||||||
protected function removeLink(string $publicPath, Tenant $tenant): void
|
protected function removeLink(string $publicPath, Tenant $tenant): void
|
||||||
{
|
{
|
||||||
|
if (! $this->symlinkExists($publicPath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$files = app()->make('files');
|
$files = app()->make('files');
|
||||||
|
|
||||||
if ($this->symlinkExists($publicPath)) {
|
|
||||||
event(new RemovingStorageSymlink($tenant));
|
event(new RemovingStorageSymlink($tenant));
|
||||||
|
|
||||||
$files->delete($publicPath);
|
$files->delete($publicPath);
|
||||||
|
|
||||||
event(new StorageSymlinkRemoved($tenant));
|
event(new StorageSymlinkRemoved($tenant));
|
||||||
|
|
||||||
|
if (! static::$removeNestedDirectories) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$publicRoot = realpath(public_path());
|
||||||
|
$directory = realpath(dirname($publicPath));
|
||||||
|
|
||||||
|
if ($publicRoot === false || $directory === false) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the directories CreateStorageSymlinksAction created for the symlink
|
// Remove the directories CreateStorageSymlinksAction created for the symlink
|
||||||
// until a non-empty one is reached.
|
// until a non-empty one is reached.
|
||||||
$directory = dirname($publicPath);
|
while (str_starts_with($directory, $publicRoot . DIRECTORY_SEPARATOR) && $files->isEmptyDirectory($directory)) {
|
||||||
|
|
||||||
while ($directory !== public_path() && $files->isEmptyDirectory($directory)) {
|
|
||||||
$files->deleteDirectory($directory);
|
$files->deleteDirectory($directory);
|
||||||
|
|
||||||
$directory = dirname($directory);
|
$directory = dirname($directory);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,12 @@ use Illuminate\Support\Facades\Storage;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||||
Event::listen(TenancyEnded::class, RevertToCentralContext::class);
|
Event::listen(TenancyEnded::class, RevertToCentralContext::class);
|
||||||
|
|
||||||
|
RemoveStorageSymlinksAction::$removeNestedDirectories = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
RemoveStorageSymlinksAction::$removeNestedDirectories = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
test('create storage symlinks action works', function (string|null $rootOverride, bool $suffixStoragePath) {
|
test('create storage symlinks action works', function (string|null $rootOverride, bool $suffixStoragePath) {
|
||||||
|
|
@ -207,6 +213,8 @@ test('symlinks of prefixed disks only expose the prefixed directory', function (
|
||||||
});
|
});
|
||||||
|
|
||||||
test('removing a prefixed disk symlink removes the directories created for it', function () {
|
test('removing a prefixed disk symlink removes the directories created for it', function () {
|
||||||
|
RemoveStorageSymlinksAction::$removeNestedDirectories = true;
|
||||||
|
|
||||||
config([
|
config([
|
||||||
'tenancy.bootstrappers' => [
|
'tenancy.bootstrappers' => [
|
||||||
FilesystemTenancyBootstrapper::class,
|
FilesystemTenancyBootstrapper::class,
|
||||||
|
|
@ -241,6 +249,8 @@ test('removing a prefixed disk symlink removes the directories created for it',
|
||||||
});
|
});
|
||||||
|
|
||||||
test('non-empty directories are not removed with the symlink', function () {
|
test('non-empty directories are not removed with the symlink', function () {
|
||||||
|
RemoveStorageSymlinksAction::$removeNestedDirectories = true;
|
||||||
|
|
||||||
config([
|
config([
|
||||||
'tenancy.bootstrappers' => [
|
'tenancy.bootstrappers' => [
|
||||||
FilesystemTenancyBootstrapper::class,
|
FilesystemTenancyBootstrapper::class,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue