5 * Contains \Drupal\AppConsole\Command\Site\InstallCommand.
8 namespace Drupal\Console\Command\Site;
10 use Symfony\Component\Filesystem\Filesystem;
11 use Symfony\Component\Config\Definition\Exception\Exception;
12 use Symfony\Component\Console\Input\InputArgument;
13 use Symfony\Component\Console\Input\InputOption;
14 use Symfony\Component\Console\Input\InputInterface;
15 use Symfony\Component\Console\Output\OutputInterface;
16 use Drupal\Console\Core\Command\ContainerAwareCommand;
17 use Drupal\Core\Database\Database;
18 use Drupal\Core\Installer\Exception\AlreadyInstalledException;
19 use Drupal\Console\Command\Shared\DatabaseTrait;
20 use Drupal\Console\Core\Utils\ConfigurationManager;
21 use Drupal\Console\Extension\Manager;
22 use Drupal\Console\Bootstrap\Drupal;
23 use Drupal\Console\Utils\Site;
24 use Drupal\Console\Core\Utils\DrupalFinder;
26 class InstallCommand extends ContainerAwareCommand
33 protected $extensionManager;
41 * @var ConfigurationManager
43 protected $configurationManager;
51 * InstallCommand constructor.
53 * @param Manager $extensionManager
55 * @param ConfigurationManager $configurationManager
56 * @param string $appRoot
58 public function __construct(
59 Manager $extensionManager,
61 ConfigurationManager $configurationManager,
64 $this->extensionManager = $extensionManager;
66 $this->configurationManager = $configurationManager;
67 $this->appRoot = $appRoot;
68 parent::__construct();
71 protected function configure()
74 ->setName('site:install')
75 ->setDescription($this->trans('commands.site.install.description'))
78 InputArgument::OPTIONAL,
79 $this->trans('commands.site.install.arguments.profile')
84 InputOption::VALUE_REQUIRED,
85 $this->trans('commands.site.install.arguments.langcode')
90 InputOption::VALUE_REQUIRED,
91 $this->trans('commands.site.install.arguments.db-type')
96 InputOption::VALUE_REQUIRED,
97 $this->trans('commands.site.install.arguments.db-file')
102 InputOption::VALUE_OPTIONAL,
103 $this->trans('commands.migrate.execute.options.db-host')
108 InputOption::VALUE_OPTIONAL,
109 $this->trans('commands.migrate.execute.options.db-name')
114 InputOption::VALUE_OPTIONAL,
115 $this->trans('commands.migrate.execute.options.db-user')
120 InputOption::VALUE_OPTIONAL,
121 $this->trans('commands.migrate.execute.options.db-pass')
126 InputOption::VALUE_OPTIONAL,
127 $this->trans('commands.migrate.execute.options.db-prefix')
132 InputOption::VALUE_OPTIONAL,
133 $this->trans('commands.migrate.execute.options.db-port')
138 InputOption::VALUE_REQUIRED,
139 $this->trans('commands.site.install.arguments.site-name')
144 InputOption::VALUE_REQUIRED,
145 $this->trans('commands.site.install.arguments.site-mail')
150 InputOption::VALUE_REQUIRED,
151 $this->trans('commands.site.install.arguments.account-name')
156 InputOption::VALUE_REQUIRED,
157 $this->trans('commands.site.install.arguments.account-mail')
162 InputOption::VALUE_REQUIRED,
163 $this->trans('commands.site.install.arguments.account-pass')
168 InputOption::VALUE_NONE,
169 $this->trans('commands.site.install.arguments.force')
171 ->setAliases(['si']);
177 protected function interact(InputInterface $input, OutputInterface $output)
180 $profile = $input->getArgument('profile');
182 $profiles = $this->extensionManager
190 $profiles = array_filter(
192 function ($profile) {
193 return strpos($profile, 'testing') !== 0;
197 $profile = $this->getIo()->choice(
198 $this->trans('commands.site.install.questions.profile'),
199 array_values($profiles)
202 $input->setArgument('profile', $profile);
206 $langcode = $input->getOption('langcode');
208 $languages = $this->site->getStandardLanguages();
209 $defaultLanguage = $this->configurationManager
211 ->get('application.language');
213 $langcode = $this->getIo()->choiceNoList(
214 $this->trans('commands.site.install.questions.langcode'),
216 $languages[$defaultLanguage]
219 $input->setOption('langcode', $langcode);
222 // Use default database setting if is available
223 $database = Database::getConnectionInfo();
224 if (empty($database['default'])) {
226 $dbType = $input->getOption('db-type');
228 $databases = $this->site->getDatabaseTypes();
229 $dbType = $this->getIo()->choice(
230 $this->trans('commands.migrate.setup.questions.db-type'),
231 array_column($databases, 'name')
234 foreach ($databases as $dbIndex => $database) {
235 if ($database['name'] == $dbType) {
240 $input->setOption('db-type', $dbType);
243 if ($dbType === 'sqlite') {
245 $dbFile = $input->getOption('db-file');
247 $dbFile = $this->getIo()->ask(
248 $this->trans('commands.migrate.execute.questions.db-file'),
249 'sites/default/files/.ht.sqlite'
251 $input->setOption('db-file', $dbFile);
255 $dbHost = $input->getOption('db-host');
257 $dbHost = $this->dbHostQuestion();
258 $input->setOption('db-host', $dbHost);
262 $dbName = $input->getOption('db-name');
264 $dbName = $this->dbNameQuestion();
265 $input->setOption('db-name', $dbName);
269 $dbUser = $input->getOption('db-user');
271 $dbUser = $this->dbUserQuestion();
272 $input->setOption('db-user', $dbUser);
276 $dbPass = $input->getOption('db-pass');
278 $dbPass = $this->dbPassQuestion();
279 $input->setOption('db-pass', $dbPass);
283 $dbPort = $input->getOption('db-port');
285 $dbPort = $this->dbPortQuestion();
286 $input->setOption('db-port', $dbPort);
291 $dbPrefix = $input->getOption('db-prefix');
293 $dbPrefix = $this->dbPrefixQuestion();
294 $input->setOption('db-prefix', $dbPrefix);
297 $input->setOption('db-type', $database['default']['driver']);
298 $input->setOption('db-host', $database['default']['host']);
299 $input->setOption('db-name', $database['default']['database']);
300 $input->setOption('db-user', $database['default']['username']);
301 $input->setOption('db-pass', $database['default']['password']);
302 $input->setOption('db-port', $database['default']['port']);
303 $input->setOption('db-prefix', $database['default']['prefix']['default']);
304 $this->getIo()->info(
306 $this->trans('commands.site.install.messages.using-current-database'),
307 $database['default']['driver'],
308 $database['default']['database'],
309 $database['default']['username']
314 // --site-name option
315 $siteName = $input->getOption('site-name');
317 $siteName = $this->getIo()->ask(
318 $this->trans('commands.site.install.questions.site-name'),
319 $this->trans('commands.site.install.suggestions.site-name')
321 $input->setOption('site-name', $siteName);
324 // --site-mail option
325 $siteMail = $input->getOption('site-mail');
327 $siteMail = $this->getIo()->ask(
328 $this->trans('commands.site.install.questions.site-mail'),
331 $input->setOption('site-mail', $siteMail);
334 // --account-name option
335 $accountName = $input->getOption('account-name');
337 $accountName = $this->getIo()->ask(
338 $this->trans('commands.site.install.questions.account-name'),
341 $input->setOption('account-name', $accountName);
344 // --account-pass option
345 $accountPass = $input->getOption('account-pass');
347 $accountPass = $this->getIo()->askHidden(
348 $this->trans('commands.site.install.questions.account-pass')
350 $input->setOption('account-pass', $accountPass);
353 // --account-mail option
354 $accountMail = $input->getOption('account-mail');
356 $accountMail = $this->getIo()->ask(
357 $this->trans('commands.site.install.questions.account-mail'),
360 $input->setOption('account-mail', $accountMail);
367 protected function execute(InputInterface $input, OutputInterface $output)
369 $uri = parse_url($input->getParameterOption(['--uri', '-l'], 'default'), PHP_URL_HOST);
371 if ($this->site->multisiteMode($uri)) {
372 if (!$this->site->validMultisite($uri)) {
373 $this->getIo()->error(
374 sprintf($this->trans('commands.site.install.messages.invalid-multisite'), $uri, $uri)
379 // Modify $_SERVER environment information to enable
380 // the Drupal installer to use the multi-site configuration.
381 $_SERVER['HTTP_HOST'] = $uri;
385 $dbType = $input->getOption('db-type')?:'mysql';
386 $dbFile = $input->getOption('db-file');
387 $dbHost = $input->getOption('db-host')?:'127.0.0.1';
388 $dbName = $input->getOption('db-name')?:'drupal_'.time();
389 $dbUser = $input->getOption('db-user')?:'root';
390 $dbPass = $input->getOption('db-pass');
391 $dbPrefix = $input->getOption('db-prefix');
392 $dbPort = $input->getOption('db-port')?:'3306';
393 $force = $input->getOption('force');
395 $databases = $this->site->getDatabaseTypes();
397 if ($dbType === 'sqlite') {
399 'database' => $dbFile,
400 'prefix' => $dbPrefix,
401 'namespace' => $databases[$dbType]['namespace'],
406 $fs = new Filesystem();
407 $fs->remove($dbFile);
411 'database' => $dbName,
412 'username' => $dbUser,
413 'password' => $dbPass,
414 'prefix' => $dbPrefix,
417 'namespace' => $databases[$dbType]['namespace'],
421 if ($force && Database::isActiveConnection()) {
422 $schema = Database::getConnection()->schema();
423 $tables = $schema->findTables('%');
424 foreach ($tables as $table) {
425 $schema->dropTable($table);
431 $drupalFinder = new DrupalFinder();
432 $drupalFinder->locateRoot(getcwd());
433 $this->runInstaller($database, $uri);
435 $autoload = $this->container->get('class_loader');
436 $drupal = new Drupal(
439 $this->configurationManager
441 $container = $drupal->boot();
442 $this->getApplication()->setContainer($container);
443 $this->getApplication()->validateCommands();
444 $this->getApplication()->loadCommands();
445 } catch (Exception $e) {
446 $this->getIo()->error($e->getMessage());
450 $this->restoreSitesFile();
456 * Backs up sites.php to backup.sites.php (if needed).
458 * This is needed because of a bug with install_drupal() that causes the
459 * install files to be placed directly under /sites instead of the
460 * appropriate subdir when run from a script and a sites.php file exists.
464 protected function backupSitesFile()
466 if (!file_exists($this->appRoot . '/sites/sites.php')) {
470 $renamed = rename($this->appRoot . '/sites/sites.php', $this->appRoot . '/sites/backup.sites.php');
472 $this->getIo()->info($this->trans('commands.site.install.messages.sites-backup'));
478 * Restores backup.sites.php to sites.php (if needed).
482 protected function restoreSitesFile()
484 if (!file_exists($this->appRoot . '/sites/backup.sites.php')) {
488 $renamed = rename($this->appRoot . '/sites/backup.sites.php', $this->appRoot . '/sites/sites.php');
490 $this->getIo()->info($this->trans('commands.site.install.messages.sites-restore'));
495 protected function runInstaller($database, $uri) {
496 $input = $this->getIo()->getInput();
497 $this->site->loadLegacyFile('/core/includes/install.core.inc');
499 $driver = (string)$database['driver'];
503 'profile' => $input->getArgument('profile') ?: 'standard',
504 'langcode' => $input->getOption('langcode') ?: 'en',
507 'install_settings_form' => [
509 $driver => $database,
510 'op' => 'Save and continue',
512 'install_configure_form' => [
513 'site_name' => $input->getOption('site-name') ?: 'Drupal 8',
514 'site_mail' => $input->getOption('site-mail') ?: 'admin@example.org',
516 'name' => $input->getOption('account-name') ?: 'admin',
517 'mail' => $input->getOption('account-mail') ?: 'admin@example.org',
519 'pass1' => $input->getOption('account-pass') ?: 'admin',
520 'pass2' => $input->getOption('account-pass') ?: 'admin'
523 'update_status_module' => [
528 'op' => 'Save and continue',
533 if (!$this->site->multisiteMode($uri)) {
534 $this->backupSitesFile();
537 $this->getIo()->newLine();
538 $this->getIo()->info($this->trans('commands.site.install.messages.installing'));
541 $autoload = $this->site->getAutoload();
542 install_drupal($autoload, $settings);
543 } catch (AlreadyInstalledException $e) {
544 $this->getIo()->error($this->trans('commands.site.install.messages.already-installed'));
546 } catch (\Exception $e) {
547 $this->getIo()->error($e->getMessage());
551 if (!$this->site->multisiteMode($uri)) {
552 $this->restoreSitesFile();
555 $this->getIo()->success($this->trans('commands.site.install.messages.installed'));