diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index fb18fe3..db35fd7 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -6,7 +6,6 @@ use Drupal\Core\Config\BootstrapConfigStorageFactory; use Drupal\Core\Database\Database; use Drupal\Core\Database\DatabaseExceptionWrapper; -use Drupal\Core\Database\Install\TaskException; use Drupal\Core\Form\FormState; use Drupal\Core\Installer\Exception\AlreadyInstalledException; use Drupal\Core\Installer\Exception\InstallerException; @@ -1133,14 +1132,24 @@ function install_database_errors($database, $settings_file) { // Run tasks associated with the database type. Any errors are caught in the // calling function. Database::addConnectionInfo('default', 'default', $database); - try { - db_run_tasks($driver); - } - catch (TaskException $e) { + + $errors = db_installer_object($driver)->runTasks(); + 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 installation handbook, or contact your hosting provider.{% endtrans%}{{ errors }}', + '#context' => [ + 'errors' => [ + '#theme' => 'item_list', + '#items' => $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 // them in the error array with standard numeric keys. - $errors[$driver . '][0'] = $e->getMessage(); + $errors[$driver . '][0'] = \Drupal::service('renderer')->renderPlain($error_message); } } return $errors; diff --git a/core/includes/install.inc b/core/includes/install.inc index 31d472a..77e0b70 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -1069,19 +1069,6 @@ function install_profile_info($profile, $langcode = 'en') { } /** - * Ensures the environment for a Drupal database on a predefined connection. - * - * This will run tasks that check that Drupal can perform all of the functions - * on a database, that Drupal needs. Tasks include simple checks like CREATE - * TABLE to database specific functions like stored procedures and client - * encoding. - */ -function db_run_tasks($driver) { - db_installer_object($driver)->runTasks(); - return TRUE; -} - -/** * Returns a database installer object. * * @param $driver diff --git a/core/lib/Drupal/Core/Database/Install/TaskException.php b/core/lib/Drupal/Core/Database/Install/TaskException.php deleted file mode 100644 index cbf5c1a..0000000 --- a/core/lib/Drupal/Core/Database/Install/TaskException.php +++ /dev/null @@ -1,13 +0,0 @@ - $task['function']))); + $this->fail(t("Failed to run all tasks against the database server. The task %task wasn't found.", array('%task' => $task['function']))); } } } - // Check for failed results and compile message - $message = ''; - foreach ($this->results as $result => $success) { - if (!$success) { - $message = SafeMarkup::isSafe($result) ? $result : SafeMarkup::checkPlain($result); - } - } - if (!empty($message)) { - $message = SafeMarkup::set('Resolve all issues below to continue the installation. For help configuring your database server, see the installation handbook, or contact your hosting provider.' . $message); - throw new TaskException($message); - } + // Filter out the success messages from results. + $errors = array_filter($this->results, function ($value) { + return !$value; + }); + return array_keys($errors); } /** diff --git a/core/modules/simpletest/src/InstallerTestBase.php b/core/modules/simpletest/src/InstallerTestBase.php index c340c92..7207555 100644 --- a/core/modules/simpletest/src/InstallerTestBase.php +++ b/core/modules/simpletest/src/InstallerTestBase.php @@ -138,33 +138,33 @@ protected function setUp() { // Configure site. $this->setUpSite(); - // Import new settings.php written by the installer. - $request = Request::createFromGlobals(); - $class_loader = require $this->container->get('app.root') . '/autoload.php'; - Settings::initialize($this->container->get('app.root'), DrupalKernel::findSitePath($request), $class_loader); - foreach ($GLOBALS['config_directories'] as $type => $path) { - $this->configDirectories[$type] = $path; + if ($this->isInstalled) { + // Import new settings.php written by the installer. + $request = Request::createFromGlobals(); + $class_loader = require $this->container->get('app.root') . '/autoload.php'; + Settings::initialize($this->container->get('app.root'), DrupalKernel::findSitePath($request), $class_loader); + foreach ($GLOBALS['config_directories'] as $type => $path) { + $this->configDirectories[$type] = $path; + } + + // After writing settings.php, the installer removes write permissions + // from the site directory. To allow drupal_generate_test_ua() to write + // a file containing the private key for drupal_valid_test_ua(), the site + // directory has to be writable. + // WebTestBase::tearDown() will delete the entire test site directory. + // Not using File API; a potential error must trigger a PHP warning. + chmod($this->container->get('app.root') . '/' . $this->siteDirectory, 0777); + $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE); + $this->kernel->prepareLegacyRequest($request); + $this->container = $this->kernel->getContainer(); + + // Manually configure the test mail collector implementation to prevent + // tests from sending out e-mails and collect them in state instead. + $this->container->get('config.factory') + ->getEditable('system.mail') + ->set('interface.default', 'test_mail_collector') + ->save(); } - - // After writing settings.php, the installer removes write permissions - // from the site directory. To allow drupal_generate_test_ua() to write - // a file containing the private key for drupal_valid_test_ua(), the site - // directory has to be writable. - // WebTestBase::tearDown() will delete the entire test site directory. - // Not using File API; a potential error must trigger a PHP warning. - chmod($this->container->get('app.root') . '/' . $this->siteDirectory, 0777); - $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE); - $this->kernel->prepareLegacyRequest($request); - $this->container = $this->kernel->getContainer(); - $config = $this->container->get('config.factory'); - - // Manually configure the test mail collector implementation to prevent - // tests from sending out e-mails and collect them in state instead. - $config->getEditable('system.mail') - ->set('interface.default', 'test_mail_collector') - ->save(); - - $this->isInstalled = TRUE; } /** @@ -196,11 +196,14 @@ protected function setUpSettings() { } /** - * Installer step: Configure site. + * Final installer step: Configure site. */ protected function setUpSite() { $edit = $this->translatePostValues($this->parameters['forms']['install_configure_form']); $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']); + // If we've got to this point the site is installed using the regular + // installation workflow. + $this->isInstalled = TRUE; } /** diff --git a/core/modules/system/src/Tests/Installer/InstallerDatabaseErrorMessagesTest.php b/core/modules/system/src/Tests/Installer/InstallerDatabaseErrorMessagesTest.php new file mode 100644 index 0000000..2452c40 --- /dev/null +++ b/core/modules/system/src/Tests/Installer/InstallerDatabaseErrorMessagesTest.php @@ -0,0 +1,46 @@ +query('CREATE TABLE {drupal_install_test} (id int NULL)'); + parent::setUpSettings(); + } + + /** + * @{inheritdoc} + */ + protected function setUpSite() { + // This step should not appear as we had a failure on the settings screen. + } + + /** + * Verifies that the error message in the settings step is correct. + */ + public function testSetUpSettingsErrorMessage() { + $this->assertRaw('