diff --git a/src/Contracts/Syncable.php b/src/Contracts/Syncable.php index 6d2fad85..a481f318 100644 --- a/src/Contracts/Syncable.php +++ b/src/Contracts/Syncable.php @@ -16,8 +16,6 @@ interface Syncable 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 } diff --git a/src/Listeners/UpdateSyncedResource.php b/src/Listeners/UpdateSyncedResource.php index 155465b0..196b53f2 100644 --- a/src/Listeners/UpdateSyncedResource.php +++ b/src/Listeners/UpdateSyncedResource.php @@ -10,6 +10,8 @@ use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Support\Arr; use Stancl\Tenancy\Contracts\Syncable; use Stancl\Tenancy\Contracts\SyncMaster; +use Stancl\Tenancy\Contracts\Tenant; +use Stancl\Tenancy\Database\TenantCollection; use Stancl\Tenancy\Events\SyncedResourceChangedInForeignDatabase; use Stancl\Tenancy\Events\SyncedResourceSaved; use Stancl\Tenancy\Exceptions\ModelNotSyncMasterException; @@ -32,14 +34,14 @@ class UpdateSyncedResource extends QueueableListener $this->updateResourceInTenantDatabases($tenants, $event, $syncedAttributes); } - protected function getTenantsForCentralModel($centralModel): EloquentCollection + protected function getTenantsForCentralModel($centralModel): TenantCollection { if (! $centralModel instanceof SyncMaster) { // If we're trying to use a tenant User model instead of the central User model, for example. 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 // relationship already loaded and cached. For this reason, we refresh the relationship. @@ -48,7 +50,7 @@ class UpdateSyncedResource extends QueueableListener return $centralModel->tenants; } - protected function updateResourceInCentralDatabaseAndGetTenants($event, $syncedAttributes): EloquentCollection + protected function updateResourceInCentralDatabaseAndGetTenants($event, array $syncedAttributes): TenantCollection { /** @var Model|SyncMaster $centralModel */ $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) { // Forget instance state and find the model, // again in the current tenant's context. + /** @var Model&Syncable $eventModel */ $eventModel = $event->model; 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()) { // 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). */ - protected function getAttributeNamesAndDefaultValues(Syncable $model): array + protected function getAttributeNamesAndDefaultValues(Model&Syncable $model): array { $syncedCreationAttributes = $model->getSyncedCreationAttributes(); diff --git a/tests/ResourceSyncingTest.php b/tests/ResourceSyncingTest.php index 683e5b42..68b08161 100644 --- a/tests/ResourceSyncingTest.php +++ b/tests/ResourceSyncingTest.php @@ -4,11 +4,9 @@ declare(strict_types=1); use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; -use Illuminate\Database\Schema\Blueprint; use Illuminate\Events\CallQueuedListener; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Queue; -use Illuminate\Support\Facades\Schema; use Illuminate\Support\Str; use Stancl\JobPipeline\JobPipeline; use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper; @@ -46,10 +44,10 @@ beforeEach(function () { Event::listen(TenancyInitialized::class, BootstrapTenancy::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); - // run migrations on central connection + // Run migrations on central connection pest()->artisan('migrate', [ '--path' => [ __DIR__ . '/Etc/synced_resource_migrations', @@ -129,7 +127,7 @@ test('only the synced columns are updated in the central db', function () { ], 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 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()); }); -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 expect(ResourceUserWithDefaultValues::all())->toHaveCount(0); @@ -244,9 +242,9 @@ test('creating the resource in tenant database creates it in central database wi expect(CentralUser::first()->password)->toBe('secret'); expect(CentralUser::first()->code)->toBeNull(); 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([ 'global_id' => 'acme', 'name' => 'John Doe',