mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 21:54:03 +00:00
Fixed Link command for Laravel v6, added StorageLink Events, more StorageLink tests, added RemoveStorageSymlinks Job, added Storage Jobs to TenancyServiceProvider stub, renamed misleading config example.
This commit is contained in:
parent
717b834c51
commit
5ed5aea6d6
11 changed files with 253 additions and 15 deletions
|
|
@ -28,6 +28,7 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
Jobs\CreateDatabase::class,
|
Jobs\CreateDatabase::class,
|
||||||
Jobs\MigrateDatabase::class,
|
Jobs\MigrateDatabase::class,
|
||||||
// Jobs\SeedDatabase::class,
|
// Jobs\SeedDatabase::class,
|
||||||
|
Jobs\CreateStorageSymlinks::class,
|
||||||
|
|
||||||
// Your own jobs to prepare the tenant.
|
// Your own jobs to prepare the tenant.
|
||||||
// Provision API keys, create S3 buckets, anything you want!
|
// Provision API keys, create S3 buckets, anything you want!
|
||||||
|
|
@ -44,6 +45,7 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
Events\TenantDeleted::class => [
|
Events\TenantDeleted::class => [
|
||||||
JobPipeline::make([
|
JobPipeline::make([
|
||||||
Jobs\DeleteDatabase::class,
|
Jobs\DeleteDatabase::class,
|
||||||
|
Jobs\RemoveStorageSymlinks::class,
|
||||||
])->send(function (Events\TenantDeleted $event) {
|
])->send(function (Events\TenantDeleted $event) {
|
||||||
return $event->tenant;
|
return $event->tenant;
|
||||||
})->shouldBeQueued(false), // `false` by default, but you probably want to make this `true` for production.
|
})->shouldBeQueued(false), // `false` by default, but you probably want to make this `true` for production.
|
||||||
|
|
@ -87,6 +89,12 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
Listeners\UpdateSyncedResource::class,
|
Listeners\UpdateSyncedResource::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// Storage symlinks
|
||||||
|
Events\CreatingStorageSymlink::class => [],
|
||||||
|
Events\StorageSymlinkCreated::class => [],
|
||||||
|
Events\RemovingStorageSymlink::class => [],
|
||||||
|
Events\StorageSymlinkRemoved::class => [],
|
||||||
|
|
||||||
// Fired only when a synced resource is changed in a different DB than the origin DB (to avoid infinite loops)
|
// Fired only when a synced resource is changed in a different DB than the origin DB (to avoid infinite loops)
|
||||||
Events\SyncedResourceChangedInForeignDatabase::class => [],
|
Events\SyncedResourceChangedInForeignDatabase::class => [],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ return [
|
||||||
*/
|
*/
|
||||||
'url_override' => [
|
'url_override' => [
|
||||||
// The array key is local disk (must exist in root_override) and value is public directory (%tenant_id% will be replaced with actual tenant id).
|
// The array key is local disk (must exist in root_override) and value is public directory (%tenant_id% will be replaced with actual tenant id).
|
||||||
'public' => 'storage-%tenant_id%',
|
'public' => 'public-%tenant_id%',
|
||||||
],
|
],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Commands;
|
namespace Stancl\Tenancy\Commands;
|
||||||
|
|
||||||
use Illuminate\Foundation\Console\StorageLinkCommand;
|
use Illuminate\Console\Command;
|
||||||
use Stancl\Tenancy\Concerns\HasATenantsOption;
|
use Stancl\Tenancy\Concerns\HasATenantsOption;
|
||||||
use Stancl\Tenancy\Contracts\Tenant;
|
use Stancl\Tenancy\Contracts\Tenant;
|
||||||
|
|
||||||
class Link extends StorageLinkCommand
|
class Link extends Command
|
||||||
{
|
{
|
||||||
use HasATenantsOption;
|
use HasATenantsOption;
|
||||||
|
|
||||||
|
|
@ -20,7 +20,8 @@ class Link extends StorageLinkCommand
|
||||||
protected $signature = 'tenants:link
|
protected $signature = 'tenants:link
|
||||||
{--tenants=* : The tenant(s) to run the command for. Default: all}
|
{--tenants=* : The tenant(s) to run the command for. Default: all}
|
||||||
{--relative : Create the symbolic link using relative paths}
|
{--relative : Create the symbolic link using relative paths}
|
||||||
{--force : Recreate existing symbolic links}';
|
{--force : Recreate existing symbolic links}
|
||||||
|
{--remove : Remove symbolic links}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
|
|
@ -29,6 +30,51 @@ class Link extends StorageLinkCommand
|
||||||
*/
|
*/
|
||||||
protected $description = 'Create the symbolic links configured for the tenancy applications';
|
protected $description = 'Create the symbolic links configured for the tenancy applications';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$relative = $this->option('relative');
|
||||||
|
|
||||||
|
if ($this->option('remove')) {
|
||||||
|
foreach ($this->links() as $link => $target) {
|
||||||
|
if (is_link($link)) {
|
||||||
|
$this->laravel->make('files')->delete($link);
|
||||||
|
|
||||||
|
$this->info("The [$link] link has been removed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('The links have been removed.');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->links() as $link => $target) {
|
||||||
|
if (file_exists($link) && ! $this->isRemovableSymlink($link, $this->option('force'))) {
|
||||||
|
$this->error("The [$link] link already exists.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_link($link)) {
|
||||||
|
$this->laravel->make('files')->delete($link);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($relative) {
|
||||||
|
$this->laravel->make('files')->relativeLink($target, $link);
|
||||||
|
} else {
|
||||||
|
$this->laravel->make('files')->link($target, $link);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info("The [$link] link has been connected to [$target].");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('The links have been created.');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the symbolic links that are configured for the application.
|
* Get the symbolic links that are configured for the application.
|
||||||
*
|
*
|
||||||
|
|
@ -40,16 +86,20 @@ class Link extends StorageLinkCommand
|
||||||
$disks = config('tenancy.filesystem.root_override');
|
$disks = config('tenancy.filesystem.root_override');
|
||||||
$suffix_base = config('tenancy.filesystem.suffix_base');
|
$suffix_base = config('tenancy.filesystem.suffix_base');
|
||||||
|
|
||||||
return $this->getTenants()
|
$tenants = $this->option('remove') && filled($this->option('tenants'))
|
||||||
->map(function (Tenant $tenant) use ($suffix_base, $disk_urls, $disks) {
|
? collect($this->option('tenants'))
|
||||||
|
: $this->getTenants()->map(function(Tenant $tenant) { return $tenant->getTenantKey(); });
|
||||||
|
|
||||||
|
return $tenants
|
||||||
|
->map(function ($tenant_key) use ($suffix_base, $disk_urls, $disks) {
|
||||||
|
|
||||||
$map = [];
|
$map = [];
|
||||||
|
|
||||||
foreach ($disk_urls as $disk => $public_path) {
|
foreach ($disk_urls as $disk => $public_path) {
|
||||||
$storage_path = str_replace('%storage_path%', $suffix_base . $tenant['id'], $disks[$disk]);
|
$storage_path = str_replace('%storage_path%', $suffix_base . $tenant_key, $disks[$disk]);
|
||||||
$storage_path = storage_path($storage_path);
|
$storage_path = storage_path($storage_path);
|
||||||
|
|
||||||
$public_path = str_replace('%tenant_id%', $tenant['id'], $public_path);
|
$public_path = str_replace('%tenant_id%', $tenant_key, $public_path);
|
||||||
$public_path = public_path($public_path);
|
$public_path = public_path($public_path);
|
||||||
|
|
||||||
// make sure storage path exist before we create symlink
|
// make sure storage path exist before we create symlink
|
||||||
|
|
@ -63,7 +113,19 @@ class Link extends StorageLinkCommand
|
||||||
return $map;
|
return $map;
|
||||||
|
|
||||||
})->flatten(1)
|
})->flatten(1)
|
||||||
->mapWithKeys(fn ($item) => $item)
|
->mapWithKeys(function ($item) {return $item; })
|
||||||
->all();
|
->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the provided path is a symlink that can be removed.
|
||||||
|
*
|
||||||
|
* @param string $link
|
||||||
|
* @param bool $force
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isRemovableSymlink(string $link, bool $force): bool
|
||||||
|
{
|
||||||
|
return is_link($link) && $force;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
src/Events/CreatingStorageSymlink.php
Normal file
9
src/Events/CreatingStorageSymlink.php
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Events;
|
||||||
|
|
||||||
|
class CreatingStorageSymlink extends Contracts\TenantEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
9
src/Events/RemovingStorageSymlink.php
Normal file
9
src/Events/RemovingStorageSymlink.php
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Events;
|
||||||
|
|
||||||
|
class RemovingStorageSymlink extends Contracts\TenantEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
9
src/Events/StorageSymlinkCreated.php
Normal file
9
src/Events/StorageSymlinkCreated.php
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Events;
|
||||||
|
|
||||||
|
class StorageSymlinkCreated extends Contracts\TenantEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
9
src/Events/StorageSymlinkRemoved.php
Normal file
9
src/Events/StorageSymlinkRemoved.php
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Events;
|
||||||
|
|
||||||
|
class StorageSymlinkRemoved extends Contracts\TenantEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,8 @@ use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
use Stancl\Tenancy\Contracts\Tenant;
|
use Stancl\Tenancy\Contracts\Tenant;
|
||||||
|
use Stancl\Tenancy\Events\CreatingStorageSymlink;
|
||||||
|
use Stancl\Tenancy\Events\StorageSymlinkCreated;
|
||||||
|
|
||||||
class CreateStorageSymlinks implements ShouldQueue
|
class CreateStorageSymlinks implements ShouldQueue
|
||||||
{
|
{
|
||||||
|
|
@ -39,8 +41,12 @@ class CreateStorageSymlinks implements ShouldQueue
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
event(new CreatingStorageSymlink($this->tenant));
|
||||||
|
|
||||||
Artisan::call('tenants:link', [
|
Artisan::call('tenants:link', [
|
||||||
'--tenants' => [$this->tenant->getTenantKey()],
|
'--tenants' => [$this->tenant->getTenantKey()],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
event(new StorageSymlinkCreated($this->tenant));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
55
src/Jobs/RemoveStorageSymlinks.php
Normal file
55
src/Jobs/RemoveStorageSymlinks.php
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Jobs;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
use Stancl\Tenancy\Contracts\Tenant;
|
||||||
|
use Stancl\Tenancy\Events\CreatingStorageSymlink;
|
||||||
|
use Stancl\Tenancy\Events\RemovingStorageSymlink;
|
||||||
|
use Stancl\Tenancy\Events\StorageSymlinkCreated;
|
||||||
|
use Stancl\Tenancy\Events\StorageSymlinkRemoved;
|
||||||
|
|
||||||
|
class RemoveStorageSymlinks implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Stancl\Tenancy\Contracts\Tenant
|
||||||
|
*/
|
||||||
|
public Tenant $tenant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(Tenant $tenant)
|
||||||
|
{
|
||||||
|
$this->tenant = $tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
event(new RemovingStorageSymlink($this->tenant));
|
||||||
|
|
||||||
|
Artisan::call('tenants:link', [
|
||||||
|
'--remove' => true,
|
||||||
|
'--tenants' => [$this->tenant->getTenantKey()],
|
||||||
|
]);
|
||||||
|
|
||||||
|
event(new StorageSymlinkRemoved($this->tenant));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,7 +17,10 @@ use Stancl\Tenancy\Bootstrappers\RedisTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Events\TenancyEnded;
|
use Stancl\Tenancy\Events\TenancyEnded;
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\Events\TenantCreated;
|
use Stancl\Tenancy\Events\TenantCreated;
|
||||||
|
use Stancl\Tenancy\Events\TenantDeleted;
|
||||||
use Stancl\Tenancy\Jobs\CreateDatabase;
|
use Stancl\Tenancy\Jobs\CreateDatabase;
|
||||||
|
use Stancl\Tenancy\Jobs\CreateStorageSymlinks;
|
||||||
|
use Stancl\Tenancy\Jobs\RemoveStorageSymlinks;
|
||||||
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
||||||
use Stancl\Tenancy\Tests\Etc\Tenant;
|
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||||
|
|
@ -218,7 +221,7 @@ class BootstrapperTest extends TestCase
|
||||||
FilesystemTenancyBootstrapper::class,
|
FilesystemTenancyBootstrapper::class,
|
||||||
],
|
],
|
||||||
'tenancy.filesystem.root_override.public' => '%storage_path%/app/public/',
|
'tenancy.filesystem.root_override.public' => '%storage_path%/app/public/',
|
||||||
'tenancy.filesystem.url_override.public' => 'storage-%tenant_id%'
|
'tenancy.filesystem.url_override.public' => 'public-%tenant_id%'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tenant1 = Tenant::create();
|
$tenant1 = Tenant::create();
|
||||||
|
|
@ -226,16 +229,57 @@ class BootstrapperTest extends TestCase
|
||||||
|
|
||||||
tenancy()->initialize($tenant1);
|
tenancy()->initialize($tenant1);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'http://localhost/storage-'.$tenant1->getTenantKey().'/',
|
'http://localhost/public-'.$tenant1->getTenantKey().'/',
|
||||||
Storage::disk('public')->url('')
|
Storage::disk('public')->url('')
|
||||||
);
|
);
|
||||||
|
|
||||||
tenancy()->initialize($tenant2);
|
tenancy()->initialize($tenant2);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'http://localhost/storage-'.$tenant2->getTenantKey().'/',
|
'http://localhost/public-'.$tenant2->getTenantKey().'/',
|
||||||
Storage::disk('public')->url('')
|
Storage::disk('public')->url('')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function create_and_delete_storage_symlinks_jobs_works()
|
||||||
|
{
|
||||||
|
Event::listen(
|
||||||
|
TenantCreated::class,
|
||||||
|
JobPipeline::make([CreateStorageSymlinks::class])->send(function (TenantCreated $event) {
|
||||||
|
return $event->tenant;
|
||||||
|
})->toListener()
|
||||||
|
);
|
||||||
|
|
||||||
|
Event::listen(
|
||||||
|
TenantDeleted::class,
|
||||||
|
JobPipeline::make([RemoveStorageSymlinks::class])->send(function (TenantDeleted $event) {
|
||||||
|
return $event->tenant;
|
||||||
|
})->toListener()
|
||||||
|
);
|
||||||
|
|
||||||
|
config([
|
||||||
|
'tenancy.bootstrappers' => [
|
||||||
|
FilesystemTenancyBootstrapper::class,
|
||||||
|
],
|
||||||
|
'tenancy.filesystem.suffix_base' => 'tenant-',
|
||||||
|
'tenancy.filesystem.root_override.public' => '%storage_path%/app/public/',
|
||||||
|
'tenancy.filesystem.url_override.public' => 'public-%tenant_id%'
|
||||||
|
]);
|
||||||
|
|
||||||
|
/** @var \Stancl\Tenancy\Database\Models\Tenant $tenant */
|
||||||
|
$tenant = Tenant::create();
|
||||||
|
|
||||||
|
tenancy()->initialize($tenant);
|
||||||
|
|
||||||
|
$tenant_key = $tenant->getTenantKey();
|
||||||
|
|
||||||
|
$this->assertDirectoryExists(storage_path("app/public"));
|
||||||
|
$this->assertEquals(storage_path("app/public/"), readlink(public_path("public-$tenant_key")));
|
||||||
|
|
||||||
|
$tenant->delete();
|
||||||
|
|
||||||
|
$this->assertDirectoryDoesNotExist(public_path("public-$tenant_key"));
|
||||||
|
}
|
||||||
|
|
||||||
// for queues see QueueTest
|
// for queues see QueueTest
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class CommandsTest extends TestCase
|
||||||
],
|
],
|
||||||
'tenancy.filesystem.suffix_base' => 'tenant-',
|
'tenancy.filesystem.suffix_base' => 'tenant-',
|
||||||
'tenancy.filesystem.root_override.public' => '%storage_path%/app/public/',
|
'tenancy.filesystem.root_override.public' => '%storage_path%/app/public/',
|
||||||
'tenancy.filesystem.url_override.public' => 'storage-%tenant_id%'
|
'tenancy.filesystem.url_override.public' => 'public-%tenant_id%'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||||
|
|
@ -215,8 +215,35 @@ class CommandsTest extends TestCase
|
||||||
Artisan::call('tenants:link');
|
Artisan::call('tenants:link');
|
||||||
|
|
||||||
$this->assertDirectoryExists(storage_path("tenant-$tenantId1/app/public"));
|
$this->assertDirectoryExists(storage_path("tenant-$tenantId1/app/public"));
|
||||||
$this->assertDirectoryExists(public_path("storage-$tenantId1"));
|
$this->assertEquals(storage_path("tenant-$tenantId1/app/public/"), readlink(public_path("public-$tenantId1")));
|
||||||
|
|
||||||
$this->assertDirectoryExists(storage_path("tenant-$tenantId2/app/public"));
|
$this->assertDirectoryExists(storage_path("tenant-$tenantId2/app/public"));
|
||||||
$this->assertDirectoryExists(public_path("storage-$tenantId2"));
|
$this->assertEquals(storage_path("tenant-$tenantId2/app/public/"), readlink(public_path("public-$tenantId2")));
|
||||||
|
|
||||||
|
Artisan::call('tenants:link', [
|
||||||
|
'--remove' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertDirectoryDoesNotExist(public_path("public-$tenantId1"));
|
||||||
|
$this->assertDirectoryDoesNotExist(public_path("public-$tenantId2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function link_command_with_tenant_specified_works()
|
||||||
|
{
|
||||||
|
$tenant_key = Tenant::create()->getTenantKey();
|
||||||
|
Artisan::call('tenants:link', [
|
||||||
|
'--tenants' => [$tenant_key],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertDirectoryExists(storage_path("tenant-$tenant_key/app/public"));
|
||||||
|
$this->assertEquals(storage_path("tenant-$tenant_key/app/public/"), readlink(public_path("public-$tenant_key")));
|
||||||
|
|
||||||
|
Artisan::call('tenants:link', [
|
||||||
|
'--remove' => true,
|
||||||
|
'--tenants' => [$tenant_key],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertDirectoryDoesNotExist(public_path("public-$tenant_key"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue