1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2026-05-06 16:24:03 +00:00
1. Remove the CreateTenantStorage job altogether since as the docblock
   says the class should be redundant now that
   FilesystemTenancyBootstrapper creates this path automatically when
   storage_path suffixing is enabled
2. Remove docblock on the DeleteTenantStorage job - a class's docblock
   should describe what it does, not how it handles edge cases. Here
   the former isn't even necessary and the latter is well explained by
   comments in the implementation.
3. Remove the CreateTenantStorage test following the class's removal,
   the test would pass on its own even without the job with just
   tenancy initialization as mentioned above.
4. Slightly improve the structure of the DeleteTenantStorage job and
   deprecated listener
5. Improve deprecation notices so they include full steps for upgrading
   to the new approach.
This commit is contained in:
Samuel Stancl 2026-04-20 18:22:04 +02:00
parent 97e856616c
commit 5bb76e1421
No known key found for this signature in database
GPG key ID: BA146259A1E16C57
6 changed files with 22 additions and 85 deletions

View file

@ -46,7 +46,6 @@ class TenancyServiceProvider extends ServiceProvider
Jobs\CreateDatabase::class,
Jobs\MigrateDatabase::class,
// Jobs\SeedDatabase::class,
// Jobs\CreateTenantStorage::class,
// Jobs\CreateStorageSymlinks::class,
// Your own jobs to prepare the tenant.

View file

@ -1,39 +0,0 @@
<?php
declare(strict_types=1);
namespace Stancl\Tenancy\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Stancl\Tenancy\Contracts\Tenant;
/**
* Can be used to manually create framework directories in the tenant storage when storage_path() is scoped.
*
* Useful when using real-time facades which use the framework/cache directory.
*
* Generally not needed anymore as the directory is also created by the FilesystemTenancyBootstrapper.
*/
class CreateTenantStorage implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(
public Tenant $tenant,
) {}
public function handle(): void
{
$storage_path = tenancy()->run($this->tenant, fn () => storage_path());
$cache_path = "$storage_path/framework/cache";
if (! is_dir($cache_path)) {
// Create the tenant's storage directory and /framework/cache within (used for e.g. real-time facades)
mkdir($cache_path, 0750, true);
}
}
}

View file

@ -12,13 +12,6 @@ use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\File;
use Stancl\Tenancy\Contracts\Tenant;
/**
* Only delete the tenant storage if storage path suffixing is enabled
* and the tenant's storage path is different from the central storage path.
*
* This is to prevent accidental deletion of the central storage when
* a tenant's storage path is not properly suffixed.
*/
class DeleteTenantStorage implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@ -29,19 +22,22 @@ class DeleteTenantStorage implements ShouldQueue
public function handle(): void
{
// Skip storage deletion if path suffixing is disabled
if (config('tenancy.filesystem.suffix_storage_path') === false) {
// Skip storage deletion if path suffixing is disabled
return;
}
$centralPath = tenancy()->central(fn () => storage_path());
$path = tenancy()->run($this->tenant, fn () => storage_path());
$centralStoragePath = tenancy()->central(fn () => storage_path());
$tenantStoragePath = tenancy()->run($this->tenant, fn () => storage_path());
// Skip storage deletion if tenant's storage path is the same as central storage path
$tenantPathIsCentral = realpath($path) === realpath($centralPath);
if ($tenantStoragePath === $centralStoragePath) {
// Check again to ensure the tenant storage path is distinct from the central storage path
// to avoid any accidental central storage path deletion
return;
}
if (is_dir($path) && ! $tenantPathIsCentral) {
File::deleteDirectory($path);
if (is_dir($tenantStoragePath)) {
File::deleteDirectory($tenantStoragePath);
}
}
}

View file

@ -7,7 +7,7 @@ namespace Stancl\Tenancy\Listeners;
use Stancl\Tenancy\Events\Contracts\TenantEvent;
/**
* @deprecated use Stancl\Tenancy\Jobs\CreateTenantStorage instead.
* @deprecated FilesystemTenancyBootstrapper creates the path automatically when suffix_storage_path is enabled.
*/
class CreateTenantStorage
{

View file

@ -8,25 +8,28 @@ use Illuminate\Support\Facades\File;
use Stancl\Tenancy\Events\Contracts\TenantEvent;
/**
* @deprecated use Stancl\Tenancy\Jobs\DeleteTenantStorage instead.
* @deprecated Use Stancl\Tenancy\Jobs\DeleteTenantStorage in a job pipeline instead.
*/
class DeleteTenantStorage
{
public function handle(TenantEvent $event): void
{
// Skip storage deletion if path suffixing is disabled
if (config('tenancy.filesystem.suffix_storage_path') === false) {
// Skip storage deletion if path suffixing is disabled
return;
}
$centralPath = tenancy()->central(fn () => storage_path());
$path = tenancy()->run($event->tenant, fn () => storage_path());
$centralStoragePath = tenancy()->central(fn () => storage_path());
$tenantStoragePath = tenancy()->run($event->tenant, fn () => storage_path());
// Skip storage deletion if tenant's storage path is the same as central storage path
$tenantPathIsCentral = realpath($path) === realpath($centralPath);
if ($tenantStoragePath === $centralStoragePath) {
// Check again to ensure the tenant storage path is distinct from the central storage path
// to avoid any accidental central storage path deletion
return;
}
if (is_dir($path) && ! $tenantPathIsCentral) {
File::deleteDirectory($path);
if (is_dir($tenantStoragePath)) {
File::deleteDirectory($tenantStoragePath);
}
}
}

View file

@ -13,7 +13,6 @@ use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Jobs\CreateStorageSymlinks;
use Stancl\Tenancy\Jobs\RemoveStorageSymlinks;
use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Jobs\CreateTenantStorage;
use Stancl\Tenancy\Jobs\DeleteTenantStorage;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
@ -185,27 +184,6 @@ test('create and delete storage symlinks jobs work', function() {
$this->assertDirectoryDoesNotExist(public_path("public-$tenantKey"));
});
test('tenant storage gets created when TenantCreated listens to CreateTenantStorage', function() {
config([
'tenancy.bootstrappers' => [
FilesystemTenancyBootstrapper::class,
],
]);
Event::listen(TenantCreated::class,
JobPipeline::make([CreateTenantStorage::class])->send(function (TenantCreated $event) {
return $event->tenant;
})->shouldBeQueued(false)->toListener()
);
$centralStoragePath = storage_path();
$tenant = Tenant::create();
$suffixBase = config('tenancy.filesystem.suffix_base', 'tenant');
$tenantStoragePath = $centralStoragePath . '/' . $suffixBase . $tenant->getTenantKey();
$this->assertDirectoryExists($tenantStoragePath . '/framework/cache');
});
test('tenant storage can get deleted after the tenant when DeletingTenant listens to DeleteTenantStorage', function() {
Event::listen(DeletingTenant::class,
JobPipeline::make([DeleteTenantStorage::class])->send(function (DeletingTenant $event) {