Commit 1d551dd7 authored by catch's avatar catch

Issue #3120731 by alexpott, japerry, daffie, codersukanta, rfay, xjm,...

Issue #3120731 by alexpott, japerry, daffie, codersukanta, rfay, xjm, tim.plunkett, catch, andypost: Incorrect "Drupal already installed" if any database settings are wrong or unsatisfactory
parent 5d95f2e1
......@@ -20,6 +20,7 @@
use Drupal\Core\Installer\Exception\AlreadyInstalledException;
use Drupal\Core\Installer\Exception\InstallerException;
use Drupal\Core\Installer\Exception\NoProfilesException;
use Drupal\Core\Installer\Form\SiteSettingsForm;
use Drupal\Core\Installer\InstallerKernel;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageManager;
......@@ -520,18 +521,14 @@ function install_begin_request($class_loader, &$install_state) {
// accessing the database before it is set up yet.)
drupal_maintenance_theme();
if ($install_state['database_verified']) {
// Verify the last completed task in the database, if there is one.
$task = install_verify_completed_task();
}
else {
$task = NULL;
// Do not install over a configured settings.php.
if (Database::getConnectionInfo()) {
throw new AlreadyInstalledException($container->get('string_translation'));
}
if (!$install_state['database_verified']) {
// Do not install over an existing installation. The call to
// install_verify_database_ready() will throw an AlreadyInstalledException
// if this is the case.
install_verify_database_ready();
}
// Verify the last completed task in the database, if there is one.
$task = install_verify_completed_task();
// Ensure that the active configuration is empty before installation starts.
if ($install_state['config_verified'] && empty($task)) {
......@@ -1173,16 +1170,28 @@ function install_verify_database_settings($site_path) {
/**
* Verify that the database is ready (no existing Drupal installation).
*
* @throws \Drupal\Core\Installer\Exception\AlreadyInstalledException
* Thrown when the database already has a table that would be created by
* installing the System module.
*/
function install_verify_database_ready() {
$system_schema = system_schema();
end($system_schema);
$table = key($system_schema);
$existing_install = FALSE;
if ($database = Database::getConnectionInfo()) {
if (Database::getConnection()->schema()->tableExists($table)) {
throw new AlreadyInstalledException(\Drupal::service('string_translation'));
try {
$existing_install = Database::getConnection()->schema()->tableExists($table);
}
// Do not trigger an error if the database query fails, since the database
// might not be set up yet.
catch (\Exception $e) {
}
}
if ($existing_install) {
throw new AlreadyInstalledException(\Drupal::service('string_translation'));
}
}
......@@ -2221,6 +2230,25 @@ function install_check_requirements($install_state) {
];
}
}
// Check the database settings if they have been configured in settings.php
// before running the Drupal installer.
if ($database = Database::getConnectionInfo()) {
$request = Request::createFromGlobals();
$site_path = empty($install_state['site_path']) ? DrupalKernel::findSitePath($request, FALSE) : $install_state['site_path'];
$database = $database['default'];
$settings_file = './' . $site_path . '/settings.php';
$errors = install_database_errors($database, $settings_file);
if (count($errors)) {
$error_message = SiteSettingsForm::getDatabaseErrorsTemplate($errors);
$requirements['database_install_errors'] = [
'title' => t('Database settings'),
'description' => $error_message,
'severity' => REQUIREMENT_ERROR,
];
}
}
}
return $requirements;
}
......
......@@ -194,16 +194,7 @@ protected function getDatabaseErrors(array $database, $settings_file) {
$errors = array_diff_key($errors, $form_errors);
if (count($errors)) {
$error_message = [
'#type' => 'inline_template',
'#template' => '{% trans %}Resolve all issues below to continue the installation. For help configuring your database server, see the <a href="https://www.drupal.org/docs/8/install">installation handbook</a>, or contact your hosting provider.{% endtrans%}{{ errors }}',
'#context' => [
'errors' => [
'#theme' => 'item_list',
'#items' => $errors,
],
],
];
$error_message = static::getDatabaseErrorsTemplate($errors);
// These are generic errors, so we do not have any specific key of the
// database connection array to attach them to; therefore, we just put
......@@ -214,6 +205,28 @@ protected function getDatabaseErrors(array $database, $settings_file) {
return $form_errors;
}
/**
* Gets the inline template render array to display the database errors.
*
* @param \Drupal\Core\StringTranslation\TranslatableMarkup[] $errors
* The database errors to list.
*
* @return mixed[]
* The inline template render array to display the database errors.
*/
public static function getDatabaseErrorsTemplate(array $errors) {
return [
'#type' => 'inline_template',
'#template' => '{% trans %}Resolve all issues below to continue the installation. For help configuring your database server, see the <a href="https://www.drupal.org/docs/8/install">installation handbook</a>, or contact your hosting provider.{% endtrans %}{{ errors }}',
'#context' => [
'errors' => [
'#theme' => 'item_list',
'#items' => $errors,
],
],
];
}
/**
* {@inheritdoc}
*/
......
<?php
namespace Drupal\FunctionalTests\Installer;
use Drupal\Core\Database\Database;
/**
* Tests the installer with broken database connection info in settings.php.
*
* @group Installer
*/
class InstallerExistingBrokenDatabaseSettingsTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected function prepareEnvironment() {
parent::prepareEnvironment();
// Pre-configure database credentials in settings.php.
$connection_info = Database::getConnectionInfo();
if ($connection_info['default']['driver'] !== 'mysql') {
$this->markTestSkipped('This test relies on overriding the mysql driver');
}
// Use a database driver that reports a fake database version that does
// not meet requirements.
unset($connection_info['default']['pdo']);
unset($connection_info['default']['init_commands']);
$connection_info['default']['driver'] = 'DrivertestMysqlDeprecatedVersion';
$namespace = 'Drupal\\driver_test\\Driver\\Database\\DrivertestMysqlDeprecatedVersion';
$connection_info['default']['namespace'] = $namespace;
$connection_info['default']['autoload'] = Database::findDriverAutoloadDirectory($namespace, \Drupal::root());
$this->settings['databases']['default'] = (object) [
'value' => $connection_info,
'required' => TRUE,
];
}
/**
* {@inheritdoc}
*/
protected function setUpSettings() {
// This form will never be reached.
return;
}
/**
* {@inheritdoc}
*/
protected function setUpSite() {
// This form will never be reached.
return;
}
/**
* Tests the expected requirements problem.
*/
public function testRequirementsProblem() {
$this->assertSession()->titleEquals('Requirements problem | Drupal');
$this->assertSession()->pageTextContains('Database settings');
$this->assertSession()->pageTextContains('Resolve all issues below to continue the installation. For help configuring your database server,');
$this->assertSession()->pageTextContains('The database server version 10.2.31-MariaDB-1:10.2.31+maria~bionic-log is less than the minimum required version');
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment