From 5aba60adab8389c794f0b264dd87fa8085f8487f Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 09:20:24 -0500 Subject: [PATCH 01/15] fix(setup/AbstractDB): handle missing dbname in dots check Also: - Switch to more modern str_contains() - Tidy up code formatting a bit Signed-off-by: Josh --- lib/private/Setup/AbstractDatabase.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index d07d4af91a6c0..e8ecb31cd4cc2 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -36,16 +36,24 @@ public function __construct( public function validate(array $config): array { $errors = []; - if (empty($config['dbuser']) && empty($config['dbname'])) { + + $dbUser = $config['dbuser'] ?? ''; + $dbName = $config['dbname'] ?? ''; + + // Check for missing required parameters + if (empty($dbUser) && empty($dbName)) { $errors[] = $this->trans->t('Enter the database Login and name for %s', [$this->dbprettyname]); - } elseif (empty($config['dbuser'])) { + } elseif (empty($dbUser)) { $errors[] = $this->trans->t('Enter the database Login for %s', [$this->dbprettyname]); - } elseif (empty($config['dbname'])) { + } elseif (empty($dbName)) { $errors[] = $this->trans->t('Enter the database name for %s', [$this->dbprettyname]); } - if (substr_count($config['dbname'], '.') >= 1) { + + // Avoid downsides of supporting database names with dots (`.`) + if (!empty($dbName) && str_contains($dbName, '.')) { $errors[] = $this->trans->t('You cannot use dots in the database name %s', [$this->dbprettyname]); } + return $errors; } From 57e54fd8678e5396bb0c800309064676269e4535 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 09:28:11 -0500 Subject: [PATCH 02/15] refactor(setup/AbstractDB): Extract validation methods - Child classes can override specific validation rules more selectively (e.g. OCI override becomes simpler to avoid the dot check) - Improved code readability Signed-off-by: Josh --- lib/private/Setup/AbstractDatabase.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index e8ecb31cd4cc2..37eb5eacf15a8 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -37,6 +37,15 @@ public function __construct( public function validate(array $config): array { $errors = []; + $errors = array_merge($errors, $this->validateRequiredFields($config)); + $errors = array_merge($errors, $this->validateDatabaseName($config)); + + return $errors; + } + + protected function validateRequiredFields(array $config): array { + $errors = []; + $dbUser = $config['dbuser'] ?? ''; $dbName = $config['dbname'] ?? ''; @@ -49,6 +58,14 @@ public function validate(array $config): array { $errors[] = $this->trans->t('Enter the database name for %s', [$this->dbprettyname]); } + return $errors; + } + + protected function validateDatabaseName(array $config): array { + $errors = []; + + $dbName = $config['dbname'] ?? ''; + // Avoid downsides of supporting database names with dots (`.`) if (!empty($dbName) && str_contains($dbName, '.')) { $errors[] = $this->trans->t('You cannot use dots in the database name %s', [$this->dbprettyname]); From 28449695f78a0e7274b5a3540ca54fa0b27264aa Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 09:35:31 -0500 Subject: [PATCH 03/15] refactor(setup/OCI): override override validateDatabaseName() to skip dot check Signed-off-by: Josh --- lib/private/Setup/OCI.php | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/lib/private/Setup/OCI.php b/lib/private/Setup/OCI.php index 7bde42c1ace75..76d41404c9104 100644 --- a/lib/private/Setup/OCI.php +++ b/lib/private/Setup/OCI.php @@ -30,16 +30,9 @@ public function initialize(array $config): void { ]); } - public function validate(array $config): array { - $errors = []; - if (empty($config['dbuser']) && empty($config['dbname'])) { - $errors[] = $this->trans->t('Enter the database Login and name for %s', [$this->dbprettyname]); - } elseif (empty($config['dbuser'])) { - $errors[] = $this->trans->t('Enter the database Login for %s', [$this->dbprettyname]); - } elseif (empty($config['dbname'])) { - $errors[] = $this->trans->t('Enter the database name for %s', [$this->dbprettyname]); - } - return $errors; + protected function validateDatabaseName(array $config): array { + // Override default checks; allow dots in service name for oracle autosetup + return []; } public function setupDatabase(): void { From 41c9b4834674833943a58b6a8002e490e0d1e288 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 10:00:18 -0500 Subject: [PATCH 04/15] refactor(setup/AbstractDB): eliminate magic property $this->dbprettyname - Makes the undefined property explicit and required (less psalm baseline noise) - Forces child classes to implement it - Better type safety Signed-off-by: Josh --- lib/private/Setup/AbstractDatabase.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index 37eb5eacf15a8..1739b1ef370f7 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -34,6 +34,8 @@ public function __construct( ) { } + abstract protected function getDisplayName(): string; + public function validate(array $config): array { $errors = []; @@ -48,14 +50,15 @@ protected function validateRequiredFields(array $config): array { $dbUser = $config['dbuser'] ?? ''; $dbName = $config['dbname'] ?? ''; + $displayName = $this->getDisplayName(); // Check for missing required parameters if (empty($dbUser) && empty($dbName)) { - $errors[] = $this->trans->t('Enter the database Login and name for %s', [$this->dbprettyname]); + $errors[] = $this->trans->t('Enter the database Login and name for %s', [$displayName]); } elseif (empty($dbUser)) { - $errors[] = $this->trans->t('Enter the database Login for %s', [$this->dbprettyname]); + $errors[] = $this->trans->t('Enter the database Login for %s', [$displayName]); } elseif (empty($dbName)) { - $errors[] = $this->trans->t('Enter the database name for %s', [$this->dbprettyname]); + $errors[] = $this->trans->t('Enter the database name for %s', [$displayName]); } return $errors; @@ -68,7 +71,7 @@ protected function validateDatabaseName(array $config): array { // Avoid downsides of supporting database names with dots (`.`) if (!empty($dbName) && str_contains($dbName, '.')) { - $errors[] = $this->trans->t('You cannot use dots in the database name %s', [$this->dbprettyname]); + $errors[] = $this->trans->t('You cannot use dots in the database name %s', [$this->getDisplayName]); } return $errors; From b0294cf397b4659969070d56bca7a6bdc44ee7b8 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 10:03:22 -0500 Subject: [PATCH 05/15] chore(setup/MySQL): switch from $dbprettyname to getDisplayName Signed-off-by: Josh --- lib/private/Setup/MySQL.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php index 24093ae97a40c..af0f59780a3c8 100644 --- a/lib/private/Setup/MySQL.php +++ b/lib/private/Setup/MySQL.php @@ -16,7 +16,10 @@ use OCP\Security\ISecureRandom; class MySQL extends AbstractDatabase { - public string $dbprettyname = 'MySQL/MariaDB'; + + protected function getDisplayName(): string { + return 'MySQL/MariaDB'; + } public function setupDatabase(): void { //check if the database user has admin right From f9ae23b0642fe8fa49e0a2597d910638bd936657 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 10:04:48 -0500 Subject: [PATCH 06/15] chore(setup/OCI): switch from $dbprettyname to getDisplayName Signed-off-by: Josh --- lib/private/Setup/OCI.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/private/Setup/OCI.php b/lib/private/Setup/OCI.php index 76d41404c9104..73cba1f1c46de 100644 --- a/lib/private/Setup/OCI.php +++ b/lib/private/Setup/OCI.php @@ -10,10 +10,12 @@ use OC\DatabaseSetupException; class OCI extends AbstractDatabase { - public $dbprettyname = 'Oracle'; - protected $dbtablespace; + protected function getDisplayName(): string { + return 'Oracle'; + } + public function initialize(array $config): void { parent::initialize($config); if (array_key_exists('dbtablespace', $config)) { From 63e1a49c0ab0e4fed0604dcda35f700929396853 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 10:06:45 -0500 Subject: [PATCH 07/15] chore(setup/Sqlite): switch from $dbprettyname to getDisplayName And canonicalize "SQLite" properly Signed-off-by: Josh --- lib/private/Setup/Sqlite.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/private/Setup/Sqlite.php b/lib/private/Setup/Sqlite.php index 325a26ce89680..95050abe128e2 100644 --- a/lib/private/Setup/Sqlite.php +++ b/lib/private/Setup/Sqlite.php @@ -10,7 +10,10 @@ use OC\DB\ConnectionFactory; class Sqlite extends AbstractDatabase { - public string $dbprettyname = 'Sqlite'; + + protected function getDisplayName(): string { + return 'SQLite'; + } public function validate(array $config): array { return []; From a5c4640be7c849a9caf8ab6bba67c0f5fde30bde Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 10:08:17 -0500 Subject: [PATCH 08/15] chore(setup/PostgreSQL): switch from $dbprettyname to getDisplayName Signed-off-by: Josh --- lib/private/Setup/PostgreSQL.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/private/Setup/PostgreSQL.php b/lib/private/Setup/PostgreSQL.php index 5ace7f6bcbee3..570d1680396e2 100644 --- a/lib/private/Setup/PostgreSQL.php +++ b/lib/private/Setup/PostgreSQL.php @@ -15,7 +15,10 @@ use OCP\Server; class PostgreSQL extends AbstractDatabase { - public $dbprettyname = 'PostgreSQL'; + + protected function getDisplayName(): string { + return 'PostgreSQL'; + } /** * @throws DatabaseSetupException From 55268455a6916401ae034f7ddd9dc2c6d1b2bc53 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 10:23:04 -0500 Subject: [PATCH 09/15] refactor(setup/AbstractDB): early return + override comment in validateDatabaseName() Signed-off-by: Josh --- lib/private/Setup/AbstractDatabase.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index 1739b1ef370f7..495dc7b388b5b 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -69,11 +69,19 @@ protected function validateDatabaseName(array $config): array { $dbName = $config['dbname'] ?? ''; + if (empty($dbName)) { + return $errors; + } + // Avoid downsides of supporting database names with dots (`.`) - if (!empty($dbName) && str_contains($dbName, '.')) { + if (str_contains($dbName, '.')) { $errors[] = $this->trans->t('You cannot use dots in the database name %s', [$this->getDisplayName]); } + // Note: Child classes should implement db specific name validations + // (optionally still calling this parent for default validations) + // (e.g. length, characters, casing, starting character, reserved words) + return $errors; } From 1d33bbbda72e214a26c962f6ee98acdd39fbbe45 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 11:26:27 -0500 Subject: [PATCH 10/15] refactor(setup/AbstractDB): split initialize() logic up into helpers - Improved readability - Easier child class customization Also added for certain config keys: a couple clarifying comments and additional error checking Signed-off-by: Josh --- lib/private/Setup/AbstractDatabase.php | 55 +++++++++++++++++--------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index 495dc7b388b5b..32fb20e48c8b1 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -86,31 +86,50 @@ protected function validateDatabaseName(array $config): array { } public function initialize(array $config): void { - $dbUser = $config['dbuser']; - $dbPass = $config['dbpass']; - $dbName = $config['dbname']; - $dbHost = !empty($config['dbhost']) ? $config['dbhost'] : 'localhost'; - $dbPort = !empty($config['dbport']) ? $config['dbport'] : ''; - $dbTablePrefix = $config['dbtableprefix'] ?? 'oc_'; + $dbParams = $this->extractDatabaseParameters($config); - $createUserConfig = $this->config->getValue('setup_create_db_user', true); - // accept `false` both as bool and string, since setting config values from env will result in a string - $this->tryCreateDbUser = $createUserConfig !== false && $createUserConfig !== 'false'; + // Should a database user/credential set be created automatically? + $this->tryCreateDbUser = $this->shouldCreateDbUser(); + // Persist database configuration to config.php $this->config->setValues([ - 'dbname' => $dbName, - 'dbhost' => $dbHost, - 'dbtableprefix' => $dbTablePrefix, + 'dbname' => $dbParams['name'], + 'dbhost' => $dbParams['host'], + 'dbtableprefix' => $dbParams['tablePrefix'], ]); - $this->dbUser = $dbUser; - $this->dbPassword = $dbPass; - $this->dbName = $dbName; - $this->dbHost = $dbHost; - $this->dbPort = $dbPort; - $this->tablePrefix = $dbTablePrefix; + // Set instance properties from database parameters for subsequent operations (e.g. connecting) + $this->setInstanceProperties($dbParams); + } + + protected function extractDatabaseParameters(array $config): array { + return [ + // Guaranteed to exist after validate() (exceptions override initialize() - i.e. SQLite) + 'user' => $config['dbuser'] ?? throw new \InvalidArgumentException('dbuser is required'), + 'name' => $config['dbname'] ?? throw new \InvalidArgumentException('dbname is required'), + // Password can be empty for some setups / code paths + 'pass' => $config['dbpass'] ?? '', + 'host' => !empty($config['dbhost']) ? $config['dbhost'] : 'localhost', + 'port' => !empty($config['dbport']) ? $config['dbport'] : '', + 'tablePrefix' => $config['dbtableprefix'] ?? 'oc_', + ]; + } + + protected function shouldCreateDbUser(): bool { + $createUserConfig = $this->config->getValue('setup_create_db_user', true); + // Accept `false` both as bool and string, since env vars result in strings + return $createUserConfig !== false && $createUserConfig !== 'false'; } + protected function setInstanceProperties(array $dbParams): void { + $this->dbUser = $dbParams['user']; + $this->dbPassword = $dbParams['pass']; + $this->dbName = $$dbParams['name']; + $this->dbHost = $dbParams['host']; + $this->dbPort = $dbParams['port']; + $this->tablePrefix = $dbParams['tablePrefix']; + } + /** * @param array $configOverwrite * @return \OC\DB\Connection From c2067e1889be26036f5ffd9cdd7c5da36a000a0d Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 16:46:55 -0500 Subject: [PATCH 11/15] refactor(setup/AbstractDB): extract port/socket handling logic Also: - add some helpful inline comments - simplify primary/replica param merging (same outcome) Signed-off-by: Josh --- lib/private/Setup/AbstractDatabase.php | 53 +++++++++++++++++--------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index 32fb20e48c8b1..1dd838ccb094b 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -75,7 +75,7 @@ protected function validateDatabaseName(array $config): array { // Avoid downsides of supporting database names with dots (`.`) if (str_contains($dbName, '.')) { - $errors[] = $this->trans->t('You cannot use dots in the database name %s', [$this->getDisplayName]); + $errors[] = $this->trans->t('You cannot use dots in the database name %s', [$this->getDisplayName()]); } // Note: Child classes should implement db specific name validations @@ -124,7 +124,7 @@ protected function shouldCreateDbUser(): bool { protected function setInstanceProperties(array $dbParams): void { $this->dbUser = $dbParams['user']; $this->dbPassword = $dbParams['pass']; - $this->dbName = $$dbParams['name']; + $this->dbName = $dbParams['name']; $this->dbHost = $dbParams['host']; $this->dbPort = $dbParams['port']; $this->tablePrefix = $dbParams['tablePrefix']; @@ -135,6 +135,7 @@ protected function setInstanceProperties(array $dbParams): void { * @return \OC\DB\Connection */ protected function connect(array $configOverwrite = []): Connection { + // Build base connection parameters $connectionParams = [ 'host' => $this->dbHost, 'user' => $this->dbUser, @@ -143,31 +144,49 @@ protected function connect(array $configOverwrite = []): Connection { 'dbname' => $this->dbName ]; - // adding port support through installer + // Apply port and socket configuration + $connectionParams = $this->applyPortAndSocketConfig($connectionParams); + + // Apply any caller-provided overrides (e.g., dbname => null) + $connectionParams = array_merge($connectionParams, $configOverwrite); + + // Configure for primary/replica topology (both point to same server during install) + $connectionParams['primary'] = $connectionParams; + $connectionParams['replica'] = [$connectionParams]; + + // Create and return the connection + $cf = new ConnectionFactory($this->config); + $connection = $cf->getConnection($this->config->getValue('dbtype', 'sqlite'), $connectionParams); + $connection->ensureConnectedToPrimary(); + return $connection; + } + + protected function applyPortAndSocketConfig(array $params): array { + // Check if port/socket is specified in the dedicated port field (only used by installer) if (!empty($this->dbPort)) { if (ctype_digit($this->dbPort)) { - $connectionParams['port'] = $this->dbPort; + $params['port'] = $this->dbPort; } else { - $connectionParams['unix_socket'] = $this->dbPort; + $params['unix_socket'] = $this->dbPort; } - } elseif (strpos($this->dbHost, ':')) { - // Host variable may carry a port or socket. + return $params; + } + + // Check if port/socket is embedded in the hostname (e.g., "localhost:3306") + if (str_contains($this->dbHost, ':')) { [$host, $portOrSocket] = explode(':', $this->dbHost, 2); + $params['host'] = $host; + // Host variable may carry a port or socket. if (ctype_digit($portOrSocket)) { - $connectionParams['port'] = $portOrSocket; + $params['port'] = $portOrSocket; } else { - $connectionParams['unix_socket'] = $portOrSocket; + $params['unix_socket'] = $portOrSocket; } - $connectionParams['host'] = $host; + return $params; } - $connectionParams = array_merge($connectionParams, $configOverwrite); - $connectionParams = array_merge($connectionParams, ['primary' => $connectionParams, 'replica' => [$connectionParams]]); - $cf = new ConnectionFactory($this->config); - $connection = $cf->getConnection($this->config->getValue('dbtype', 'sqlite'), $connectionParams); - $connection->ensureConnectedToPrimary(); - return $connection; + // Shouldn't reach here... } - + abstract public function setupDatabase(); public function runMigrations(?IOutput $output = null) { From d3ce30b46a6b1c80da33e64997507c9ed984ca5b Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 16:56:01 -0500 Subject: [PATCH 12/15] feat(setup/AbstractDB): add param debug logging to connect() Signed-off-by: Josh --- lib/private/Setup/AbstractDatabase.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index 1dd838ccb094b..6330a454204ea 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -154,9 +154,18 @@ protected function connect(array $configOverwrite = []): Connection { $connectionParams['primary'] = $connectionParams; $connectionParams['replica'] = [$connectionParams]; + $dbType = $this->config->getValue('dbtype', 'sqlite'); + + $this->logger->debug('Creating database connection', [ + 'dbtype' => $dbType, + 'host' => $connectionParams['host'] ?? 'unknown', + 'port' => $connectionParams['port'] ?? $connectionParams['unix_socket'] ?? 'default', + 'dbname' => $connectionParams['dbname'] ?? 'none', + ]); + // Create and return the connection $cf = new ConnectionFactory($this->config); - $connection = $cf->getConnection($this->config->getValue('dbtype', 'sqlite'), $connectionParams); + $connection = $cf->getConnection($dbType, $connectionParams); $connection->ensureConnectedToPrimary(); return $connection; } From 46b618520276ba5681ec79e80e0a620275fdf377 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 22:04:40 -0500 Subject: [PATCH 13/15] refactor(setup/AbstractDB): add logging and docs to runMigrations Signed-off-by: Josh --- lib/private/Setup/AbstractDatabase.php | 48 +++++++++++++++++++++----- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index 6330a454204ea..960616c7cecf0 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -34,8 +34,18 @@ public function __construct( ) { } + /** + * Returns the display name of the database system (e.g., "MySQL/MariaDB", "PostgreSQL") + */ abstract protected function getDisplayName(): string; + + /** + * Validates the database configuration + * + * @param array $config Configuration array containing database credentials and settings + * @return array Array of validation error messages (empty if valid) + */ public function validate(array $config): array { $errors = []; @@ -131,8 +141,7 @@ protected function setInstanceProperties(array $dbParams): void { } /** - * @param array $configOverwrite - * @return \OC\DB\Connection + * @param array $configOverwrite Optional parameters to override (e.g., ['dbname' => null]) */ protected function connect(array $configOverwrite = []): Connection { // Build base connection parameters @@ -195,14 +204,35 @@ protected function applyPortAndSocketConfig(array $params): array { } // Shouldn't reach here... } - - abstract public function setupDatabase(); - public function runMigrations(?IOutput $output = null) { - if (!is_dir(\OC::$SERVERROOT . '/core/Migrations')) { - return; + /** + * Sets up the database (creates database, users, etc.) + * + * Must be implemented by database-specific child classes + */ + abstract public function setupDatabase(): void; + + /** + * @throws \Exception If migration fails (handled by caller) + */ + public function runMigrations(?IOutput $output = null): void { + $migrationsPath = \OC::$SERVERROOT . '/core/Migrations'; + + if (!is_dir($migrationsPath)) { + $this->logger->debug('Skipping migrations - directory not found: {path}', [ + 'path' => $migrationsPath, + ]); + return; // @todo: should we throw an Exception here instead to let caller decide? } - $ms = new MigrationService('core', Server::get(Connection::class), $output); - $ms->migrate('latest', true); + + $this->logger->info('Starting core database migrations'); + + $migrationService = new MigrationService('core', Server::get(Connection::class), $output); + + // Migrate to latest version, applying schema changes only + // (no data migrations needed for fresh install) + $migrationService->migrate('latest', true); + + $this->logger->info('Core database migrations completed successfully'); } } From 047d464240940df3cc937853464bcab9892844a2 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 22:15:47 -0500 Subject: [PATCH 14/15] chore(setup/AbstractDB): drop fixed psalm-baseline entries Signed-off-by: Josh --- build/psalm-baseline.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index c837e74952171..2ac39d475d4f3 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -3874,12 +3874,6 @@ dbPort)]]> - - dbprettyname]]> - dbprettyname]]> - dbprettyname]]> - dbprettyname]]> - From edbb1e282199d680616e71742fae9da718f2c054 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 18 Feb 2026 22:32:10 -0500 Subject: [PATCH 15/15] chore(Setup/AbstractDB): fixup for cs and psalm Signed-off-by: Josh --- lib/private/Setup/AbstractDatabase.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index 960616c7cecf0..c5616d0a0cee3 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -39,10 +39,9 @@ public function __construct( */ abstract protected function getDisplayName(): string; - /** * Validates the database configuration - * + * * @param array $config Configuration array containing database credentials and settings * @return array Array of validation error messages (empty if valid) */ @@ -52,7 +51,7 @@ public function validate(array $config): array { $errors = array_merge($errors, $this->validateRequiredFields($config)); $errors = array_merge($errors, $this->validateDatabaseName($config)); - return $errors; + return $errors; } protected function validateRequiredFields(array $config): array { @@ -138,7 +137,7 @@ protected function setInstanceProperties(array $dbParams): void { $this->dbHost = $dbParams['host']; $this->dbPort = $dbParams['port']; $this->tablePrefix = $dbParams['tablePrefix']; - } + } /** * @param array $configOverwrite Optional parameters to override (e.g., ['dbname' => null]) @@ -194,20 +193,19 @@ protected function applyPortAndSocketConfig(array $params): array { if (str_contains($this->dbHost, ':')) { [$host, $portOrSocket] = explode(':', $this->dbHost, 2); $params['host'] = $host; - // Host variable may carry a port or socket. + // Host variable may carry a port or socket. if (ctype_digit($portOrSocket)) { $params['port'] = $portOrSocket; } else { $params['unix_socket'] = $portOrSocket; } - return $params; } - // Shouldn't reach here... + return $params; } /** * Sets up the database (creates database, users, etc.) - * + * * Must be implemented by database-specific child classes */ abstract public function setupDatabase(): void; @@ -228,7 +226,7 @@ public function runMigrations(?IOutput $output = null): void { $this->logger->info('Starting core database migrations'); $migrationService = new MigrationService('core', Server::get(Connection::class), $output); - + // Migrate to latest version, applying schema changes only // (no data migrations needed for fresh install) $migrationService->migrate('latest', true);