Skip to content

Commit

Permalink
use DBAL for retrieving list of existing database tables, fixes #4688
Browse files Browse the repository at this point in the history
  • Loading branch information
Guite committed Oct 13, 2021
1 parent ee5779d commit f77868d
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELOG-3.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
}
3 changes: 1 addition & 2 deletions translations/messages.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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%.'
Expand All @@ -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.'
Expand Down

0 comments on commit f77868d

Please sign in to comment.