mirror of
https://github.com/archtechx/tenancy.git
synced 2026-05-06 16:24:03 +00:00
Some bootstrappers read attributes of the tenant during bootstrap() but don't respond to changes made to the tenant afterwards. Therefore, when making changes to the tenant that'd affect the behavior of a bootstrapper, it's necessary to reinitialize tenancy (if it matters that changes are reflected immediately). This adds a convenience helper for that purpose.
157 lines
4.2 KiB
PHP
157 lines
4.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use Illuminate\Support\Facades\Event;
|
|
use Stancl\Tenancy\Contracts\TenancyBootstrapper;
|
|
use Stancl\Tenancy\Events\TenancyEnded;
|
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
|
use Stancl\Tenancy\Listeners\RevertToCentralContext;
|
|
use Stancl\Tenancy\Tests\Etc\Tenant;
|
|
use function Stancl\Tenancy\Tests\pest;
|
|
use function Stancl\Tenancy\Tests\withTenantDatabases;
|
|
|
|
beforeEach(function () {
|
|
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
|
Event::listen(TenancyEnded::class, RevertToCentralContext::class);
|
|
});
|
|
|
|
test('context is switched to tenant when initializing tenancy and reverted when ending tenancy', function () {
|
|
config(['tenancy.bootstrappers' => [
|
|
MyBootstrapper::class,
|
|
]]);
|
|
|
|
$tenant = Tenant::create([
|
|
'id' => 'acme',
|
|
]);
|
|
|
|
tenancy()->initialize($tenant);
|
|
|
|
expect(app('tenancy_initialized_for_tenant'))->toBe('acme');
|
|
|
|
tenancy()->end();
|
|
|
|
expect(app('tenancy_ended'))->toBe(true);
|
|
});
|
|
|
|
test('context is switched when tenancy is reinitialized', function () {
|
|
config(['tenancy.bootstrappers' => [
|
|
MyBootstrapper::class,
|
|
]]);
|
|
|
|
$tenant = Tenant::create([
|
|
'id' => 'acme',
|
|
]);
|
|
|
|
tenancy()->initialize($tenant);
|
|
|
|
expect(app('tenancy_initialized_for_tenant'))->toBe('acme');
|
|
|
|
$tenant2 = Tenant::create([
|
|
'id' => 'foobar',
|
|
]);
|
|
|
|
tenancy()->initialize($tenant2);
|
|
|
|
expect(app('tenancy_initialized_for_tenant'))->toBe('foobar');
|
|
});
|
|
|
|
test('central helper runs callbacks in the central state', function () {
|
|
withTenantDatabases();
|
|
|
|
tenancy()->initialize($tenant = Tenant::create());
|
|
|
|
tenancy()->central(function () {
|
|
expect(tenant())->toBe(null);
|
|
});
|
|
|
|
expect(tenant())->toBe($tenant);
|
|
});
|
|
|
|
test('central helper returns the value from the callback', function () {
|
|
withTenantDatabases();
|
|
|
|
tenancy()->initialize(Tenant::create());
|
|
|
|
pest()->assertSame('foo', tenancy()->central(function () {
|
|
return 'foo';
|
|
}));
|
|
});
|
|
|
|
test('central helper reverts back to tenant context', function () {
|
|
withTenantDatabases();
|
|
|
|
tenancy()->initialize($tenant = Tenant::create());
|
|
|
|
tenancy()->central(function () {
|
|
//
|
|
});
|
|
|
|
expect(tenant())->toBe($tenant);
|
|
});
|
|
|
|
test('central helper doesnt change tenancy state when called in central context', function () {
|
|
expect(tenancy()->initialized)->toBeFalse();
|
|
expect(tenant())->toBeNull();
|
|
|
|
tenancy()->central(function () {
|
|
//
|
|
});
|
|
|
|
expect(tenancy()->initialized)->toBeFalse();
|
|
expect(tenant())->toBeNull();
|
|
});
|
|
|
|
test('reinitialize method does nothing in the central context', function () {
|
|
expect(tenancy()->initialized)->toBe(false);
|
|
expect(fn () => tenancy()->reinitialize())->not()->toThrow(\Throwable::class);
|
|
expect(tenancy()->initialized)->toBe(false);
|
|
});
|
|
|
|
test('reinitialize method runs bootstrappers again for the current tenant', function () {
|
|
config(['tenancy.bootstrappers' => [
|
|
ReinitBootstrapper::class,
|
|
]]);
|
|
|
|
tenancy()->initialize($tenant = Tenant::create(['reinit_bootstrapper_key' => 'foo']));
|
|
|
|
expect(tenant()->getKey())->toBe($tenant->getKey());
|
|
expect(app('tenancy_reinit_bootstrapper_key'))->toBe('foo');
|
|
|
|
$tenant->update(['reinit_bootstrapper_key' => 'bar']);
|
|
|
|
// Unchanged until we reinitialize...
|
|
expect(app('tenancy_reinit_bootstrapper_key'))->toBe('foo');
|
|
|
|
tenancy()->reinitialize();
|
|
|
|
expect(tenant()->getKey())->toBe($tenant->getKey());
|
|
expect(app('tenancy_reinit_bootstrapper_key'))->toBe('bar');
|
|
});
|
|
|
|
class MyBootstrapper implements TenancyBootstrapper
|
|
{
|
|
public function bootstrap(\Stancl\Tenancy\Contracts\Tenant $tenant): void
|
|
{
|
|
app()->instance('tenancy_initialized_for_tenant', $tenant->getTenantKey());
|
|
}
|
|
|
|
public function revert(): void
|
|
{
|
|
app()->instance('tenancy_ended', true);
|
|
}
|
|
}
|
|
|
|
class ReinitBootstrapper implements TenancyBootstrapper
|
|
{
|
|
public function bootstrap(\Stancl\Tenancy\Contracts\Tenant $tenant): void
|
|
{
|
|
app()->instance('tenancy_reinit_bootstrapper_key', $tenant->getAttribute('reinit_bootstrapper_key'));
|
|
}
|
|
|
|
public function revert(): void
|
|
{
|
|
app()->instance('tenancy_reinit_bootstrapper_key', null);
|
|
}
|
|
}
|