From 80aca9f9083b64189c097e022a4d4a85b35441cc Mon Sep 17 00:00:00 2001 From: lukinovec Date: Mon, 1 Dec 2025 10:28:58 +0100 Subject: [PATCH 1/2] Make morph maps work with resource syncing Before, morph maps didn't work because in TriggerSyncingTrait, we were trying to get the pivot's `$this->morphClass`. Now, we're first checking if the morph class is an alias, and if it is, resolve its full class name, if it is not, `$this->morphClass` is already the class name, so we can use it. --- src/ResourceSyncing/TriggerSyncingEvents.php | 3 +- tests/ResourceSyncingTest.php | 44 ++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/ResourceSyncing/TriggerSyncingEvents.php b/src/ResourceSyncing/TriggerSyncingEvents.php index 2f8914b5..b3051e2d 100644 --- a/src/ResourceSyncing/TriggerSyncingEvents.php +++ b/src/ResourceSyncing/TriggerSyncingEvents.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Relations\MorphPivot; use Illuminate\Database\Eloquent\Relations\Pivot; use Stancl\Tenancy\Contracts\Tenant; use Stancl\Tenancy\Database\Contracts\TenantWithDatabase; +use Illuminate\Database\Eloquent\Relations\Relation; /** * Used on pivot models. @@ -85,7 +86,7 @@ trait TriggerSyncingEvents } if ($this instanceof MorphPivot) { - return $this->morphClass; + return Relation::getMorphedModel($this->morphClass) ?? $this->morphClass; } throw new CentralResourceNotAvailableInPivotException; diff --git a/tests/ResourceSyncingTest.php b/tests/ResourceSyncingTest.php index 826ed780..baf0e9c8 100644 --- a/tests/ResourceSyncingTest.php +++ b/tests/ResourceSyncingTest.php @@ -52,6 +52,7 @@ use Stancl\Tenancy\Events\TenantDeleted; use Stancl\Tenancy\ResourceSyncing\Events\SyncedResourceDeleted; use Stancl\Tenancy\ResourceSyncing\Listeners\DeleteAllTenantMappings; use Stancl\Tenancy\ResourceSyncing\Listeners\DeleteResourceMapping; +use Illuminate\Database\Eloquent\Relations\Relation; beforeEach(function () { config(['tenancy.bootstrappers' => [ @@ -1364,6 +1365,49 @@ test('global scopes on syncable models can break resource syncing', function () expect($tenant1->run(fn () => TenantUser::first()->name))->toBe('tenant2 user'); }); +test('attach and detach events are handled correctly when using morph maps', function() { + config(['tenancy.models.tenant' => MorphTenant::class]); + [$tenant] = createTenantsAndRunMigrations(); + migrateCompaniesTableForTenants(); + + Relation::morphMap([ + 'users' => BaseCentralUser::class, + 'companies' => CentralCompany::class, + ]); + + $centralUser = BaseCentralUser::create([ + 'global_id' => 'user', + 'name' => 'Central user', + 'email' => 'central@localhost', + 'password' => 'password', + 'role' => 'user', + ]); + + $centralCompany = CentralCompany::create([ + 'global_id' => 'company', + 'name' => 'Central company', + 'email' => 'company@localhost', + ]); + + $tenant->users()->attach($centralUser); + $tenant->companies()->attach($centralCompany); + + tenancy()->initialize($tenant); + + expect(BaseTenantUser::whereGlobalId('user')->first())->not()->toBeNull(); + expect(TenantCompany::whereGlobalId('company')->first())->not()->toBeNull(); + + tenancy()->end(); + + $tenant->users()->detach($centralUser); + $tenant->companies()->detach($centralCompany); + + tenancy()->initialize($tenant); + + expect(BaseTenantUser::whereGlobalId('user')->first())->toBeNull(); + expect(TenantCompany::whereGlobalId('company')->first())->toBeNull(); +}); + function addTenantIdConstraintToPivot(string $pivotTable): void { Schema::table($pivotTable, function (Blueprint $table) { From e85ee25abc0029bed64d5a3148e08ee3845ad128 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 1 Dec 2025 10:26:07 +0000 Subject: [PATCH 2/2] Fix code style (php-cs-fixer) --- src/ResourceSyncing/TriggerSyncingEvents.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResourceSyncing/TriggerSyncingEvents.php b/src/ResourceSyncing/TriggerSyncingEvents.php index b3051e2d..059eb579 100644 --- a/src/ResourceSyncing/TriggerSyncingEvents.php +++ b/src/ResourceSyncing/TriggerSyncingEvents.php @@ -7,9 +7,9 @@ namespace Stancl\Tenancy\ResourceSyncing; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphPivot; use Illuminate\Database\Eloquent\Relations\Pivot; +use Illuminate\Database\Eloquent\Relations\Relation; use Stancl\Tenancy\Contracts\Tenant; use Stancl\Tenancy\Database\Contracts\TenantWithDatabase; -use Illuminate\Database\Eloquent\Relations\Relation; /** * Used on pivot models.