diff --git a/CHANGELOG-3.1.md b/CHANGELOG-3.1.md index 4634e7cef0..0e58924332 100644 --- a/CHANGELOG-3.1.md +++ b/CHANGELOG-3.1.md @@ -16,6 +16,7 @@ - [composer] Correct Composer 2 compatibilty. - [translations] Fix non-working extraction of translation with `@Translate` annotation (#4694). - [CoreBundle] Added clearing of OPCache (if in use) to standard clearcache operation (#4507). + - [CoreInstallerBundle] Use DBAL for cross-database determination of existing tables (#4688). - [Admin] Add missing numeric casts to admin module setting usages (#4709). - [Groups] Fix some non-working translations (#4694). - [Menu] Fixed handling of menu items without URI in custom request voter. diff --git a/src/Zikula/CoreInstallerBundle/Validator/Constraints/ValidPdoConnectionValidator.php b/src/Zikula/CoreInstallerBundle/Validator/Constraints/ValidPdoConnectionValidator.php index cf737dc678..a4fa24852d 100644 --- a/src/Zikula/CoreInstallerBundle/Validator/Constraints/ValidPdoConnectionValidator.php +++ b/src/Zikula/CoreInstallerBundle/Validator/Constraints/ValidPdoConnectionValidator.php @@ -13,8 +13,9 @@ namespace Zikula\Bundle\CoreInstallerBundle\Validator\Constraints; -use PDO; -use PDOException; +use Doctrine\DBAL\Configuration; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\DriverManager; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Contracts\Translation\TranslatorInterface; @@ -40,31 +41,42 @@ public function validate($object, Constraint $constraint) return; } - $dbName = $object['database_name']; - $dsn = $object['database_driver'] . ':host=' . $object['database_host'] . ';dbname=' . $dbName; + $connectionParams = [ + 'url' => $this->buildDsn($object), + ]; + try { - $dbh = new PDO($dsn, $object['database_user'], $object['database_password']); - $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $sql = in_array($object['database_driver'], ['mysql', 'mysqli']) - ? 'SHOW TABLES FROM `' . $dbName . "` LIKE '%'" - : 'SHOW TABLES FROM ' . $dbName . " LIKE '%'"; - $tables = $dbh->query($sql); - if (!is_object($tables)) { - $this->context - ->buildViolation($this->trans('Error! Determination existing tables failed.') . ' SQL: ' . $sql) - ->addViolation() - ; - } elseif ($tables->rowCount() > 0) { + $connection = DriverManager::getConnection($connectionParams, new Configuration()); + if (!$connection->connect()) { $this->context - ->buildViolation($this->trans('Error! The database exists and contains tables. Please delete all tables before proceeding or select a new database.')) + ->buildViolation($this->trans('Error! Could not connect to the database. Please check that you have entered the correct database information and try again.')) ->addViolation() ; + } else { + $tables = $connection->getSchemaManager()->listTableNames(); + if (0 < count($tables)) { + $this->context + ->buildViolation($this->trans('Error! The database exists and contains tables. Please delete all tables before proceeding or select a new database.')) + ->addViolation() + ; + } } - } catch (PDOException $exception) { + } catch (DBALException $exception) { $this->context - ->buildViolation($this->trans('Error! Could not connect to the database. Please check that you have entered the correct database information and try again. ') . $exception->getMessage()) + ->buildViolation($this->trans('Error! Could not connect to the database. Please check that you have entered the correct database information and try again.') . ' ' . $exception->getMessage()) ->addViolation() ; } } + + private function buildDsn($object): string + { + $dsn = $object['database_driver'] . '://' . $object['database_user'] . ':' . $object['database_password'] + . '@' . $object['database_host'] . (!empty($object['database_port']) ? ':' . $object['database_port'] : '') + . '/' . $object['database_name'] + . '?serverVersion=' . ($object['database_server_version'] ?? '5.7') // any value for serverVersion will work (bypasses DBALException) + ; + + return $dsn; + } } diff --git a/translations/messages.en.yaml b/translations/messages.en.yaml index 206566ee57..806b8ed81d 100644 --- a/translations/messages.en.yaml +++ b/translations/messages.en.yaml @@ -603,7 +603,7 @@ Entity: Entity 'Error! A category by this name already exists.': 'Error! A category by this name already exists.' 'Error! Activation of %name% not allowed.': 'Error! Activation of %name% not allowed.' 'Error! Controller helper needs a request.': 'Error! Controller helper needs a request.' -'Error! Could not connect to the database. Please check that you have entered the correct database information and try again. ': 'Error! Could not connect to the database. Please check that you have entered the correct database information and try again. ' +'Error! Could not connect to the database. Please check that you have entered the correct database information and try again.': 'Error! Could not connect to the database. Please check that you have entered the correct database information and try again.' 'Error! Could not determine workflow actions.': 'Error! Could not determine workflow actions.' 'Error! Could not get module name for id %moduleId%.': 'Error! Could not get module name for id %moduleId%.' 'Error! Could not load data for %extension%.': 'Error! Could not load data for %extension%.' @@ -614,7 +614,6 @@ Entity: Entity 'Error! Could not save configuration: unknown permission rule ID.': 'Error! Could not save configuration: unknown permission rule ID.' 'Error! Creation attempt failed.': 'Error! Creation attempt failed.' 'Error! Deletion attempt failed.': 'Error! Deletion attempt failed.' -'Error! Determination existing tables failed.': 'Error! Determination existing tables failed.' 'Error! In your permalink settings, strings cannot be terminated with a comma.': 'Error! In your permalink settings, strings cannot be terminated with a comma.' 'Error! In your permalink settings, the search list and the replacement list for permalink cleansing have a different number of comma-separated elements. If you have 3 elements in the search list then there must be 3 elements in the replacement list.': 'Error! In your permalink settings, the search list and the replacement list for permalink cleansing have a different number of comma-separated elements. If you have 3 elements in the search list then there must be 3 elements in the replacement list.' 'Error! Invalid %identifier% received.': 'Error! Invalid %identifier% received.'