Skip to content

Commit

Permalink
Support for deferred scope apply for Models booted before Tenant setup (
Browse files Browse the repository at this point in the history
#66)

* Added support for deferred scope apply for Models booted before Tenant setup

* Support tenant change to deferred models

* Support to tenant change after model initialized
  • Loading branch information
renanwilliam authored and Caleb Fidecaro committed Aug 6, 2017
1 parent f2b19b4 commit cdb0390
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
composer.lock
phpunit.xml
vendor
.idea
49 changes: 48 additions & 1 deletion src/TenantManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,18 @@ class TenantManager
*/
protected $tenants;

/**
* @var Collection
*/
protected $deferredModels;

/**
* Landlord constructor.
*/
public function __construct()
{
$this->tenants = collect();
$this->deferredModels = collect();
}

/**
Expand All @@ -52,7 +58,7 @@ public function disable()
* Add a tenant to scope by.
*
* @param string|Model $tenant
* @param mixed|null $id
* @param mixed|null $id
*
* @throws TenantNullIdException
*/
Expand Down Expand Up @@ -128,13 +134,48 @@ public function applyTenantScopes(Model $model)
return;
}

if ($this->tenants->isEmpty()) {
// No tenants yet, defer scoping to a later stage
$this->deferredModels->push($model);
return;
}

$this->modelTenants($model)->each(function ($id, $tenant) use ($model) {
$model->addGlobalScope($tenant, function (Builder $builder) use ($tenant, $id, $model) {
if($this->getTenants()->first() && $this->getTenants()->first() != $id){
$id = $this->getTenants()->first();
}

$builder->where($model->getQualifiedTenant($tenant), '=', $id);
});
});
}

/**
* Applies applicable tenant scopes to deferred model booted before tenants setup.
*/
public function applyTenantScopesToDeferredModels()
{
$this->deferredModels->each(function ($model) {
/* @var Model|BelongsToTenants $model */
$this->modelTenants($model)->each(function ($id, $tenant) use ($model) {
if (!isset($model->{$tenant})) {
$model->setAttribute($tenant, $id);
}

$model->addGlobalScope($tenant, function (Builder $builder) use ($tenant, $id, $model) {
if($this->getTenants()->first() && $this->getTenants()->first() != $id){
$id = $this->getTenants()->first();
}

$builder->where($model->getQualifiedTenant($tenant), '=', $id);
});
});
});

$this->deferredModels = collect();
}

/**
* Add tenant columns as needed to a new model instance before it is created.
*
Expand All @@ -146,6 +187,12 @@ public function newModel(Model $model)
return;
}

if ($this->tenants->isEmpty()) {
// No tenants yet, defer scoping to a later stage
$this->deferredModels->push($model);
return;
}

$this->modelTenants($model)->each(function ($tenantId, $tenantColumn) use ($model) {
if (!isset($model->{$tenantColumn})) {
$model->setAttribute($tenantColumn, $tenantId);
Expand Down
15 changes: 15 additions & 0 deletions tests/LandlordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ public function testApplyTenantScopes()
$this->assertArrayNotHasKey('tenant_b_id', $model->getGlobalScopes());
}

public function testApplyTenantScopesToDeferredModels()
{
$landlord = new TenantManager();

$model = new ModelStub();
$landlord->newModel($model);

$landlord->addTenant('tenant_a_id', 1);
$this->assertNull($model->tenant_a_id);

$landlord->applyTenantScopesToDeferredModels();

$this->assertEquals(1, $model->tenant_a_id);
}

public function testNewModel()
{
$landlord = new TenantManager();
Expand Down

0 comments on commit cdb0390

Please sign in to comment.