|
<?php |
|
|
|
namespace Tests\Concerns; |
|
|
|
use App\Jobs\CreateTenantDatabase; |
|
use App\Models\Tenant; |
|
use Illuminate\Foundation\Console\Kernel; |
|
use Illuminate\Support\Facades\Event; |
|
use Illuminate\Support\Facades\Queue; |
|
use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig; |
|
use Spatie\Multitenancy\Events\MadeTenantCurrentEvent; |
|
use Tests\MultitenancyState; |
|
|
|
trait TenantAware |
|
{ |
|
use UsesMultitenancyConfig; |
|
|
|
/** |
|
* Set up the multitenancy migration of landlord db |
|
* |
|
* @return void |
|
*/ |
|
public function setUpTenantAware(): void |
|
{ |
|
$this->refreshLandLordDatabase(); |
|
|
|
if ($this->setUpCurrentTenant()) { |
|
$this->refreshTenantDatabase(); |
|
} |
|
|
|
} |
|
|
|
/** |
|
* Refresh landlord database |
|
* |
|
* @return void |
|
*/ |
|
protected function refreshLandLordDatabase(): void |
|
{ |
|
$connectionName = $this->landlordDatabaseConnectionName(); |
|
|
|
if (! MultitenancyState::$landLordMigrated) { |
|
$this->artisan("migrate:fresh --database={$connectionName} --path=database/migrations/landlord") |
|
->assertExitCode(0); |
|
|
|
$this->app[Kernel::class]->setArtisan(null); |
|
|
|
MultitenancyState::$landLordMigrated = true; |
|
} |
|
|
|
$this->beginDatabaseTransaction($connectionName); |
|
} |
|
|
|
/** |
|
* Refresh tenant database |
|
* |
|
* @return void |
|
*/ |
|
protected function refreshTenantDatabase(): void |
|
{ |
|
$connectionName = $this->tenantDatabaseConnectionName(); |
|
|
|
if (! MultitenancyState::$tenantMigrated) { |
|
$this->artisan("migrate:fresh --database={$connectionName}") |
|
->assertExitCode(0); |
|
|
|
$this->app[Kernel::class]->setArtisan(null); |
|
|
|
MultitenancyState::$tenantMigrated = true; |
|
} |
|
|
|
if (Tenant::checkCurrent()) { |
|
// Start the transaction when the current tenant exists |
|
$this->beginDatabaseTransaction($connectionName); |
|
} else { |
|
// Start the transaction until a tenant is being made the current one |
|
Event::listen(MadeTenantCurrentEvent::class, fn () => $this->beginDatabaseTransaction($connectionName)); |
|
} |
|
} |
|
|
|
/** |
|
* Begin a database transaction on the testing database. |
|
* |
|
* @return void |
|
*/ |
|
public function beginDatabaseTransaction($connectionName) |
|
{ |
|
$database = $this->app->make('db'); |
|
|
|
$connection = $database->connection($connectionName); |
|
$dispatcher = $connection->getEventDispatcher(); |
|
|
|
$connection->unsetEventDispatcher(); |
|
$connection->beginTransaction(); |
|
$connection->setEventDispatcher($dispatcher); |
|
|
|
if ($this->app->resolved('db.transactions')) { |
|
$this->app->make('db.transactions')->callbacksShouldIgnore( |
|
$this->app->make('db.transactions')->getTransactions()->first() |
|
); |
|
} |
|
|
|
$this->beforeApplicationDestroyed(function () use ($database, $connectionName) { |
|
$connection = $database->connection($connectionName); |
|
$dispatcher = $connection->getEventDispatcher(); |
|
|
|
$connection->unsetEventDispatcher(); |
|
$connection->rollBack(); |
|
$connection->setEventDispatcher($dispatcher); |
|
$connection->disconnect(); |
|
}); |
|
} |
|
|
|
/** |
|
* Set up the current tenant for application testing |
|
* |
|
* @return bool |
|
*/ |
|
public function setUpCurrentTenant(): bool |
|
{ |
|
Queue::fake([CreateTenantDatabase::class]); |
|
|
|
$tenant = Tenant::factory(['database' => env('DB_DATABASE_TENANT')])->create(); |
|
|
|
$tenant->makeCurrent(); |
|
|
|
Queue::assertPushed(fn (CreateTenantDatabase $job) => $job->tenant->id == $tenant->id, 1); |
|
|
|
return $tenant->isCurrent(); |
|
} |
|
} |