mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 08:04:03 +00:00
Use polymorphic table for mapping resources to tenants (#997)
* wip * Fix code style (php-cs-fixer) * adjust tests * Update ResourceSyncingPolymorphicTest.php * Update SyncMaster.php * correct method name * Update ResourceSyncingPolymorphicTest.php * use BelongsToMany return type * separate pivot model for each approach * ability to publish migrations * remove unsed import * use resource migrations from asset * anonymous migration for `tenant_resources` table * rename file * rename classes * trait * add back using statement * revert to unset change * use unset approach * use unset approach * Assert `tenants` are accessible * Update ResourceSyncingUsingPolymorphicTest.php * improve `tenants` assertions * improve assertions * remove `getResourceTenantModelName` method and use config * use `BelongsToMany` for `tenants` method return type * Fix code style (php-cs-fixer) * revert type * use correct key * test right resources are accessible from the tenant * Update tests/ResourceSyncingUsingPolymorphicTest.php --------- Co-authored-by: PHP CS Fixer <phpcsfixer@example.com> Co-authored-by: Samuel Štancl <samuel@archte.ch>
This commit is contained in:
parent
087733d5db
commit
758fbc8a75
9 changed files with 502 additions and 12 deletions
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('tenant_resources', function (Blueprint $table) {
|
||||||
|
$table->increments('id');
|
||||||
|
$table->string('tenant_id');
|
||||||
|
$table->string('resource_global_id');
|
||||||
|
$table->string('tenant_resources_type');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('tenant_resources');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -4,8 +4,10 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Database\Concerns;
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||||
use Stancl\Tenancy\Contracts\Syncable;
|
use Stancl\Tenancy\Contracts\Syncable;
|
||||||
use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
|
use Stancl\Tenancy\Contracts\UniqueIdentifierGenerator;
|
||||||
|
use Stancl\Tenancy\Database\Models\TenantMorphPivot;
|
||||||
use Stancl\Tenancy\Events\SyncedResourceSaved;
|
use Stancl\Tenancy\Events\SyncedResourceSaved;
|
||||||
|
|
||||||
trait ResourceSyncing
|
trait ResourceSyncing
|
||||||
|
|
@ -43,4 +45,10 @@ trait ResourceSyncing
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function tenants(): MorphToMany
|
||||||
|
{
|
||||||
|
return $this->morphToMany(config('tenancy.models.tenant'), 'tenant_resources', 'tenant_resources', 'resource_global_id', 'tenant_id', 'global_id')
|
||||||
|
->using(TenantMorphPivot::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
src/Database/Concerns/TriggerSyncEvent.php
Normal file
21
src/Database/Concerns/TriggerSyncEvent.php
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\Contracts\Syncable;
|
||||||
|
|
||||||
|
trait TriggerSyncEvent
|
||||||
|
{
|
||||||
|
public static function booted(): void
|
||||||
|
{
|
||||||
|
static::saved(function (self $pivot) {
|
||||||
|
$parent = $pivot->pivotParent;
|
||||||
|
|
||||||
|
if ($parent instanceof Syncable && $parent->shouldSync()) {
|
||||||
|
$parent->triggerSyncEvent();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/Database/Models/TenantMorphPivot.php
Normal file
13
src/Database/Models/TenantMorphPivot.php
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Database\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Relations\MorphPivot;
|
||||||
|
use Stancl\Tenancy\Database\Concerns\TriggerSyncEvent;
|
||||||
|
|
||||||
|
class TenantMorphPivot extends MorphPivot
|
||||||
|
{
|
||||||
|
use TriggerSyncEvent;
|
||||||
|
}
|
||||||
|
|
@ -5,18 +5,9 @@ declare(strict_types=1);
|
||||||
namespace Stancl\Tenancy\Database\Models;
|
namespace Stancl\Tenancy\Database\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||||
use Stancl\Tenancy\Contracts\Syncable;
|
use Stancl\Tenancy\Database\Concerns\TriggerSyncEvent;
|
||||||
|
|
||||||
class TenantPivot extends Pivot
|
class TenantPivot extends Pivot
|
||||||
{
|
{
|
||||||
public static function booted(): void
|
use TriggerSyncEvent;
|
||||||
{
|
|
||||||
static::saved(function (self $pivot) {
|
|
||||||
$parent = $pivot->pivotParent;
|
|
||||||
|
|
||||||
if ($parent instanceof Syncable && $parent->shouldSync()) {
|
|
||||||
$parent->triggerSyncEvent();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,10 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
__DIR__ . '/../assets/impersonation-migrations/' => database_path('migrations'),
|
__DIR__ . '/../assets/impersonation-migrations/' => database_path('migrations'),
|
||||||
], 'impersonation-migrations');
|
], 'impersonation-migrations');
|
||||||
|
|
||||||
|
$this->publishes([
|
||||||
|
__DIR__ . '/../assets/resource-syncing-migrations/' => database_path('migrations'),
|
||||||
|
], 'resource-syncing-migrations');
|
||||||
|
|
||||||
$this->publishes([
|
$this->publishes([
|
||||||
__DIR__ . '/../assets/tenant_routes.stub.php' => base_path('routes/tenant.php'),
|
__DIR__ . '/../assets/tenant_routes.stub.php' => base_path('routes/tenant.php'),
|
||||||
], 'routes');
|
], 'routes');
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class TestCreateCompaniesTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('companies', function (Blueprint $table) {
|
||||||
|
$table->increments('id');
|
||||||
|
$table->string('global_id')->unique();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('email');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('companies');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -832,7 +832,7 @@ function migrateUsersTableForTenants(): void
|
||||||
// Tenant model used for resource syncing setup
|
// Tenant model used for resource syncing setup
|
||||||
class ResourceTenant extends Tenant
|
class ResourceTenant extends Tenant
|
||||||
{
|
{
|
||||||
public function users()
|
public function users(): BelongsToMany
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(CentralUser::class, 'tenant_users', 'tenant_id', 'global_user_id', 'id', 'global_id')
|
return $this->belongsToMany(CentralUser::class, 'tenant_users', 'tenant_id', 'global_user_id', 'id', 'global_id')
|
||||||
->using(TenantPivot::class);
|
->using(TenantPivot::class);
|
||||||
|
|
|
||||||
398
tests/ResourceSyncingUsingPolymorphicTest.php
Normal file
398
tests/ResourceSyncingUsingPolymorphicTest.php
Normal file
|
|
@ -0,0 +1,398 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Stancl\JobPipeline\JobPipeline;
|
||||||
|
use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper;
|
||||||
|
use Stancl\Tenancy\Contracts\Syncable;
|
||||||
|
use Stancl\Tenancy\Contracts\SyncMaster;
|
||||||
|
use Stancl\Tenancy\Database\Concerns\CentralConnection;
|
||||||
|
use Stancl\Tenancy\Database\Concerns\ResourceSyncing;
|
||||||
|
use Stancl\Tenancy\Database\DatabaseConfig;
|
||||||
|
use Stancl\Tenancy\Database\Models\TenantMorphPivot;
|
||||||
|
use Stancl\Tenancy\Database\Models\TenantPivot;
|
||||||
|
use Stancl\Tenancy\Events\SyncedResourceSaved;
|
||||||
|
use Stancl\Tenancy\Events\TenancyEnded;
|
||||||
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
|
use Stancl\Tenancy\Events\TenantCreated;
|
||||||
|
use Stancl\Tenancy\Jobs\CreateDatabase;
|
||||||
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
|
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
||||||
|
use Stancl\Tenancy\Listeners\UpdateSyncedResource;
|
||||||
|
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
config([
|
||||||
|
'tenancy.bootstrappers' => [
|
||||||
|
DatabaseTenancyBootstrapper::class,
|
||||||
|
],
|
||||||
|
'tenancy.models.tenant' => ResourceTenantUsingPolymorphic::class,
|
||||||
|
]);
|
||||||
|
|
||||||
|
Event::listen(TenantCreated::class, JobPipeline::make([CreateDatabase::class])->send(function (TenantCreated $event) {
|
||||||
|
return $event->tenant;
|
||||||
|
})->toListener());
|
||||||
|
|
||||||
|
DatabaseConfig::generateDatabaseNamesUsing(function () {
|
||||||
|
return 'db' . Str::random(16);
|
||||||
|
});
|
||||||
|
|
||||||
|
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||||
|
Event::listen(TenancyEnded::class, RevertToCentralContext::class);
|
||||||
|
|
||||||
|
UpdateSyncedResource::$shouldQueue = false; // Global state cleanup
|
||||||
|
Event::listen(SyncedResourceSaved::class, UpdateSyncedResource::class);
|
||||||
|
|
||||||
|
// Run migrations on central connection
|
||||||
|
pest()->artisan('migrate', [
|
||||||
|
'--path' => [
|
||||||
|
__DIR__ . '/../assets/resource-syncing-migrations',
|
||||||
|
__DIR__ . '/Etc/synced_resource_migrations/users',
|
||||||
|
__DIR__ . '/Etc/synced_resource_migrations/companies',
|
||||||
|
],
|
||||||
|
'--realpath' => true,
|
||||||
|
])->assertExitCode(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('resource syncing works using a single pivot table for multiple models when syncing from central to tenant', function () {
|
||||||
|
$tenant1 = ResourceTenantUsingPolymorphic::create(['id' => 't1']);
|
||||||
|
migrateUsersTableForTenants();
|
||||||
|
|
||||||
|
$centralUser = CentralUserUsingPolymorphic::create([
|
||||||
|
'global_id' => 'acme',
|
||||||
|
'name' => 'John Doe',
|
||||||
|
'email' => 'john@localhost',
|
||||||
|
'password' => 'password',
|
||||||
|
'role' => 'commenter',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$tenant1->run(function () {
|
||||||
|
expect(TenantUserUsingPolymorphic::all())->toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
$centralUser->tenants()->attach('t1');
|
||||||
|
|
||||||
|
// Assert `tenants` are accessible
|
||||||
|
expect($centralUser->tenants->pluck('id')->toArray())->toBe(['t1']);
|
||||||
|
|
||||||
|
// Users are accessible from tenant
|
||||||
|
expect($tenant1->users()->pluck('email')->toArray())->toBe(['john@localhost']);
|
||||||
|
|
||||||
|
// Assert User resource is synced
|
||||||
|
$tenant1->run(function () use ($centralUser) {
|
||||||
|
$tenantUser = TenantUserUsingPolymorphic::first()->toArray();
|
||||||
|
$centralUser = $centralUser->withoutRelations()->toArray();
|
||||||
|
unset($centralUser['id'], $tenantUser['id']);
|
||||||
|
|
||||||
|
expect($tenantUser)->toBe($centralUser);
|
||||||
|
});
|
||||||
|
|
||||||
|
$tenant2 = ResourceTenantUsingPolymorphic::create(['id' => 't2']);
|
||||||
|
migrateCompaniesTableForTenants();
|
||||||
|
|
||||||
|
$centralCompany = CentralCompanyUsingPolymorphic::create([
|
||||||
|
'global_id' => 'acme',
|
||||||
|
'name' => 'ArchTech',
|
||||||
|
'email' => 'archtech@localhost',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$tenant2->run(function () {
|
||||||
|
expect(TenantCompanyUsingPolymorphic::all())->toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
$centralCompany->tenants()->attach('t2');
|
||||||
|
|
||||||
|
// Assert `tenants` are accessible
|
||||||
|
expect($centralCompany->tenants->pluck('id')->toArray())->toBe(['t2']);
|
||||||
|
|
||||||
|
// Companies are accessible from tenant
|
||||||
|
expect($tenant2->companies()->pluck('email')->toArray())->toBe(['archtech@localhost']);
|
||||||
|
|
||||||
|
// Assert Company resource is synced
|
||||||
|
$tenant2->run(function () use ($centralCompany) {
|
||||||
|
$tenantCompany = TenantCompanyUsingPolymorphic::first()->toArray();
|
||||||
|
$centralCompany = $centralCompany->withoutRelations()->toArray();
|
||||||
|
|
||||||
|
unset($centralCompany['id'], $tenantCompany['id']);
|
||||||
|
|
||||||
|
expect($tenantCompany)->toBe($centralCompany);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('resource syncing works using a single pivot table for multiple models when syncing from tenant to central', function () {
|
||||||
|
$tenant1 = ResourceTenantUsingPolymorphic::create(['id' => 't1']);
|
||||||
|
migrateUsersTableForTenants();
|
||||||
|
|
||||||
|
tenancy()->initialize($tenant1);
|
||||||
|
|
||||||
|
$tenantUser = TenantUserUsingPolymorphic::create([
|
||||||
|
'name' => 'John Doe',
|
||||||
|
'email' => 'john@localhost',
|
||||||
|
'password' => 'password',
|
||||||
|
'role' => 'commenter',
|
||||||
|
]);
|
||||||
|
|
||||||
|
tenancy()->end();
|
||||||
|
|
||||||
|
// Assert User resource is synced
|
||||||
|
$centralUser = CentralUserUsingPolymorphic::first();
|
||||||
|
|
||||||
|
// Assert `tenants` are accessible
|
||||||
|
expect($centralUser->tenants->pluck('id')->toArray())->toBe(['t1']);
|
||||||
|
|
||||||
|
// Users are accessible from tenant
|
||||||
|
expect($tenant1->users()->pluck('email')->toArray())->toBe(['john@localhost']);
|
||||||
|
|
||||||
|
$centralUser = $centralUser->withoutRelations()->toArray();
|
||||||
|
$tenantUser = $tenantUser->toArray();
|
||||||
|
unset($centralUser['id'], $tenantUser['id']);
|
||||||
|
|
||||||
|
// array keys use a different order here
|
||||||
|
expect($tenantUser)->toEqualCanonicalizing($centralUser);
|
||||||
|
|
||||||
|
$tenant2 = ResourceTenantUsingPolymorphic::create(['id' => 't2']);
|
||||||
|
migrateCompaniesTableForTenants();
|
||||||
|
|
||||||
|
tenancy()->initialize($tenant2);
|
||||||
|
|
||||||
|
$tenantCompany = TenantCompanyUsingPolymorphic::create([
|
||||||
|
'global_id' => 'acme',
|
||||||
|
'name' => 'tenant comp',
|
||||||
|
'email' => 'company@localhost',
|
||||||
|
]);
|
||||||
|
|
||||||
|
tenancy()->end();
|
||||||
|
|
||||||
|
// Assert Company resource is synced
|
||||||
|
$centralCompany = CentralCompanyUsingPolymorphic::first();
|
||||||
|
|
||||||
|
// Assert `tenants` are accessible
|
||||||
|
expect($centralCompany->tenants->pluck('id')->toArray())->toBe(['t2']);
|
||||||
|
|
||||||
|
// Companies are accessible from tenant
|
||||||
|
expect($tenant2->companies()->pluck('email')->toArray())->toBe(['company@localhost']);
|
||||||
|
|
||||||
|
$centralCompany = $centralCompany->withoutRelations()->toArray();
|
||||||
|
$tenantCompany = $tenantCompany->toArray();
|
||||||
|
unset($centralCompany['id'], $tenantCompany['id']);
|
||||||
|
|
||||||
|
expect($tenantCompany)->toBe($centralCompany);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('right resources are accessible from the tenant', function () {
|
||||||
|
$tenant1 = ResourceTenantUsingPolymorphic::create(['id' => 't1']);
|
||||||
|
$tenant2 = ResourceTenantUsingPolymorphic::create(['id' => 't2']);
|
||||||
|
migrateUsersTableForTenants();
|
||||||
|
|
||||||
|
$user1 = CentralUserUsingPolymorphic::create([
|
||||||
|
'global_id' => 'user1',
|
||||||
|
'name' => 'user1',
|
||||||
|
'email' => 'user1@localhost',
|
||||||
|
'password' => 'password',
|
||||||
|
'role' => 'commenter',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user2 = CentralUserUsingPolymorphic::create([
|
||||||
|
'global_id' => 'user2',
|
||||||
|
'name' => 'user2',
|
||||||
|
'email' => 'user2@localhost',
|
||||||
|
'password' => 'password',
|
||||||
|
'role' => 'commenter',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user3 = CentralUserUsingPolymorphic::create([
|
||||||
|
'global_id' => 'user3',
|
||||||
|
'name' => 'user3',
|
||||||
|
'email' => 'user3@localhost',
|
||||||
|
'password' => 'password',
|
||||||
|
'role' => 'commenter',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user1->tenants()->attach('t1');
|
||||||
|
$user2->tenants()->attach('t1');
|
||||||
|
$user3->tenants()->attach('t2');
|
||||||
|
|
||||||
|
expect($tenant1->users()->pluck('email')->toArray())->toBe([$user1->email, $user2->email]);
|
||||||
|
expect($tenant2->users()->pluck('email')->toArray())->toBe([$user3->email]);
|
||||||
|
});
|
||||||
|
|
||||||
|
function migrateCompaniesTableForTenants(): void
|
||||||
|
{
|
||||||
|
pest()->artisan('tenants:migrate', [
|
||||||
|
'--path' => __DIR__ . '/Etc/synced_resource_migrations/companies',
|
||||||
|
'--realpath' => true,
|
||||||
|
])->assertExitCode(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tenant model used for resource syncing setup
|
||||||
|
class ResourceTenantUsingPolymorphic extends Tenant
|
||||||
|
{
|
||||||
|
public function users(): MorphToMany
|
||||||
|
{
|
||||||
|
return $this->morphedByMany(CentralUserUsingPolymorphic::class, 'tenant_resources', 'tenant_resources', 'tenant_id', 'resource_global_id', 'id', 'global_id')
|
||||||
|
->using(TenantMorphPivot::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function companies(): MorphToMany
|
||||||
|
{
|
||||||
|
return $this->morphedByMany(CentralCompanyUsingPolymorphic::class, 'tenant_resources', 'tenant_resources', 'tenant_id', 'resource_global_id', 'id', 'global_id')
|
||||||
|
->using(TenantMorphPivot::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CentralUserUsingPolymorphic extends Model implements SyncMaster
|
||||||
|
{
|
||||||
|
use ResourceSyncing, CentralConnection;
|
||||||
|
|
||||||
|
protected $guarded = [];
|
||||||
|
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
public $table = 'users';
|
||||||
|
|
||||||
|
public function getTenantModelName(): string
|
||||||
|
{
|
||||||
|
return TenantUserUsingPolymorphic::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGlobalIdentifierKey(): string|int
|
||||||
|
{
|
||||||
|
return $this->getAttribute($this->getGlobalIdentifierKeyName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGlobalIdentifierKeyName(): string
|
||||||
|
{
|
||||||
|
return 'global_id';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCentralModelName(): string
|
||||||
|
{
|
||||||
|
return static::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSyncedAttributeNames(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'global_id',
|
||||||
|
'name',
|
||||||
|
'password',
|
||||||
|
'email',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TenantUserUsingPolymorphic extends Model implements Syncable
|
||||||
|
{
|
||||||
|
use ResourceSyncing;
|
||||||
|
|
||||||
|
protected $table = 'users';
|
||||||
|
|
||||||
|
protected $guarded = [];
|
||||||
|
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
public function getGlobalIdentifierKey(): string|int
|
||||||
|
{
|
||||||
|
return $this->getAttribute($this->getGlobalIdentifierKeyName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGlobalIdentifierKeyName(): string
|
||||||
|
{
|
||||||
|
return 'global_id';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCentralModelName(): string
|
||||||
|
{
|
||||||
|
return CentralUserUsingPolymorphic::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSyncedAttributeNames(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'global_id',
|
||||||
|
'name',
|
||||||
|
'password',
|
||||||
|
'email',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CentralCompanyUsingPolymorphic extends Model implements SyncMaster
|
||||||
|
{
|
||||||
|
use ResourceSyncing, CentralConnection;
|
||||||
|
|
||||||
|
protected $guarded = [];
|
||||||
|
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
public $table = 'companies';
|
||||||
|
|
||||||
|
public function getTenantModelName(): string
|
||||||
|
{
|
||||||
|
return TenantCompanyUsingPolymorphic::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGlobalIdentifierKey(): string|int
|
||||||
|
{
|
||||||
|
return $this->getAttribute($this->getGlobalIdentifierKeyName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGlobalIdentifierKeyName(): string
|
||||||
|
{
|
||||||
|
return 'global_id';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCentralModelName(): string
|
||||||
|
{
|
||||||
|
return static::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSyncedAttributeNames(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'global_id',
|
||||||
|
'name',
|
||||||
|
'email',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TenantCompanyUsingPolymorphic extends Model implements Syncable
|
||||||
|
{
|
||||||
|
use ResourceSyncing;
|
||||||
|
|
||||||
|
protected $table = 'companies';
|
||||||
|
|
||||||
|
protected $guarded = [];
|
||||||
|
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
public function getGlobalIdentifierKey(): string|int
|
||||||
|
{
|
||||||
|
return $this->getAttribute($this->getGlobalIdentifierKeyName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGlobalIdentifierKeyName(): string
|
||||||
|
{
|
||||||
|
return 'global_id';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCentralModelName(): string
|
||||||
|
{
|
||||||
|
return CentralCompanyUsingPolymorphic::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSyncedAttributeNames(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'global_id',
|
||||||
|
'name',
|
||||||
|
'email',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue