From 6416d34e4b9e53d0ce0e14cd761810d438f19d76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johann=20Rodr=C3=ADguez?= Date: Sat, 27 Sep 2025 22:38:51 +0100 Subject: [PATCH 1/4] Added support for pgsql's search_path --- framework/core/src/Database/Migrator.php | 13 +++++++++++-- .../src/Install/Controller/InstallController.php | 1 + framework/core/src/Install/DatabaseConfig.php | 7 ++++++- framework/core/src/Install/Installation.php | 2 +- framework/core/src/Install/Steps/RunMigrations.php | 5 +++-- framework/core/views/install/install.php | 13 ++++++++++++- 6 files changed, 34 insertions(+), 7 deletions(-) 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/Controller/InstallController.php b/framework/core/src/Install/Controller/InstallController.php index f3297d19f7..94c028d63c 100644 --- a/framework/core/src/Install/Controller/InstallController.php +++ b/framework/core/src/Install/Controller/InstallController.php @@ -92,6 +92,7 @@ private function makeDatabaseConfig(array $input): DatabaseConfig $driver, $host, intval($port), + Arr::get($input, 'dbSchema'), Arr::get($input, 'dbName'), Arr::get($input, 'dbUsername'), Arr::get($input, 'dbPassword'), diff --git a/framework/core/src/Install/DatabaseConfig.php b/framework/core/src/Install/DatabaseConfig.php index bf7b39fe3d..58837f8cbd 100644 --- a/framework/core/src/Install/DatabaseConfig.php +++ b/framework/core/src/Install/DatabaseConfig.php @@ -18,6 +18,7 @@ public function __construct( private readonly string $driver, private readonly ?string $host, private readonly int $port, + private string $schema, private string $database, private readonly ?string $username, #[\SensitiveParameter] private readonly ?string $password, @@ -54,6 +55,10 @@ private function validate(): void throw new ValidationFailed('Please provide a valid port number between 1 and 65535.'); } + if (empty($this->schema) && $this->driver == 'pgsql') { + throw new ValidationFailed('Please specify the schema name.'); + } + if (empty($this->database)) { throw new ValidationFailed('Please specify the database name.'); } @@ -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..cbaf518dab 100644 --- a/framework/core/views/install/install.php +++ b/framework/core/views/install/install.php @@ -31,6 +31,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(); From bc92b29b7ac8afa58776aae3835c62500075cdd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johann=20Rodr=C3=ADguez?= Date: Sat, 27 Sep 2025 23:55:50 +0100 Subject: [PATCH 2/4] Put schema after database name --- .../core/src/Install/Controller/InstallController.php | 2 +- framework/core/src/Install/DatabaseConfig.php | 10 +++++----- framework/core/views/install/install.php | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/framework/core/src/Install/Controller/InstallController.php b/framework/core/src/Install/Controller/InstallController.php index 94c028d63c..799fad8142 100644 --- a/framework/core/src/Install/Controller/InstallController.php +++ b/framework/core/src/Install/Controller/InstallController.php @@ -92,8 +92,8 @@ private function makeDatabaseConfig(array $input): DatabaseConfig $driver, $host, intval($port), - Arr::get($input, 'dbSchema'), 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 58837f8cbd..79a1b3ce0f 100644 --- a/framework/core/src/Install/DatabaseConfig.php +++ b/framework/core/src/Install/DatabaseConfig.php @@ -18,8 +18,8 @@ public function __construct( private readonly string $driver, private readonly ?string $host, private readonly int $port, - private string $schema, private string $database, + private readonly ?string $schema, private readonly ?string $username, #[\SensitiveParameter] private readonly ?string $password, private readonly ?string $prefix @@ -55,14 +55,14 @@ private function validate(): void throw new ValidationFailed('Please provide a valid port number between 1 and 65535.'); } - if (empty($this->schema) && $this->driver == 'pgsql') { - throw new ValidationFailed('Please specify the schema name.'); - } - if (empty($this->database)) { 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.'); } diff --git a/framework/core/views/install/install.php b/framework/core/views/install/install.php index cbaf518dab..4205ec82b1 100644 --- a/framework/core/views/install/install.php +++ b/framework/core/views/install/install.php @@ -31,6 +31,11 @@
+
+ + +
+
@@ -38,11 +43,6 @@
-
- - -
-
From 5d0d2db5783f3d50d6cba5fc7706140a676d47d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johann=20Rodr=C3=ADguez?= Date: Sun, 28 Sep 2025 00:06:10 +0100 Subject: [PATCH 3/4] Add schema arguments and order 'ask's --- .../core/src/Install/Console/FileDataProvider.php | 1 + .../core/src/Install/Console/UserDataProvider.php | 15 +++++++++++++-- .../testing/src/integration/Setup/SetupScript.php | 5 +++++ 3 files changed, 19 insertions(+), 2 deletions(-) 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/php-packages/testing/src/integration/Setup/SetupScript.php b/php-packages/testing/src/integration/Setup/SetupScript.php index fee9d05f63..50883d0ffc 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->name = 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"; + } else if ($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 From 8241635b7cb92d708bdb71f1b69e0caf7fe7a291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johann=20Rodr=C3=ADguez?= Date: Sun, 28 Sep 2025 00:12:50 +0100 Subject: [PATCH 4/4] Fixed errors --- php-packages/testing/src/integration/Setup/SetupScript.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php-packages/testing/src/integration/Setup/SetupScript.php b/php-packages/testing/src/integration/Setup/SetupScript.php index 50883d0ffc..afbb735a89 100644 --- a/php-packages/testing/src/integration/Setup/SetupScript.php +++ b/php-packages/testing/src/integration/Setup/SetupScript.php @@ -47,7 +47,7 @@ public function __construct() default => 0, }); $this->name = getenv('DB_DATABASE') ?: 'flarum_test'; - $this->name = getenv('DB_SCHEMA') ?: 'public'; + $this->schema = getenv('DB_SCHEMA') ?: 'public'; $this->user = getenv('DB_USERNAME') ?: 'root'; $this->pass = getenv('DB_PASSWORD') ?? 'root'; $this->pref = getenv('DB_PREFIX') ?: ''; @@ -59,7 +59,7 @@ public function run() if ($this->driver === 'sqlite') { echo "Connecting to SQLite database at $this->name.\n"; - } else if ($this->driver === 'pgsql') { + } 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";