1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2026-02-05 18:34:04 +00:00

code improvements

This commit is contained in:
Samuel Štancl 2022-09-29 17:01:27 +02:00
parent 8aea33c0f2
commit c62dc0f0f3
3 changed files with 16 additions and 17 deletions

View file

@ -16,8 +16,6 @@ interface Syncable
public function triggerSyncEvent(): void; public function triggerSyncEvent(): void;
/** /** Get the attributes used for creating the *other* model (i.e. tenant if this is the central one, and central if this is the tenant one). */
* Get the attributes used for creating the *other* model (i.e. tenant if this is the central one, and central if this is the tenant one).
*/
public function getSyncedCreationAttributes(): array|null; // todo come up with a better name public function getSyncedCreationAttributes(): array|null; // todo come up with a better name
} }

View file

@ -10,6 +10,8 @@ use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Stancl\Tenancy\Contracts\Syncable; use Stancl\Tenancy\Contracts\Syncable;
use Stancl\Tenancy\Contracts\SyncMaster; use Stancl\Tenancy\Contracts\SyncMaster;
use Stancl\Tenancy\Contracts\Tenant;
use Stancl\Tenancy\Database\TenantCollection;
use Stancl\Tenancy\Events\SyncedResourceChangedInForeignDatabase; use Stancl\Tenancy\Events\SyncedResourceChangedInForeignDatabase;
use Stancl\Tenancy\Events\SyncedResourceSaved; use Stancl\Tenancy\Events\SyncedResourceSaved;
use Stancl\Tenancy\Exceptions\ModelNotSyncMasterException; use Stancl\Tenancy\Exceptions\ModelNotSyncMasterException;
@ -32,14 +34,14 @@ class UpdateSyncedResource extends QueueableListener
$this->updateResourceInTenantDatabases($tenants, $event, $syncedAttributes); $this->updateResourceInTenantDatabases($tenants, $event, $syncedAttributes);
} }
protected function getTenantsForCentralModel($centralModel): EloquentCollection protected function getTenantsForCentralModel($centralModel): TenantCollection
{ {
if (! $centralModel instanceof SyncMaster) { if (! $centralModel instanceof SyncMaster) {
// If we're trying to use a tenant User model instead of the central User model, for example. // If we're trying to use a tenant User model instead of the central User model, for example.
throw new ModelNotSyncMasterException(get_class($centralModel)); throw new ModelNotSyncMasterException(get_class($centralModel));
} }
/** @var SyncMaster|Model $centralModel */ /** @var Tenant&Model&SyncMaster $centralModel */
// Since this model is "dirty" (taken by reference from the event), it might have the tenants // Since this model is "dirty" (taken by reference from the event), it might have the tenants
// relationship already loaded and cached. For this reason, we refresh the relationship. // relationship already loaded and cached. For this reason, we refresh the relationship.
@ -48,7 +50,7 @@ class UpdateSyncedResource extends QueueableListener
return $centralModel->tenants; return $centralModel->tenants;
} }
protected function updateResourceInCentralDatabaseAndGetTenants($event, $syncedAttributes): EloquentCollection protected function updateResourceInCentralDatabaseAndGetTenants($event, array $syncedAttributes): TenantCollection
{ {
/** @var Model|SyncMaster $centralModel */ /** @var Model|SyncMaster $centralModel */
$centralModel = $event->model->getCentralModelName()::where($event->model->getGlobalIdentifierKeyName(), $event->model->getGlobalIdentifierKey()) $centralModel = $event->model->getCentralModelName()::where($event->model->getGlobalIdentifierKeyName(), $event->model->getGlobalIdentifierKey())
@ -87,12 +89,13 @@ class UpdateSyncedResource extends QueueableListener
}); });
} }
protected function updateResourceInTenantDatabases($tenants, $event, $syncedAttributes): void protected function updateResourceInTenantDatabases($tenants, $event, array $syncedAttributes): void
{ {
tenancy()->runForMultiple($tenants, function ($tenant) use ($event, $syncedAttributes) { tenancy()->runForMultiple($tenants, function ($tenant) use ($event, $syncedAttributes) {
// Forget instance state and find the model, // Forget instance state and find the model,
// again in the current tenant's context. // again in the current tenant's context.
/** @var Model&Syncable $eventModel */
$eventModel = $event->model; $eventModel = $event->model;
if ($eventModel instanceof SyncMaster) { if ($eventModel instanceof SyncMaster) {
@ -121,7 +124,7 @@ class UpdateSyncedResource extends QueueableListener
}); });
} }
protected function getAttributesForCreation(Syncable $model): array protected function getAttributesForCreation(Model&Syncable $model): array
{ {
if (! $model->getSyncedCreationAttributes()) { if (! $model->getSyncedCreationAttributes()) {
// Creation attributes are not specified so create the model as 1:1 copy // Creation attributes are not specified so create the model as 1:1 copy
@ -143,7 +146,7 @@ class UpdateSyncedResource extends QueueableListener
/** /**
* Split the attribute names (sequential index items) and default values (key => values). * Split the attribute names (sequential index items) and default values (key => values).
*/ */
protected function getAttributeNamesAndDefaultValues(Syncable $model): array protected function getAttributeNamesAndDefaultValues(Model&Syncable $model): array
{ {
$syncedCreationAttributes = $model->getSyncedCreationAttributes(); $syncedCreationAttributes = $model->getSyncedCreationAttributes();

View file

@ -4,11 +4,9 @@ declare(strict_types=1);
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Events\CallQueuedListener; use Illuminate\Events\CallQueuedListener;
use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Stancl\JobPipeline\JobPipeline; use Stancl\JobPipeline\JobPipeline;
use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper; use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper;
@ -46,10 +44,10 @@ 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);
UpdateSyncedResource::$shouldQueue = false; // global state cleanup UpdateSyncedResource::$shouldQueue = false; // Global state cleanup
Event::listen(SyncedResourceSaved::class, UpdateSyncedResource::class); Event::listen(SyncedResourceSaved::class, UpdateSyncedResource::class);
// run migrations on central connection // Run migrations on central connection
pest()->artisan('migrate', [ pest()->artisan('migrate', [
'--path' => [ '--path' => [
__DIR__ . '/Etc/synced_resource_migrations', __DIR__ . '/Etc/synced_resource_migrations',
@ -129,7 +127,7 @@ test('only the synced columns are updated in the central db', function () {
], ResourceUser::first()->getAttributes()); ], ResourceUser::first()->getAttributes());
}); });
test('creating the resource in tenant database creates it in central database as 1:1 copy when creation attributes are not specified', function () { test('creating the resource in tenant database creates it in central database as a direct copy when creation attributes are not specified', function () {
// Assert no user exists in central DB // Assert no user exists in central DB
expect(ResourceUser::all())->toHaveCount(0); expect(ResourceUser::all())->toHaveCount(0);
@ -154,7 +152,7 @@ test('creating the resource in tenant database creates it in central database as
expect(CentralUser::first()->toArray())->toEqual(ResourceUser::first()->toArray()); expect(CentralUser::first()->toArray())->toEqual(ResourceUser::first()->toArray());
}); });
test('creating the resource in tenant database creates it in central database with default attributes values', function () { test('creating the resource in tenant database creates it in central database with default attribute values', function () {
// Assert no user exists in central DB // Assert no user exists in central DB
expect(ResourceUserWithDefaultValues::all())->toHaveCount(0); expect(ResourceUserWithDefaultValues::all())->toHaveCount(0);
@ -246,7 +244,7 @@ test('creating the resource in tenant database creates it in central database wi
expect(CentralUser::first()->role)->toBe('admin'); // unsynced so it should be default value expect(CentralUser::first()->role)->toBe('admin'); // unsynced so it should be default value
}); });
test('creating the resource in central database creates it in tenant database as 1:1 copy when creation attributes are not specified', function () { test('creating the resource in central database creates it in tenant database as direct copy when creation attributes are not specified', function () {
$centralUser = CentralUser::create([ $centralUser = CentralUser::create([
'global_id' => 'acme', 'global_id' => 'acme',
'name' => 'John Doe', 'name' => 'John Doe',