diff --git a/framework/core/src/Database/Migrator.php b/framework/core/src/Database/Migrator.php index 8dccce81c4..91dc873d13 100644 --- a/framework/core/src/Database/Migrator.php +++ b/framework/core/src/Database/Migrator.php @@ -11,6 +11,7 @@ use Flarum\Database\Exception\MigrationKeyMissing; use Flarum\Extension\Extension; +use Flarum\Install\DatabaseConfig; use Illuminate\Contracts\Filesystem\FileNotFoundException; use Illuminate\Database\ConnectionInterface; use Illuminate\Filesystem\Filesystem; @@ -224,8 +225,11 @@ public function resolve(string $path, string $file): array * * @param string $path to the directory containing the dump. */ - public function installFromSchema(string $path, string $driver): bool + public function installFromSchema(string $path, DatabaseConfig $dbConfig): bool { + $driver = $dbConfig->toArray()['driver']; + $pgSearchPath = $dbConfig->toArray()['search_path'] ?? 'public'; + $schemaPath = "$path/$driver-install.dump"; if (! file_exists($schemaPath)) { @@ -252,11 +256,16 @@ public function installFromSchema(string $path, string $driver): bool $this->connection->getTablePrefix() ?? '', $statement ); + + if ($driver === 'pgsql' && $pgSearchPath != 'public') { + $statement = preg_replace('/(public)([\s.;])/', "$pgSearchPath\$2", $statement); + } + $this->connection->statement($statement); } if ($driver === 'pgsql') { - $this->connection->statement('SELECT pg_catalog.set_config(\'search_path\', \'public\', false)'); + $this->connection->statement("SELECT pg_catalog.set_config('search_path', '$pgSearchPath', false)"); } $this->connection->getSchemaBuilder()->enableForeignKeyConstraints(); diff --git a/framework/core/src/Install/Console/FileDataProvider.php b/framework/core/src/Install/Console/FileDataProvider.php index 4dd828407e..721b91d245 100644 --- a/framework/core/src/Install/Console/FileDataProvider.php +++ b/framework/core/src/Install/Console/FileDataProvider.php @@ -73,6 +73,7 @@ private function getDatabaseConfiguration(): DatabaseConfig $this->databaseConfiguration['host'] ?? 'localhost', $this->databaseConfiguration['port'] ?? 3306, $this->databaseConfiguration['database'] ?? 'flarum', + $this->databaseConfiguration['search_path'] ?? 'public', $this->databaseConfiguration['username'] ?? 'root', $this->databaseConfiguration['password'] ?? '', $this->databaseConfiguration['prefix'] ?? '' diff --git a/framework/core/src/Install/Console/UserDataProvider.php b/framework/core/src/Install/Console/UserDataProvider.php index d546d9d9a7..67735505b0 100644 --- a/framework/core/src/Install/Console/UserDataProvider.php +++ b/framework/core/src/Install/Console/UserDataProvider.php @@ -56,19 +56,30 @@ private function getDatabaseConfiguration(): DatabaseConfig if (Str::contains($host, ':')) { [$host, $port] = explode(':', $host, 2); } + } + + $database = $this->ask('Database name (required):', required: true); + + if ($driver === 'pgsql') { + $schema = $this->ask('Schema (Default: public):', 'public'); + } + if (in_array($driver, ['mysql', 'mariadb', 'pgsql'])) { $user = $this->ask('Database user (required):', required: true); $password = $this->secret('Database password:'); } + $prefix = $this->ask('Prefix:'); + return new DatabaseConfig( $driver, $host ?? null, intval($port), - $this->ask('Database name (required):', required: true), + $database, + $schema ?? null, $user ?? null, $password ?? null, - $this->ask('Prefix:') + $prefix ?? null ); } diff --git a/framework/core/src/Install/Controller/InstallController.php b/framework/core/src/Install/Controller/InstallController.php index f3297d19f7..799fad8142 100644 --- a/framework/core/src/Install/Controller/InstallController.php +++ b/framework/core/src/Install/Controller/InstallController.php @@ -93,6 +93,7 @@ private function makeDatabaseConfig(array $input): DatabaseConfig $host, intval($port), Arr::get($input, 'dbName'), + Arr::get($input, 'dbSchema'), Arr::get($input, 'dbUsername'), Arr::get($input, 'dbPassword'), Arr::get($input, 'tablePrefix') diff --git a/framework/core/src/Install/DatabaseConfig.php b/framework/core/src/Install/DatabaseConfig.php index bf7b39fe3d..79a1b3ce0f 100644 --- a/framework/core/src/Install/DatabaseConfig.php +++ b/framework/core/src/Install/DatabaseConfig.php @@ -19,6 +19,7 @@ public function __construct( private readonly ?string $host, private readonly int $port, private string $database, + private readonly ?string $schema, private readonly ?string $username, #[\SensitiveParameter] private readonly ?string $password, private readonly ?string $prefix @@ -58,6 +59,10 @@ private function validate(): void throw new ValidationFailed('Please specify the database name.'); } + if (empty($this->schema) && $this->driver == 'pgsql') { + throw new ValidationFailed('Please specify the schema name.'); + } + if (empty($this->username) && in_array($this->driver, ['mysql', 'mariadb', 'pgsql'])) { throw new ValidationFailed('Please specify the username for accessing the database.'); } @@ -100,7 +105,7 @@ private function driverOptions(): array 'username' => $this->username, 'password' => $this->password, 'charset' => 'utf8', - 'search_path' => 'public', + 'search_path' => $this->schema, 'sslmode' => 'prefer', ], 'sqlite' => [ diff --git a/framework/core/src/Install/Installation.php b/framework/core/src/Install/Installation.php index 6a821c2b93..0c6c9ec836 100644 --- a/framework/core/src/Install/Installation.php +++ b/framework/core/src/Install/Installation.php @@ -138,7 +138,7 @@ function ($connection) { }); $pipeline->pipe(function () { - return new Steps\RunMigrations($this->db, $this->dbConfig->toArray()['driver'], $this->getMigrationPath()); + return new Steps\RunMigrations($this->db, $this->dbConfig, $this->getMigrationPath()); }); $pipeline->pipe(function () { diff --git a/framework/core/src/Install/Steps/RunMigrations.php b/framework/core/src/Install/Steps/RunMigrations.php index da78d065c1..73077edc2e 100644 --- a/framework/core/src/Install/Steps/RunMigrations.php +++ b/framework/core/src/Install/Steps/RunMigrations.php @@ -11,6 +11,7 @@ use Flarum\Database\DatabaseMigrationRepository; use Flarum\Database\Migrator; +use Flarum\Install\DatabaseConfig; use Flarum\Install\Step; use Illuminate\Database\ConnectionInterface; use Illuminate\Filesystem\Filesystem; @@ -19,7 +20,7 @@ { public function __construct( private ConnectionInterface $database, - private string $driver, + private DatabaseConfig $dbConfig, private string $path ) { } @@ -33,7 +34,7 @@ public function run(): void { $migrator = $this->getMigrator(); - if (! $migrator->repositoryExists() && ! $migrator->installFromSchema($this->path, $this->driver)) { + if (! $migrator->repositoryExists() && ! $migrator->installFromSchema($this->path, $this->dbConfig)) { $migrator->getRepository()->createRepository(); } diff --git a/framework/core/views/install/install.php b/framework/core/views/install/install.php index 8f08032bd7..4205ec82b1 100644 --- a/framework/core/views/install/install.php +++ b/framework/core/views/install/install.php @@ -36,6 +36,13 @@ +
+
+ + +
+
+
@@ -90,7 +97,9 @@ document.addEventListener('DOMContentLoaded', function() { document.querySelector('form input').select(); - document.querySelector('select[name="dbDriver"]').addEventListener('change', function() { + const dbDriver = document.querySelector('select[name="dbDriver"]'); + + dbDriver.addEventListener('change', function() { document.querySelectorAll('[data-group]').forEach(function(group) { group.style.display = 'none'; }); @@ -102,6 +111,8 @@ }); }); + dbDriver.dispatchEvent(new Event('change', { bubbles: true })); + document.querySelector('form').addEventListener('submit', function(e) { e.preventDefault(); diff --git a/php-packages/testing/src/integration/Setup/SetupScript.php b/php-packages/testing/src/integration/Setup/SetupScript.php index fee9d05f63..afbb735a89 100644 --- a/php-packages/testing/src/integration/Setup/SetupScript.php +++ b/php-packages/testing/src/integration/Setup/SetupScript.php @@ -25,6 +25,7 @@ class SetupScript protected string $host; protected int $port; protected string $name; + protected string $schema; protected string $user; protected string $pass; protected string $pref; @@ -46,6 +47,7 @@ public function __construct() default => 0, }); $this->name = getenv('DB_DATABASE') ?: 'flarum_test'; + $this->schema = getenv('DB_SCHEMA') ?: 'public'; $this->user = getenv('DB_USERNAME') ?: 'root'; $this->pass = getenv('DB_PASSWORD') ?? 'root'; $this->pref = getenv('DB_PREFIX') ?: ''; @@ -57,6 +59,8 @@ public function run() if ($this->driver === 'sqlite') { echo "Connecting to SQLite database at $this->name.\n"; + } elseif ($this->driver === 'pgsql') { + echo "Connecting to database $this->name, schema $this->schema at $this->host:$this->port.\n"; } else { echo "Connecting to database $this->name at $this->host:$this->port.\n"; } @@ -80,6 +84,7 @@ public function run() $this->host, $this->port, $this->name, + $this->schema, $this->user, $this->pass, $this->pref