1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-12 19:14:04 +00:00

Simplify TenantWithDatabase interface, move tenantConfig() logic

This commit is contained in:
Samuel Štancl 2024-03-01 10:48:33 +01:00
parent 8a269f8dd8
commit e8c3c75d7c
5 changed files with 68 additions and 59 deletions

View file

@ -4,15 +4,38 @@ declare(strict_types=1);
namespace Stancl\Tenancy\Database\Concerns;
use Illuminate\Database\Eloquent\Model;
use Stancl\Tenancy\Database\Contracts\TenantWithDatabase;
use Stancl\Tenancy\Database\DatabaseConfig;
/**
* @mixin Model
*/
trait HasDatabase
{
use HasInternalKeys;
public function database(): DatabaseConfig
{
/** @var TenantWithDatabase $this */
/** @var TenantWithDatabase&Model $this */
$databaseConfig = [];
return new DatabaseConfig($this);
foreach ($this->getAttributes() as $key => $value) {
if (str($key)->startsWith($this->internalPrefix() . 'db_')) {
if ($key === $this->internalPrefix() . 'db_name') {
// Remove DB name because we set that separately
continue;
}
if ($key === $this->internalPrefix() . 'db_connection') {
// Remove DB connection because that's not used here
continue;
}
$databaseConfig[str($key)->after($this->internalPrefix() . 'db_')->toString()] = $value;
}
}
return new DatabaseConfig($this, $databaseConfig);
}
}

View file

@ -4,6 +4,9 @@ declare(strict_types=1);
namespace Stancl\Tenancy\Database\Concerns;
/**
* @mixin \Illuminate\Database\Eloquent\Model
*/
trait HasInternalKeys
{
/** Get the internal prefix. */

View file

@ -11,13 +11,4 @@ interface TenantWithDatabase extends Tenant
{
/** Get the tenant's database config. */
public function database(): DatabaseConfig;
/** Get the internal prefix. */
public static function internalPrefix(): string;
/** Get an internal key. */
public function getInternal(string $key): mixed;
/** Set internal key. */
public function setInternal(string $key, mixed $value): static;
}

View file

@ -18,35 +18,57 @@ class DatabaseConfig
/** The tenant whose database we're dealing with. */
public Tenant&Model $tenant;
/** Database username generator (can be set by the developer.) */
public static Closure|null $usernameGenerator = null;
/** Additional config for the database connection, specific to this tenant. */
public array $tenantConfig;
/** Database password generator (can be set by the developer.) */
public static Closure|null $passwordGenerator = null;
/**
* Database username generator (can be set by the developer.).
*
* @var Closure(Model&Tenant): string
*/
public static Closure $usernameGenerator;
/** Database name generator (can be set by the developer.) */
public static Closure|null $databaseNameGenerator = null;
/**
* Database password generator (can be set by the developer.).
*
* @var Closure(Model&Tenant): string
*/
public static Closure $passwordGenerator;
/**
* Database name generator (can be set by the developer.).
*
* @var Closure(Model&Tenant): string
*/
public static Closure $databaseNameGenerator;
public static function __constructStatic(): void
{
static::$usernameGenerator = static::$usernameGenerator ?? function (Model&Tenant $tenant) {
return Str::random(16);
};
if (! isset(static::$usernameGenerator)) {
static::$usernameGenerator = function () {
return Str::random(16);
};
}
static::$passwordGenerator = static::$passwordGenerator ?? function (Model&Tenant $tenant) {
return Hash::make(Str::random(32));
};
if (! isset(static::$passwordGenerator)) {
static::$passwordGenerator = function () {
return Hash::make(Str::random(32));
};
}
static::$databaseNameGenerator = static::$databaseNameGenerator ?? function (Model&Tenant $tenant) {
return config('tenancy.database.prefix') . $tenant->getTenantKey() . config('tenancy.database.suffix');
};
if (! isset(static::$databaseNameGenerator)) {
static::$databaseNameGenerator = function (Model&Tenant $tenant) {
return config('tenancy.database.prefix') . $tenant->getTenantKey() . config('tenancy.database.suffix');
};
}
}
public function __construct(Model&Tenant $tenant)
public function __construct(Model&Tenant $tenant, array $databaseConfig)
{
static::__constructStatic();
$this->tenant = $tenant;
$this->tenantConfig = $databaseConfig;
}
public static function generateDatabaseNamesUsing(Closure $databaseNameGenerator): void
@ -134,7 +156,7 @@ class DatabaseConfig
$templateConnection = $this->getTemplateConnection();
return $this->manager()->makeConnectionConfig(
array_merge($templateConnection, $this->tenantConfig()),
array_merge($templateConnection, $this->tenantConfig),
$this->getName()
);
}
@ -144,7 +166,7 @@ class DatabaseConfig
*/
public function hostConnection(): array
{
$config = $this->tenantConfig();
$config = $this->tenantConfig;
$templateConnection = $this->getTemplateConnection();
if ($this->connectionDriverManager($this->getTemplateConnectionDriver()) instanceof Contracts\ManagesDatabaseUsers) {
@ -169,32 +191,6 @@ class DatabaseConfig
DB::purge($this->getTenantHostConnectionName());
}
/**
* Additional config for the database connection, specific to this tenant.
*/
public function tenantConfig(): array
{
$dbConfig = array_filter(array_keys($this->tenant->getAttributes()), function ($key) {
return Str::startsWith($key, $this->tenant->internalPrefix() . 'db_');
});
// Remove DB name because we set that separately
if (($pos = array_search($this->tenant->internalPrefix() . 'db_name', $dbConfig)) !== false) {
unset($dbConfig[$pos]);
}
// Remove DB connection because that's not used inside the array
if (($pos = array_search($this->tenant->internalPrefix() . 'db_connection', $dbConfig)) !== false) {
unset($dbConfig[$pos]);
}
return array_reduce($dbConfig, function ($config, $key) {
return array_merge($config, [
Str::substr($key, strlen($this->tenant->internalPrefix() . 'db_')) => $this->tenant->getAttribute($key),
]);
}, []);
}
/** Get the TenantDatabaseManager for this tenant's connection.
*
* @throws NoConnectionSetException|DatabaseManagerNotRegisteredException