diff --git a/src/ResourceSyncing/TriggerSyncingEvents.php b/src/ResourceSyncing/TriggerSyncingEvents.php index 059eb5793..b59a95502 100644 --- a/src/ResourceSyncing/TriggerSyncingEvents.php +++ b/src/ResourceSyncing/TriggerSyncingEvents.php @@ -22,13 +22,14 @@ trait TriggerSyncingEvents public static function bootTriggerSyncingEvents(): void { static::saving(static function (self $pivot) { - // Try getting the central resource to see if it is available - // If it is not available, throw an exception to interrupt the saving process - // And prevent creating a pivot record without a central resource + // Try getting the central resource to see if it is available. + // If it is not, getCentralResourceAndTenant() throws (indirectly, via findCentralResource() -> getResourceClass()), + // interrupting the save, preventing the creation of a pivot record without a central resource. $pivot->getCentralResourceAndTenant(); }); - static::saved(static function (self $pivot) { + // Only attach when the pivot is created + static::created(static function (self $pivot) { /** * @var static&Pivot $pivot * @var SyncMaster|null $centralResource @@ -55,6 +56,10 @@ public static function bootTriggerSyncingEvents(): void }); } + /** + * @throws CentralResourceNotAvailableInPivotException Throws when the tenant is the pivot parent + * but the central resource class cannot be resolved (thrown indirectly via findCentralResource() -> getResourceClass()) + */ public function getCentralResourceAndTenant(): array { /** @var $this&Pivot $this */ diff --git a/tests/ResourceSyncingTest.php b/tests/ResourceSyncingTest.php index 11a172c50..e971b6b54 100644 --- a/tests/ResourceSyncingTest.php +++ b/tests/ResourceSyncingTest.php @@ -274,6 +274,32 @@ }); }); +test('updating pivot column does not re-create the synced tenant resource', function () { + // Add an extra pivot column so we can update it + Schema::table('tenant_users', fn (Blueprint $table) => $table->string('note')->nullable()); + + $centralUser = CentralUser::create([ + 'global_id' => 'acme', + 'name' => 'John Doe', + 'email' => 'john@localhost', + 'password' => 'secret', + 'role' => 'commenter', + ]); + + $tenant = Tenant::create(); + migrateUsersTableForTenants(); + + // Attaching creates the tenant resource + $centralUser->tenants()->attach($tenant); + $tenant->run(fn () => expect(TenantUser::count())->toBe(1)); + + // Updating a pivot column does not re-attach and create the resource again + // (which would throw a duplicate entry error -- regression test for #1467) + $centralUser->tenants()->updateExistingPivot($tenant->getTenantKey(), ['note' => 'foo']); + + $tenant->run(fn () => expect(TenantUser::count())->toBe(1)); +}); + test('detaching central users from tenants or vice versa force deletes the synced tenant resource', function (bool $attachUserToTenant) { $centralUser = CentralUser::create([ 'global_id' => 'acme',