1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-12 06:44:04 +00:00
tenancy/src/ResourceSyncing/ResourceSyncing.php
Samuel Stancl 87368e36d6
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-22 03:30:42 +01:00

133 lines
4.4 KiB
PHP

<?php
declare(strict_types=1);
namespace Stancl\Tenancy\ResourceSyncing;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
use Stancl\Tenancy\Database\Contracts\TenantWithDatabase;
use Stancl\Tenancy\ResourceSyncing\Events\CentralResourceAttachedToTenant;
use Stancl\Tenancy\ResourceSyncing\Events\CentralResourceDetachedFromTenant;
use Stancl\Tenancy\ResourceSyncing\Events\SyncedResourceDeleted;
use Stancl\Tenancy\ResourceSyncing\Events\SyncedResourceSaved;
use Stancl\Tenancy\ResourceSyncing\Events\SyncMasterDeleted;
use Stancl\Tenancy\ResourceSyncing\Events\SyncMasterRestored;
trait ResourceSyncing
{
public static function bootResourceSyncing(): void
{
static::saved(static function (Syncable&Model $model) {
if ($model->shouldSync() && ($model->wasRecentlyCreated || $model->wasChanged($model->getSyncedAttributeNames()))) {
$model->triggerSyncEvent();
}
});
static::deleted(static function (Syncable&Model $model) {
if ($model->shouldSync()) {
$model->triggerDeleteEvent();
}
});
static::creating(static function (Syncable&Model $model) {
if (! $model->getAttribute($model->getGlobalIdentifierKeyName())) {
$model->generateGlobalIdentifierKey();
}
});
if (in_array(SoftDeletes::class, class_uses_recursive(static::class), true)) {
static::forceDeleting(static function (Syncable&Model $model) {
if ($model->shouldSync()) {
$model->triggerDeleteEvent(true);
}
});
static::restoring(static function (Syncable&Model $model) {
if ($model instanceof SyncMaster && $model->shouldSync()) {
$model->triggerRestoreEvent();
}
});
}
}
public function triggerSyncEvent(): void
{
/** @var Syncable&Model $this */
event(new SyncedResourceSaved($this, tenant()));
}
public function triggerDeleteEvent(bool $forceDelete = false): void
{
if ($this instanceof SyncMaster) {
/** @var SyncMaster&Model $this */
event(new SyncMasterDeleted($this, $forceDelete));
}
event(new SyncedResourceDeleted($this, tenant(), $forceDelete));
}
public function triggerRestoreEvent(): void
{
if ($this instanceof SyncMaster && in_array(SoftDeletes::class, class_uses_recursive($this), true)) {
/** @var SyncMaster&Model $this */
event(new SyncMasterRestored($this));
}
}
/** Default implementation for \Stancl\Tenancy\ResourceSyncing\SyncMaster */
public function triggerAttachEvent(TenantWithDatabase&Model $tenant): void
{
if ($this instanceof SyncMaster) {
/** @var SyncMaster&Model $this */
event(new CentralResourceAttachedToTenant($this, $tenant));
}
}
/** Default implementation for \Stancl\Tenancy\ResourceSyncing\SyncMaster */
public function triggerDetachEvent(TenantWithDatabase&Model $tenant): void
{
if ($this instanceof SyncMaster) {
/** @var SyncMaster&Model $this */
event(new CentralResourceDetachedFromTenant($this, $tenant));
}
}
public function getCreationAttributes(): array
{
return $this->getSyncedAttributeNames();
}
public function shouldSync(): bool
{
return true;
}
public function tenants(): BelongsToMany
{
return $this->morphToMany(config('tenancy.models.tenant'), 'tenant_resources', 'tenant_resources', 'resource_global_id', 'tenant_id', $this->getGlobalIdentifierKeyName())
->using(TenantMorphPivot::class);
}
public function getGlobalIdentifierKeyName(): string
{
return 'global_id';
}
public function getGlobalIdentifierKey(): string|int
{
return $this->getAttribute($this->getGlobalIdentifierKeyName());
}
protected function generateGlobalIdentifierKey(): void
{
if (! app()->bound(UniqueIdentifierGenerator::class)) return;
$this->setAttribute(
$this->getGlobalIdentifierKeyName(),
app(UniqueIdentifierGenerator::class)->generate($this),
);
}
}