CaiWuXiTong/modules/EcommerceFinance/Services/UpstreamStoredConfiguration.php

120 lines
4.1 KiB
PHP

<?php
namespace Modules\EcommerceFinance\Services;
use App\Models\Settings\DatabaseConnection;
use Illuminate\Support\Facades\Schema;
/**
* 从系统数据库读取可由同一套系统数据库凭据解锁的上游连接配置。
*
* 本地、开发和测试环境保持可用;生产环境必须通过私有环境变量显式开启。
*/
class UpstreamStoredConfiguration
{
public const SYSTEM_COMPANY_ID = 0;
/** @var array<string, DatabaseConnection|null> */
private array $connections = [];
public function editable(): bool
{
return app()->environment(['local', 'development', 'testing'])
|| (bool) config('upstreams.stored_configuration.enabled', false);
}
public function enabled(): bool
{
return (bool) config('upstreams.stored_configuration.enabled', false);
}
public function find(string $source): ?DatabaseConnection
{
if (! $this->enabled()) {
return null;
}
if (array_key_exists($source, $this->connections)) {
return $this->connections[$source];
}
if (! Schema::hasTable('system_database_connections')) {
return $this->connections[$source] = null;
}
$query = DatabaseConnection::query()->where('company_id', self::SYSTEM_COMPANY_ID);
if (preg_match('/^database_([1-9][0-9]*)$/', $source, $matches)) {
$query->where('id', $matches[1])->whereNull('source_key');
} else {
$query->where('source_key', $source);
}
$this->connections[$source] = $query->first();
return $this->connections[$source];
}
public function forget(string $source): void
{
unset($this->connections[$source]);
}
/** @return array<string,DatabaseConnection> */
public function all(): array
{
if (! $this->enabled() || ! Schema::hasTable('system_database_connections')) {
return [];
}
return DatabaseConnection::query()->where('company_id', self::SYSTEM_COMPANY_ID)
->get()->keyBy(fn (DatabaseConnection $row) => $row->sourceIdentifier())->all();
}
public function value(string $source, string $path, mixed $default = null): mixed
{
$connection = $this->find($source);
if (! $connection) {
return $default;
}
return match (trim($path, '.')) {
'enabled' => $connection->enabled,
'allowed_scopes' => $connection->allowed_scopes ?? [],
'connection' => $this->connection($connection, $default),
'connection.host' => $connection->host,
'connection.driver' => $connection->driver,
'connection.port' => $connection->port,
'connection.database' => $connection->database_name,
'connection.username' => $connection->username,
'connection.password' => $this->password($connection, $default),
'connection.odbc_driver' => $connection->odbc_driver,
'connection.tds_version' => $connection->tds_version,
'connection.connect_timeout' => $connection->connect_timeout,
'connection.query_timeout' => $connection->query_timeout,
default => $default,
};
}
private function connection(DatabaseConnection $connection, mixed $default): array
{
$configured = is_array($default) ? $default : [];
return array_replace($configured, [
'driver' => $connection->driver,
'host' => $connection->host,
'port' => $connection->port,
'database' => $connection->database_name,
'username' => $connection->username,
'password' => $this->password($connection, $configured['password'] ?? null),
'odbc_driver' => $connection->odbc_driver,
'tds_version' => $connection->tds_version,
'connect_timeout' => $connection->connect_timeout,
'query_timeout' => $connection->query_timeout,
]);
}
private function password(DatabaseConnection $connection, mixed $_localPassword): mixed
{
return $connection->resolvedPassword();
}
}