1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-13 20:04:05 +00:00

Compare commits

..

2 commits

Author SHA1 Message Date
3974ad046e
Syncing: move global ID generation logic to an overridable method
Also make all resource syncing-related listener closures static.

Also correct return type for getGlobalIdentifierKey to string|int.
(We intentionally do not support returning null like many other
"get x key" methods would since such a case might break resource
syncing logic. This is also why we use inline getAttribute() in the
creating listener instead of calling the method.)
2025-11-21 02:03:36 +01:00
lukinovec
cfae527c93 Syncing: Add DeleteAllTenantMappings listener 2025-11-21 02:03:36 +01:00
2 changed files with 20 additions and 10 deletions

View file

@ -9,30 +9,40 @@ use Stancl\Tenancy\Events\TenantDeleted;
use Stancl\Tenancy\Listeners\QueueableListener; use Stancl\Tenancy\Listeners\QueueableListener;
/** /**
* Cleans up pivot records related to the deleted tenant. * Clean up pivot records related to the deleted tenant.
*
* The listener only cleans up the pivot tables specified * The listener only cleans up the pivot tables specified
* in the $pivotTables property (see the property for details), * in the $pivotTables property (see the property for details),
* and is intended for use with tables that do not have tenant * and is intended for use with tables that do not have tenant foreign key constraints.
* foreign key constraints with onDelete('cascade'). *
* When using foreign key constraints, you'll still have to use ->onDelete('cascade')
* on the constraint (otherwise, deleting a tenant will throw a foreign key constraint violation).
* That way, the cleanup will happen on the database level, and this listener will essentially
* just perform an extra 'where' query.
*/ */
class DeleteAllTenantMappings extends QueueableListener class DeleteAllTenantMappings extends QueueableListener
{ {
/** /**
* Pivot tables to clean up after a tenant is deleted, in the * Pivot tables to clean up after a tenant is deleted,
* ['table_name' => 'tenant_key_column'] format. * formatted like ['table_name' => 'tenant_key_column'].
* *
* Since we cannot automatically detect which pivot tables * Since we cannot automatically detect which pivot tables
* are being used, they have to be specified here manually. * you want to clean up, they have to be specified here.
* *
* The default value follows the polymorphic table used by default. * By default, resource syncing uses the tenant_resources table, and the records are associated
* to tenants by the tenant_id column (thus the ['tenant_resources' => 'tenant_id'] default).
*
* To customize this, set this property, e.g. in TenancyServiceProvider:
* DeleteAllTenantMappings::$pivotTables = [
* 'tenant_users' => 'tenant_id',
* // You can also add more pivot tables here
* ];
*/ */
public static array $pivotTables = ['tenant_resources' => 'tenant_id']; public static array $pivotTables = ['tenant_resources' => 'tenant_id'];
public function handle(TenantDeleted $event): void public function handle(TenantDeleted $event): void
{ {
foreach (static::$pivotTables as $table => $tenantKeyColumn) { foreach (static::$pivotTables as $table => $tenantKeyColumn) {
DB::table($table)->where($tenantKeyColumn, $event->tenant->getKey())->delete(); DB::table($table)->where($tenantKeyColumn, $event->tenant->getTenantKey())->delete();
} }
} }
} }

View file

@ -898,7 +898,7 @@ test('deleting SyncMaster automatically deletes its Syncables', function (bool $
'basic pivot' => false, 'basic pivot' => false,
]); ]);
test('tenant pivot records are deleted along with the tenants to which they belong', function (bool $dbLevelOnCascadeDelete, bool $morphPivot) { test('tenant pivot records are deleted along with the tenants to which they belong to', function (bool $dbLevelOnCascadeDelete, bool $morphPivot) {
[$tenant] = createTenantsAndRunMigrations(); [$tenant] = createTenantsAndRunMigrations();
if ($morphPivot) { if ($morphPivot) {