From 2839f45196981451d7acb017fe866c4ab8967a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C5=A0tancl?= Date: Sun, 24 May 2020 20:40:10 +0200 Subject: [PATCH] Refactor models & config --- assets/TenancyServiceProvider.stub.php | 2 +- assets/config.php | 44 +++++++-------- .../Concerns/EnsuresDomainIsNotOccupied.php | 19 +++++++ src/Database/Concerns/GeneratesIds.php | 9 +++- src/Database/Concerns/HasInternalKeys.php | 32 +++++++++++ src/Database/Concerns/TenantRun.php | 26 +++++++++ src/Database/Models/Domain.php | 31 +++-------- src/Database/Models/Tenant.php | 53 +++---------------- tests/TenantDatabaseManagerTest.php | 4 -- 9 files changed, 123 insertions(+), 97 deletions(-) create mode 100644 src/Database/Concerns/EnsuresDomainIsNotOccupied.php create mode 100644 src/Database/Concerns/HasInternalKeys.php create mode 100644 src/Database/Concerns/TenantRun.php diff --git a/assets/TenancyServiceProvider.stub.php b/assets/TenancyServiceProvider.stub.php index ddaf84bb..93de0346 100644 --- a/assets/TenancyServiceProvider.stub.php +++ b/assets/TenancyServiceProvider.stub.php @@ -110,7 +110,7 @@ class TenancyServiceProvider extends ServiceProvider protected function mapRoutes() { if (file_exists(base_path('routes/tenant.php'))) { - Route::namespace($this->app['config']['tenancy.tenant_route_namespace'] ?? 'App\Http\Controllers') + Route::namespace('App\Http\Controllers') ->group(base_path('routes/tenant.php')); } } diff --git a/assets/config.php b/assets/config.php index 4e944b84..67cd0da1 100644 --- a/assets/config.php +++ b/assets/config.php @@ -7,20 +7,20 @@ use Stancl\Tenancy\Database\Models\Tenant; return [ 'tenant_model' => Tenant::class, - 'internal_prefix' => 'tenancy_', 'id_generator' => Stancl\Tenancy\UUIDGenerator::class, 'domain_model' => Domain::class, + + /** + * The list of domains hosting your central app. + * + * Only relevant if you're using the domain or subdomain identification middleware. + */ 'central_domains' => [ '127.0.0.1', 'localhost', ], - /** - * Controller namespace used by routes in routes/tenant.php. - */ - 'tenant_route_namespace' => 'App\Http\Controllers', - /** * Tenancy bootstrappers are executed when tenancy is initialized. * Their responsibility is making Laravel features tenant-aware. @@ -75,22 +75,6 @@ return [ ], ], - /** - * Redis tenancy config. Used by RedisTenancyBoostrapper. - * - * Note: You need phpredis to use Redis tenancy. - * - * Note: You don't need to use this if you're using Redis only for cache. - * Redis tenancy is only relevant if you're making direct Redis calls, - * either using the Redis facade or by injecting it as a dependency. - */ - 'redis' => [ - 'prefix_base' => 'tenant', // Each key in Redis will be prepended by this prefix_base, followed by the tenant id. - 'prefixed_connections' => [ // Redis connections whose keys are prefixed, to separate one tenant's keys from another. - // 'default', - ], - ], - /** * Cache tenancy config. Used by CacheTenancyBootstrapper. * @@ -151,6 +135,22 @@ return [ 'asset_helper_tenancy' => true, ], + /** + * Redis tenancy config. Used by RedisTenancyBoostrapper. + * + * Note: You need phpredis to use Redis tenancy. + * + * Note: You don't need to use this if you're using Redis only for cache. + * Redis tenancy is only relevant if you're making direct Redis calls, + * either using the Redis facade or by injecting it as a dependency. + */ + 'redis' => [ + 'prefix_base' => 'tenant', // Each key in Redis will be prepended by this prefix_base, followed by the tenant id. + 'prefixed_connections' => [ // Redis connections whose keys are prefixed, to separate one tenant's keys from another. + // 'default', + ], + ], + /** * Features are classes that provide additional functionality * not needed for tenancy to be bootstrapped. They are run diff --git a/src/Database/Concerns/EnsuresDomainIsNotOccupied.php b/src/Database/Concerns/EnsuresDomainIsNotOccupied.php new file mode 100644 index 00000000..a63e2c00 --- /dev/null +++ b/src/Database/Concerns/EnsuresDomainIsNotOccupied.php @@ -0,0 +1,19 @@ +newQuery()->where('domain', $self->domain)->first()) { + if ($domain->getKey() !== $self->getKey()) { + throw new DomainOccupiedByOtherTenantException($self->domain); + } + } + }); + } +} diff --git a/src/Database/Concerns/GeneratesIds.php b/src/Database/Concerns/GeneratesIds.php index 3ac8802e..fe0e2ec9 100644 --- a/src/Database/Concerns/GeneratesIds.php +++ b/src/Database/Concerns/GeneratesIds.php @@ -11,7 +11,7 @@ trait GeneratesIds public static function bootGeneratesIds() { static::creating(function (self $model) { - if (! $model->getTenantKey() && app()->bound(UniqueIdentifierGenerator::class)) { + if (! $model->getTenantKey() && $model->shouldGenerateId()) { $model->setAttribute($model->getTenantKeyName(), app(UniqueIdentifierGenerator::class)->generate($model)); } }); @@ -19,6 +19,11 @@ trait GeneratesIds public function getIncrementing() { - return ! app()->bound(UniqueIdentifierGenerator::class); + return ! $this->shouldGenerateId(); + } + + public function shouldGenerateId(): bool + { + return app()->bound(UniqueIdentifierGenerator::class); } } diff --git a/src/Database/Concerns/HasInternalKeys.php b/src/Database/Concerns/HasInternalKeys.php new file mode 100644 index 00000000..1ddf5846 --- /dev/null +++ b/src/Database/Concerns/HasInternalKeys.php @@ -0,0 +1,32 @@ +getAttribute(static::internalPrefix() . $key); + } + + /** + * Set internal key. + */ + public function setInternal(string $key, $value) + { + $this->setAttribute(static::internalPrefix() . $key, $value); + + return $this; + } +} \ No newline at end of file diff --git a/src/Database/Concerns/TenantRun.php b/src/Database/Concerns/TenantRun.php new file mode 100644 index 00000000..36cf44e5 --- /dev/null +++ b/src/Database/Concerns/TenantRun.php @@ -0,0 +1,26 @@ +initialize($this); + $result = $callback($this); + + if ($originalTenant) { + tenancy()->initialize($originalTenant); + } else { + tenancy()->end(); + } + + return $result; + } +} diff --git a/src/Database/Models/Domain.php b/src/Database/Models/Domain.php index 1895078f..2a6099b1 100644 --- a/src/Database/Models/Domain.php +++ b/src/Database/Models/Domain.php @@ -7,9 +7,8 @@ namespace Stancl\Tenancy\Database\Models; use Illuminate\Database\Eloquent\Model; use Stancl\Tenancy\Contracts; use Stancl\Tenancy\Contracts\Tenant; -use Stancl\Tenancy\Database\Concerns\CentralConnection; +use Stancl\Tenancy\Database\Concerns; use Stancl\Tenancy\Events; -use Stancl\Tenancy\Exceptions\DomainOccupiedByOtherTenantException; /** * @property string $domain @@ -19,38 +18,24 @@ use Stancl\Tenancy\Exceptions\DomainOccupiedByOtherTenantException; */ class Domain extends Model implements Contracts\Domain { - use CentralConnection; + use Concerns\CentralConnection, + Concerns\EnsuresDomainIsNotOccupied; protected $guarded = []; - public static function boot() - { - parent::boot(); - - $ensureDomainIsNotOccupied = function (self $self) { - if ($domain = self::where('domain', $self->domain)->first()) { - if ($domain->getKey() !== $self->getKey()) { - throw new DomainOccupiedByOtherTenantException($self->domain); - } - } - }; - - static::saving($ensureDomainIsNotOccupied); - } - public function tenant() { return $this->belongsTo(config('tenancy.tenant_model')); } - public $dispatchesEvents = [ - 'saved' => Events\DomainSaved::class, + protected $dispatchesEvents = [ 'saving' => Events\SavingDomain::class, - 'created' => Events\DomainCreated::class, + 'saved' => Events\DomainSaved::class, 'creating' => Events\CreatingDomain::class, - 'updated' => Events\DomainUpdated::class, + 'created' => Events\DomainCreated::class, 'updating' => Events\UpdatingDomain::class, - 'deleted' => Events\DomainDeleted::class, + 'updated' => Events\DomainUpdated::class, 'deleting' => Events\DeletingDomain::class, + 'deleted' => Events\DomainDeleted::class, ]; } diff --git a/src/Database/Models/Tenant.php b/src/Database/Models/Tenant.php index 070d1d2e..8032716f 100644 --- a/src/Database/Models/Tenant.php +++ b/src/Database/Models/Tenant.php @@ -23,7 +23,9 @@ class Tenant extends Model implements Contracts\Tenant { use Concerns\CentralConnection, Concerns\GeneratesIds, - Concerns\HasDataColumn; + Concerns\HasDataColumn, + Concerns\HasInternalKeys, + Concerns\TenantRun; protected $table = 'tenants'; protected $primaryKey = 'id'; @@ -44,53 +46,14 @@ class Tenant extends Model implements Contracts\Tenant return new TenantCollection($models); } - public static function internalPrefix(): string - { - return config('tenancy.internal_prefix'); - } - - /** - * Get an internal key. - */ - public function getInternal(string $key) - { - return $this->getAttribute(static::internalPrefix() . $key); - } - - /** - * Set internal key. - */ - public function setInternal(string $key, $value) - { - $this->setAttribute(static::internalPrefix() . $key, $value); - - return $this; - } - - public function run(callable $callback) - { - $originalTenant = tenant(); - - tenancy()->initialize($this); - $result = $callback($this); - - if ($originalTenant) { - tenancy()->initialize($originalTenant); - } else { - tenancy()->end(); - } - - return $result; - } - - public $dispatchesEvents = [ - 'saved' => Events\TenantSaved::class, + protected $dispatchesEvents = [ 'saving' => Events\SavingTenant::class, - 'created' => Events\TenantCreated::class, + 'saved' => Events\TenantSaved::class, 'creating' => Events\CreatingTenant::class, - 'updated' => Events\TenantUpdated::class, + 'created' => Events\TenantCreated::class, 'updating' => Events\UpdatingTenant::class, - 'deleted' => Events\TenantDeleted::class, + 'updated' => Events\TenantUpdated::class, 'deleting' => Events\DeletingTenant::class, + 'deleted' => Events\TenantDeleted::class, ]; } diff --git a/tests/TenantDatabaseManagerTest.php b/tests/TenantDatabaseManagerTest.php index fa4c9312..5bf139d4 100644 --- a/tests/TenantDatabaseManagerTest.php +++ b/tests/TenantDatabaseManagerTest.php @@ -36,7 +36,6 @@ class TenantDatabaseManagerTest extends TestCase config()->set([ "tenancy.database.managers.$driver" => $databaseManager, - 'tenancy.internal_prefix' => 'tenancy_', ]); $name = 'db' . $this->randomString(); @@ -65,8 +64,6 @@ class TenantDatabaseManagerTest extends TestCase return $event->tenant; })->toListener()); - config(['tenancy.internal_prefix' => 'tenancy_']); - $database = 'db' . $this->randomString(); $mysqlmanager = app(MySQLDatabaseManager::class); @@ -113,7 +110,6 @@ class TenantDatabaseManagerTest extends TestCase } config([ 'database.connections.fooconn.driver' => 'sqlite', - 'tenancy.internal_prefix' => 'tenancy_', ]); $tenant = Tenant::create([