You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.5 KiB
177 lines
5.5 KiB
<?php |
|
|
|
namespace App\Services; |
|
|
|
use App\Contracts\DatabaseListerInterface; |
|
use App\Models\DatabaseConnection; |
|
use Illuminate\Support\Facades\Config; |
|
use Illuminate\Support\Facades\DB; |
|
use InvalidArgumentException; |
|
use RuntimeException; |
|
use Throwable; |
|
|
|
class DatabaseConnectionManager |
|
{ |
|
public function __construct( |
|
private readonly SqlServerDatabaseService $sqlServer, |
|
private readonly PgsqlDatabaseService $pgsql, |
|
private readonly MySqlDatabaseService $mysql |
|
) { |
|
} |
|
|
|
public function allActive(): array |
|
{ |
|
return DatabaseConnection::query() |
|
->where('is_active', true) |
|
->orderBy('name') |
|
->get() |
|
->all(); |
|
} |
|
|
|
public function find(int $id): DatabaseConnection |
|
{ |
|
return DatabaseConnection::query()->findOrFail($id); |
|
} |
|
|
|
public function listerFor(?int $connectionId): DatabaseListerInterface |
|
{ |
|
if ($connectionId === null) { |
|
$connection = DatabaseConnection::query()->where('is_active', true)->orderBy('id')->first(); |
|
if ($connection === null) { |
|
$this->registerEnvSqlServer(); |
|
|
|
return $this->sqlServer->using('sqlsrv'); |
|
} |
|
|
|
return $this->listerFromModel($connection); |
|
} |
|
|
|
return $this->listerFromModel($this->find($connectionId)); |
|
} |
|
|
|
public function listerFromModel(DatabaseConnection $connection): DatabaseListerInterface |
|
{ |
|
$key = $this->register($connection); |
|
|
|
return match ($connection->driver) { |
|
'sqlsrv' => $this->sqlServer->using($key), |
|
'pgsql' => $this->pgsql->using($key), |
|
'mysql', 'mariadb' => $this->mysql->using($key), |
|
default => throw new InvalidArgumentException('Unsupported database driver.'), |
|
}; |
|
} |
|
|
|
public function register(DatabaseConnection $connection): string |
|
{ |
|
$key = $connection->connectionKey(); |
|
$driver = $connection->driver === 'mariadb' ? 'mysql' : $connection->driver; |
|
|
|
$config = [ |
|
'driver' => $driver, |
|
'host' => $connection->host, |
|
'port' => $connection->port, |
|
'database' => $connection->database ?: ($driver === 'sqlsrv' ? 'master' : 'postgres'), |
|
'username' => $connection->username, |
|
'password' => $connection->getPassword(), |
|
'charset' => 'utf8', |
|
'prefix' => '', |
|
'prefix_indexes' => true, |
|
]; |
|
|
|
if ($driver === 'sqlsrv') { |
|
$config['encrypt'] = 'yes'; |
|
$config['trust_server_certificate'] = 'true'; |
|
} |
|
|
|
Config::set("database.connections.{$key}", $config); |
|
|
|
return $key; |
|
} |
|
|
|
public function test(array $data): string |
|
{ |
|
$driver = $data['driver'] === 'mariadb' ? 'mysql' : $data['driver']; |
|
$key = 'dbconn_test_' . uniqid(); |
|
|
|
Config::set("database.connections.{$key}", [ |
|
'driver' => $driver, |
|
'host' => $data['host'], |
|
'port' => (int) $data['port'], |
|
'database' => $data['database'] ?: ($driver === 'sqlsrv' ? 'master' : ($driver === 'pgsql' ? 'postgres' : 'mysql')), |
|
'username' => $data['username'], |
|
'password' => $data['password'], |
|
'charset' => 'utf8', |
|
'prefix' => '', |
|
'encrypt' => $driver === 'sqlsrv' ? 'yes' : null, |
|
'trust_server_certificate' => $driver === 'sqlsrv' ? 'true' : null, |
|
]); |
|
|
|
try { |
|
DB::connection($key)->getPdo(); |
|
|
|
return 'Connection successful.'; |
|
} catch (Throwable $e) { |
|
throw new RuntimeException('Connection failed: ' . $e->getMessage()); |
|
} finally { |
|
DB::purge($key); |
|
} |
|
} |
|
|
|
public function store(array $data): DatabaseConnection |
|
{ |
|
$connection = new DatabaseConnection([ |
|
'name' => $data['name'], |
|
'driver' => $data['driver'], |
|
'host' => $data['host'], |
|
'port' => (int) $data['port'], |
|
'database' => $data['database'] ?? '', |
|
'username' => $data['username'], |
|
'is_active' => true, |
|
]); |
|
$connection->setPassword($data['password']); |
|
$connection->save(); |
|
|
|
return $connection; |
|
} |
|
|
|
public function update(DatabaseConnection $connection, array $data): DatabaseConnection |
|
{ |
|
$connection->fill([ |
|
'name' => $data['name'], |
|
'driver' => $data['driver'], |
|
'host' => $data['host'], |
|
'port' => (int) $data['port'], |
|
'database' => $data['database'] ?? '', |
|
'username' => $data['username'], |
|
'is_active' => (bool) ($data['is_active'] ?? true), |
|
]); |
|
|
|
if (! empty($data['password'])) { |
|
$connection->setPassword($data['password']); |
|
} |
|
|
|
$connection->save(); |
|
|
|
return $connection; |
|
} |
|
|
|
private function registerEnvSqlServer(): void |
|
{ |
|
if (config('database.connections.sqlsrv.host')) { |
|
return; |
|
} |
|
|
|
Config::set('database.connections.sqlsrv', [ |
|
'driver' => 'sqlsrv', |
|
'host' => env('MSSQL_HOST', 'localhost'), |
|
'port' => env('MSSQL_PORT', '1433'), |
|
'database' => env('MSSQL_DATABASE', 'master'), |
|
'username' => env('MSSQL_USERNAME', 'sa'), |
|
'password' => env('MSSQL_PASSWORD', ''), |
|
'charset' => 'utf8', |
|
'prefix' => '', |
|
'encrypt' => 'yes', |
|
'trust_server_certificate' => 'true', |
|
]); |
|
} |
|
}
|
|
|