From 6fc156e21d94142647eae33c726ad20a319a57cd Mon Sep 17 00:00:00 2001 From: Axel Guckelsberger Date: Wed, 13 Oct 2021 07:54:49 +0200 Subject: [PATCH] use DBAL for retrieving list of existing database tables, fixes #4688 --- .../ValidPdoConnectionValidator.php | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/Validator/Constraints/ValidPdoConnectionValidator.php b/Validator/Constraints/ValidPdoConnectionValidator.php index cf737dc..a4fa248 100644 --- a/Validator/Constraints/ValidPdoConnectionValidator.php +++ b/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; + } }