mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 21:54:03 +00:00
Extract Link command logic into actions
This commit is contained in:
parent
fa783641f4
commit
2594b1960f
6 changed files with 182 additions and 110 deletions
|
|
@ -4,8 +4,12 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy\Commands;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
use Stancl\Tenancy\Concerns\HasATenantsOption;
|
||||
use Stancl\Tenancy\CreateStorageSymlinksAction;
|
||||
use Stancl\Tenancy\RemoveStorageSymlinksAction;
|
||||
|
||||
class Link extends Command
|
||||
{
|
||||
|
|
@ -27,7 +31,7 @@ class Link extends Command
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create symbolic links for tenants.';
|
||||
protected $description = 'Create or remove tenant symbolic links.';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
|
|
@ -36,102 +40,48 @@ class Link extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
$tenants = collect($this->option('tenants')) ?? $this->getTenants()->map->getTenantKey();
|
||||
$links = $tenants->flatMap(fn ($tenantKey) => $this->getPossibleTenantSymlinks($tenantKey))
|
||||
->mapWithKeys(fn ($item) => $item)
|
||||
->all();
|
||||
$tenants = $this->getTenants();
|
||||
|
||||
if ($this->option('remove')) {
|
||||
$this->removeLinks($links);
|
||||
} else {
|
||||
$this->createLinks($links);
|
||||
try {
|
||||
if ($this->option('remove')) {
|
||||
$this->removeLinks($tenants);
|
||||
} else {
|
||||
$this->createLinks($tenants);
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
$this->error($exception->getMessage());
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
protected function removeLinks(array $links)
|
||||
/**
|
||||
* @param LazyCollection $tenants
|
||||
* @return void
|
||||
*/
|
||||
protected function removeLinks($tenants)
|
||||
{
|
||||
foreach ($links as $publicPath => $storagePath) {
|
||||
$this->removeLink($publicPath);
|
||||
}
|
||||
RemoveStorageSymlinksAction::handle(
|
||||
$tenants,
|
||||
afterLinkRemoval: fn($publicPath) => $this->info("The [$publicPath] link has been removed.")
|
||||
);
|
||||
|
||||
$this->info('The links have been removed.');
|
||||
}
|
||||
|
||||
protected function createLinks(array $links)
|
||||
/**
|
||||
* @param LazyCollection $tenants
|
||||
* @return void
|
||||
*/
|
||||
protected function createLinks($tenants)
|
||||
{
|
||||
foreach ($links as $link => $storagePath) {
|
||||
$this->createLink($link, $storagePath);
|
||||
}
|
||||
CreateStorageSymlinksAction::handle(
|
||||
$tenants,
|
||||
$this->option('relative') ?? false,
|
||||
$this->option('force') ?? false,
|
||||
afterLinkCreation: fn($publicPath, $storagePath) => $this->info("The [$publicPath] link has been connected to [$storagePath].")
|
||||
);
|
||||
|
||||
$this->info('The links have been created.');
|
||||
}
|
||||
|
||||
protected function removeLink(string $publicPath)
|
||||
{
|
||||
if ($this->symlinkExists($publicPath)) {
|
||||
$this->laravel->make('files')->delete($publicPath);
|
||||
|
||||
$this->info("The [$publicPath] link has been removed.");
|
||||
}
|
||||
}
|
||||
|
||||
protected function createLink(string $publicPath, string $storagePath)
|
||||
{
|
||||
if ($this->symlinkExists($publicPath)) {
|
||||
// If the 'force' option isn't passed, don't overwrite the existing symlink
|
||||
if (! $this->option('force')) {
|
||||
$this->error("The [$publicPath] link already exists.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->laravel->make('files')->delete($publicPath);
|
||||
}
|
||||
|
||||
// Make sure the storage path exists before we create a symlink
|
||||
if (! is_dir($storagePath)) {
|
||||
mkdir($storagePath, 0777, true);
|
||||
}
|
||||
|
||||
if ($this->option('relative')) {
|
||||
$this->laravel->make('files')->relativeLink($storagePath, $publicPath);
|
||||
} else {
|
||||
$this->laravel->make('files')->link($storagePath, $publicPath);
|
||||
}
|
||||
|
||||
$this->info("The [$publicPath] link has been connected to [$storagePath].");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all possible tenant symlinks, existing or not (array of ['public path' => 'storage path']).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getPossibleTenantSymlinks(int|string $tenantKey)
|
||||
{
|
||||
$diskUrls = config('tenancy.filesystem.url_override');
|
||||
$disks = config('tenancy.filesystem.root_override');
|
||||
$suffixBase = config('tenancy.filesystem.suffix_base');
|
||||
$symlinks = [];
|
||||
|
||||
foreach ($diskUrls as $disk => $publicPath) {
|
||||
$storagePath = str_replace('%storage_path%', $suffixBase . $tenantKey, $disks[$disk]);
|
||||
$storagePath = storage_path($storagePath);
|
||||
|
||||
$publicPath = str_replace('%tenant_id%', $tenantKey, $publicPath);
|
||||
$publicPath = public_path($publicPath);
|
||||
|
||||
$symlinks[] = [$publicPath => $storagePath];
|
||||
}
|
||||
|
||||
return $symlinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the provided path is an existing symlink.
|
||||
*/
|
||||
protected function symlinkExists(string $link): bool
|
||||
{
|
||||
return file_exists($link) && is_link($link);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
43
src/Concerns/DealsWithTenantSymlinks.php
Normal file
43
src/Concerns/DealsWithTenantSymlinks.php
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Stancl\Tenancy\Concerns;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Stancl\Tenancy\Database\Models\Tenant;
|
||||
|
||||
trait DealsWithTenantSymlinks
|
||||
{
|
||||
/**
|
||||
* Get all possible tenant symlinks, existing or not (array of ['public path' => 'storage path']).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function possibleTenantSymlinks(Tenant $tenant): Collection
|
||||
{
|
||||
$diskUrls = config('tenancy.filesystem.url_override');
|
||||
$disks = config('tenancy.filesystem.root_override');
|
||||
$suffixBase = config('tenancy.filesystem.suffix_base');
|
||||
$symlinks = [];
|
||||
$tenantKey = $tenant->getTenantKey();
|
||||
|
||||
foreach ($diskUrls as $disk => $publicPath) {
|
||||
$storagePath = str_replace('%storage_path%', $suffixBase . $tenantKey, $disks[$disk]);
|
||||
$storagePath = storage_path($storagePath);
|
||||
|
||||
$publicPath = str_replace('%tenant_id%', $tenantKey, $publicPath);
|
||||
$publicPath = public_path($publicPath);
|
||||
|
||||
$symlinks[] = [$publicPath => $storagePath];
|
||||
}
|
||||
|
||||
return collect($symlinks)->mapWithKeys(fn($item) => $item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the provided path is an existing symlink.
|
||||
*/
|
||||
protected static function symlinkExists(string $link): bool
|
||||
{
|
||||
return file_exists($link) && is_link($link);
|
||||
}
|
||||
}
|
||||
54
src/CreateStorageSymlinksAction.php
Normal file
54
src/CreateStorageSymlinksAction.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace Stancl\Tenancy;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Stancl\Tenancy\Database\Models\Tenant;
|
||||
use Stancl\Tenancy\Events\StorageSymlinkCreated;
|
||||
use Stancl\Tenancy\Events\CreatingStorageSymlink;
|
||||
use Stancl\Tenancy\Concerns\DealsWithTenantSymlinks;
|
||||
|
||||
class CreateStorageSymlinksAction
|
||||
{
|
||||
use DealsWithTenantSymlinks;
|
||||
|
||||
public static function handle($tenants, bool $relativeLink = false, bool $force = false, Closure|null $afterLinkCreation = null)
|
||||
{
|
||||
$tenants = $tenants instanceof Tenant ? collect([$tenants]) : $tenants;
|
||||
|
||||
/** @var Tenant $tenant */
|
||||
foreach ($tenants as $tenant) {
|
||||
foreach(static::possibleTenantSymlinks($tenant) as $publicPath => $storagePath) {
|
||||
static::createLink($publicPath, $storagePath, $tenant, $relativeLink, $force, $afterLinkCreation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static function createLink(string $publicPath, string $storagePath, Tenant $tenant, bool $relativeLink, bool $force, Closure|null $afterLinkCreation)
|
||||
{
|
||||
event(new CreatingStorageSymlink($tenant));
|
||||
|
||||
if (static::symlinkExists($publicPath)) {
|
||||
// If the 'force' option isn't passed, don't overwrite the existing symlink
|
||||
throw_if(! $force, new Exception("The [$publicPath] link already exists."));
|
||||
|
||||
app()->make('files')->delete($publicPath);
|
||||
}
|
||||
|
||||
// Make sure the storage path exists before we create a symlink
|
||||
if (! is_dir($storagePath)) {
|
||||
mkdir($storagePath, 0777, true);
|
||||
}
|
||||
|
||||
if ($relativeLink) {
|
||||
app()->make('files')->relativeLink($storagePath, $publicPath);
|
||||
} else {
|
||||
app()->make('files')->link($storagePath, $publicPath);
|
||||
}
|
||||
|
||||
event((new StorageSymlinkCreated($tenant)));
|
||||
|
||||
$afterLinkCreation($publicPath, $storagePath);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,10 +9,8 @@ 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\StorageSymlinkCreated;
|
||||
use Stancl\Tenancy\CreateStorageSymlinksAction;
|
||||
|
||||
class CreateStorageSymlinks implements ShouldQueue
|
||||
{
|
||||
|
|
@ -37,12 +35,6 @@ class CreateStorageSymlinks implements ShouldQueue
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
event(new CreatingStorageSymlink($this->tenant));
|
||||
|
||||
Artisan::call('tenants:link', [
|
||||
'--tenants' => [$this->tenant->getTenantKey()],
|
||||
]);
|
||||
|
||||
event(new StorageSymlinkCreated($this->tenant));
|
||||
CreateStorageSymlinksAction::handle($this->tenant);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,14 +5,12 @@ declare(strict_types=1);
|
|||
namespace Stancl\Tenancy\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Stancl\Tenancy\Contracts\Tenant;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
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\RemovingStorageSymlink;
|
||||
use Stancl\Tenancy\Events\StorageSymlinkRemoved;
|
||||
use Stancl\Tenancy\RemoveStorageSymlinksAction;
|
||||
|
||||
class RemoveStorageSymlinks implements ShouldQueue
|
||||
{
|
||||
|
|
@ -37,13 +35,6 @@ class RemoveStorageSymlinks implements ShouldQueue
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
event(new RemovingStorageSymlink($this->tenant));
|
||||
|
||||
Artisan::call('tenants:link', [
|
||||
'--remove' => true,
|
||||
'--tenants' => [$this->tenant->getTenantKey()],
|
||||
]);
|
||||
|
||||
event(new StorageSymlinkRemoved($this->tenant));
|
||||
RemoveStorageSymlinksAction::handle($this->tenant);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
42
src/RemoveStorageSymlinksAction.php
Normal file
42
src/RemoveStorageSymlinksAction.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace Stancl\Tenancy;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Collection;
|
||||
use Stancl\Tenancy\Concerns\DealsWithTenantSymlinks;
|
||||
use Stancl\Tenancy\Database\Models\Tenant;
|
||||
use Stancl\Tenancy\Events\StorageSymlinkRemoved;
|
||||
use Stancl\Tenancy\Events\RemovingStorageSymlink;
|
||||
|
||||
class RemoveStorageSymlinksAction
|
||||
{
|
||||
use DealsWithTenantSymlinks;
|
||||
|
||||
public static function handle($tenants, Closure|null $afterLinkRemoval = null)
|
||||
{
|
||||
$tenants = $tenants instanceof Tenant ? collect([$tenants]) : $tenants;
|
||||
|
||||
/** @var Tenant $tenant */
|
||||
foreach ($tenants as $tenant) {
|
||||
foreach(static::possibleTenantSymlinks($tenant) as $publicPath => $storagePath) {
|
||||
static::removeLink($publicPath, $tenant, $afterLinkRemoval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static function removeLink(string $publicPath, Tenant $tenant, Closure|null $afterLinkRemoval)
|
||||
{
|
||||
if (static::symlinkExists($publicPath)) {
|
||||
event(new RemovingStorageSymlink($tenant));
|
||||
|
||||
app()->make('files')->delete($publicPath);
|
||||
|
||||
event(new StorageSymlinkRemoved($tenant));
|
||||
|
||||
if ($afterLinkRemoval) {
|
||||
$afterLinkRemoval($publicPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue