diff --git a/core/lib/Drupal/Core/Command/DevInstallCommand.php b/core/lib/Drupal/Core/Command/DevInstallCommand.php index 1816dc76f3..032e9086d0 100644 --- a/core/lib/Drupal/Core/Command/DevInstallCommand.php +++ b/core/lib/Drupal/Core/Command/DevInstallCommand.php @@ -2,16 +2,15 @@ namespace Drupal\Core\Command; +use Drupal\Core\Database\ConnectionNotDefinedException; use Drupal\Core\Database\Database; use Drupal\Core\DrupalKernel; +use Drupal\Core\Site\Settings; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Question\ConfirmationQuestion; -use Symfony\Component\HttpFoundation\Request; /** * Installs a Drupal site for local testing/development. @@ -44,7 +43,6 @@ protected function configure() { ->setDescription('Installs a Drupal dev site. This is not meant for production or any custom development. It is a quick and easy way to get Drupal running.') ->addOption('install_profile', NULL, InputOption::VALUE_OPTIONAL, 'Install profile to install the site in. Defaults to standard', 'standard') ->addOption('langcode', NULL, InputOption::VALUE_OPTIONAL, 'The language to install the site in. Defaults to en', 'en') - ->addOption('force', 'y', InputOption::VALUE_NONE, 'Force overriding the existing installation') ->addOption('site_name', NULL, InputOption::VALUE_OPTIONAL, 'Set the site name.', 'Drupal') ->addUsage('--install_profile demo_umami --langcode fr'); @@ -55,15 +53,22 @@ protected function configure() { * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->changeRoot(); - - if (!$input->getOption('force') && $this->isDrupalInstalled()) { - $question_helper = new QuestionHelper(); - if (!$question_helper->ask($input, $output, new ConfirmationQuestion('There is already an existing installation. Confirm whether you want to override it. (y/N) ', FALSE))) { - return; - } + if (!extension_loaded('pdo_sqlite')) { + $output->getErrorOutput()->writeln('You need to have sqlite installed.'); + return; } + + // Change the directory to the Drupal root. + chdir(dirname(dirname(dirname(dirname(dirname(__DIR__)))))); + // Check whether there is already an installation. + if ($this->isDrupalInstalled()) { + // Do not fail if the site is already installed so this command can be + // chained with DevStartCommand. + $output->writeln('Drupal is already installed.'); + return; + } + $this->install($this->classLoader, $output, $input->getOption('install_profile'), $input->getOption('langcode'), $this->getSitePath(), $input->getOption('site_name')); } @@ -73,24 +78,19 @@ protected function execute(InputInterface $input, OutputInterface $output) { * @return bool */ protected function isDrupalInstalled() { - $request = Request::createFromGlobals(); - DrupalKernel::createFromRequest($request, $this->classLoader, 'prod'); - + try { + $kernel = new DrupalKernel('prod', $this->classLoader, FALSE); + $kernel::bootEnvironment(); + $kernel->setSitePath($this->getSitePath()); + Settings::initialize($kernel->getAppRoot(), $kernel->getSitePath(), $this->classLoader); + $kernel->boot(); + } + catch (ConnectionNotDefinedException $e) { + return FALSE; + } return !empty(Database::getConnectionInfo()); } - /** - * Changes the directory to the Drupal root. - * - * @return string - * Returns the path to the Drupal root. - */ - protected function changeRoot() { - $root = dirname(dirname(dirname(dirname(dirname(__DIR__))))); - chdir($root); - return $root; - } - /** * Installs Drupal with specified installation profile. * @@ -106,7 +106,6 @@ protected function changeRoot() { * (optional) The path to install the site to, like 'sites/default'. */ protected function install($class_loader, ConsoleOutputInterface $output, $profile = 'standard', $langcode = 'en', $site_path = 'sites/default', $site_name = 'Drupal') { - $parameters = [ 'interactive' => FALSE, 'site_path' => $site_path, @@ -140,36 +139,17 @@ protected function install($class_loader, ConsoleOutputInterface $output, $profi ], ]; - require_once 'core/includes/install.core.inc'; - - if (!extension_loaded('pdo_sqlite')) { - $output->getErrorOutput()->writeln('You need to have sqlite installed.'); - return; - } - - // If we have a custom site path, we need to create the sites directory - // first. - if ($site_path && !file_exists($site_path)) { + // Create the directory and settings.php if not there so that the installer + // works. + if (!file_exists($site_path)) { mkdir($site_path, 0775); } - - if (file_exists("{$site_path}/settings.php")) { - $result = unlink("{$site_path}/settings.php"); - if ($result === FALSE) { - $output->getErrorOutput()->writeln('Removing settings.php failed, please do it manually ...'); - return; - } - } - copy("sites/default/default.settings.php", "{$site_path}/settings.php"); - if (file_exists("{$site_path}/files/.sqlite")) { - $result = unlink("{$site_path}/files/.sqlite"); - if ($result === FALSE) { - $output->getErrorOutput()->writeln('Removing .sqlite failed, please do it manually ...'); - return; - } + if (!file_exists("{$site_path}/settings.php")) { + copy("sites/default/default.settings.php", "{$site_path}/settings.php"); } $output->writeln('Drupal installation started. This could take a minute.'); + require_once 'core/includes/install.core.inc'; install_drupal($class_loader, $parameters); $output->writeln('Drupal successfully installed.'); } diff --git a/core/lib/Drupal/Core/Command/DevStartCommand.php b/core/lib/Drupal/Core/Command/DevStartCommand.php index 056bc7cf12..0652cbf517 100644 --- a/core/lib/Drupal/Core/Command/DevStartCommand.php +++ b/core/lib/Drupal/Core/Command/DevStartCommand.php @@ -65,8 +65,7 @@ protected function execute(InputInterface $input, OutputInterface $output) { * Exception thrown if kernel does not boot. */ protected function boot() { - $root = dirname(dirname(dirname(dirname(dirname(__DIR__))))); - chdir($root); + chdir(dirname(dirname(dirname(dirname(dirname(__DIR__)))))); $kernel = new DrupalKernel('prod', $this->classLoader, FALSE); $kernel::bootEnvironment(); diff --git a/core/tests/Drupal/Tests/Core/Command/DevSiteTest.php b/core/tests/Drupal/Tests/Core/Command/DevSiteTest.php index 49f154026c..c0f309963f 100644 --- a/core/tests/Drupal/Tests/Core/Command/DevSiteTest.php +++ b/core/tests/Drupal/Tests/Core/Command/DevSiteTest.php @@ -30,32 +30,33 @@ public function testDevSiteCommands() { $test_db = new TestDatabase(); // Install a site. - $command = "{$php} core/scripts/dev-site.php install --force --install_profile=testing --site_name='Test site {$test_db->getDatabasePrefix()}'"; - $process = new Process($command, NULL, ['DRUPAL_DEV_SITE_PATH' => $test_db->getTestSitePath()]); - $process->inheritEnvironmentVariables(); - $process->setTimeout(500); - $result = $process->run(); + $install_command = "{$php} core/scripts/dev-site.php install --install_profile=testing --site_name='Test site {$test_db->getDatabasePrefix()}'"; + $install_process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $test_db->getTestSitePath()]); + $install_process->inheritEnvironmentVariables(); + $install_process->setTimeout(500); + $result = $install_process->run(); $this->assertSame(0, $result); - $this->assertContains('Drupal installation started. This could take a minute.', $process->getOutput()); - $this->assertContains('Drupal successfully installed.', $process->getOutput()); + $this->assertContains('Drupal installation started. This could take a minute.', $install_process->getOutput()); + $this->assertContains('Drupal successfully installed.', $install_process->getOutput()); // Run the PHP built-in webserver. - $process = new Process("{$php} core/scripts/dev-site.php start --suppress_login --no_tty", NULL, ['DRUPAL_DEV_SITE_PATH' => $test_db->getTestSitePath()]); - $process->inheritEnvironmentVariables(); - $process->start(); + $start_command = "{$php} core/scripts/dev-site.php start --suppress_login --no_tty"; + $start_process = new Process($start_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $test_db->getTestSitePath()]); + $start_process->inheritEnvironmentVariables(); + $start_process->start(); $guzzle = new Client(); $port = FALSE; $output = ''; - while ($process->isRunning()) { - $output .= $process->getOutput(); - if (preg_match('/localhost:(\d+)/', $process->getOutput(), $match)) { + while ($start_process->isRunning()) { + $output .= $start_process->getOutput(); + if (preg_match('/localhost:(\d+)/', $start_process->getOutput(), $match)) { $port = $match[1]; break; } // Wait for more output. sleep(1); } - $this->assertNotFalse($port, "Web server running.: " . $output . "\n\nError output\n" . $process->getErrorOutput()); + $this->assertNotFalse($port, "Web server running.: " . $output . "\n\nError output\n" . $start_process->getErrorOutput()); // Give the server a couple of seconds to be ready. sleep(2); @@ -71,7 +72,23 @@ public function testDevSiteCommands() { $response = $guzzle->get('http://localhost:' . $port, ['cookies' => $cookieJar]); $content = (string) $response->getBody(); $this->assertContains('Test site ' . $test_db->getDatabasePrefix(), $content); - $process->stop(); + + // Try to re-install over the top of an existing site. + $install_command = "{$php} core/scripts/dev-site.php install --install_profile=testing --site_name='Test another site {$test_db->getDatabasePrefix()}'"; + $install_process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $test_db->getTestSitePath()]); + $install_process->inheritEnvironmentVariables(); + $install_process->setTimeout(500); + $result = $install_process->run(); + $this->assertSame(0, $result); + $this->assertContains('Drupal is already installed.', $install_process->getOutput()); + + // Ensure the site name has not changed. + $response = $guzzle->get('http://localhost:' . $port, ['cookies' => $cookieJar]); + $content = (string) $response->getBody(); + $this->assertContains('Test site ' . $test_db->getDatabasePrefix(), $content); + + // Stop the web server. + $start_process->stop(); // @todo use the tear down command from // https://www.drupal.org/project/drupal/issues/2926633