Yaffs site version 1.1
[yaffs-website] / vendor / drupal / console / src / Command / Site / InstallCommand.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\AppConsole\Command\Site\InstallCommand.
6  */
7
8 namespace Drupal\Console\Command\Site;
9
10 use Symfony\Component\Filesystem\Filesystem;
11 use Symfony\Component\Config\Definition\Exception\Exception;
12 use Symfony\Component\Console\Input\ArgvInput;
13 use Symfony\Component\Console\Input\InputArgument;
14 use Symfony\Component\Console\Input\InputOption;
15 use Symfony\Component\Console\Input\InputInterface;
16 use Symfony\Component\Console\Output\OutputInterface;
17 use Symfony\Component\Console\Command\Command;
18 use Drupal\Core\Database\Database;
19 use Drupal\Core\Installer\Exception\AlreadyInstalledException;
20 use Drupal\Console\Core\Command\Shared\ContainerAwareCommandTrait;
21 use Drupal\Console\Command\Shared\DatabaseTrait;
22 use Drupal\Console\Core\Utils\ConfigurationManager;
23 use Drupal\Console\Extension\Manager;
24 use Drupal\Console\Core\Style\DrupalStyle;
25 use Drupal\Console\Bootstrap\Drupal;
26 use Drupal\Console\Utils\Site;
27 use DrupalFinder\DrupalFinder;
28
29 class InstallCommand extends Command
30 {
31     use ContainerAwareCommandTrait;
32     use DatabaseTrait;
33
34     /**
35      * @var Manager
36      */
37     protected $extensionManager;
38
39     /**
40      * @var Site
41      */
42     protected $site;
43
44     /**
45      * @var  ConfigurationManager
46      */
47     protected $configurationManager;
48
49     /**
50      * @var string
51      */
52     protected $appRoot;
53
54     /**
55      * InstallCommand constructor.
56      *
57      * @param Manager              $extensionManager
58      * @param Site                 $site
59      * @param ConfigurationManager $configurationManager
60      * @param string               $appRoot
61      */
62     public function __construct(
63         Manager $extensionManager,
64         Site $site,
65         ConfigurationManager $configurationManager,
66         $appRoot
67     ) {
68         $this->extensionManager = $extensionManager;
69         $this->site = $site;
70         $this->configurationManager = $configurationManager;
71         $this->appRoot = $appRoot;
72         parent::__construct();
73     }
74
75     protected function configure()
76     {
77         $this
78             ->setName('site:install')
79             ->setDescription($this->trans('commands.site.install.description'))
80             ->addArgument(
81                 'profile',
82                 InputArgument::OPTIONAL,
83                 $this->trans('commands.site.install.arguments.profile')
84             )
85             ->addOption(
86                 'langcode',
87                 null,
88                 InputOption::VALUE_REQUIRED,
89                 $this->trans('commands.site.install.options.langcode')
90             )
91             ->addOption(
92                 'db-type',
93                 null,
94                 InputOption::VALUE_REQUIRED,
95                 $this->trans('commands.site.install.options.db-type')
96             )
97             ->addOption(
98                 'db-file',
99                 null,
100                 InputOption::VALUE_REQUIRED,
101                 $this->trans('commands.site.install.options.db-file')
102             )
103             ->addOption(
104                 'db-host',
105                 null,
106                 InputOption::VALUE_OPTIONAL,
107                 $this->trans('commands.migrate.execute.options.db-host')
108             )
109             ->addOption(
110                 'db-name',
111                 null,
112                 InputOption::VALUE_OPTIONAL,
113                 $this->trans('commands.migrate.execute.options.db-name')
114             )
115             ->addOption(
116                 'db-user',
117                 null,
118                 InputOption::VALUE_OPTIONAL,
119                 $this->trans('commands.migrate.execute.options.db-user')
120             )
121             ->addOption(
122                 'db-pass',
123                 null,
124                 InputOption::VALUE_OPTIONAL,
125                 $this->trans('commands.migrate.execute.options.db-pass')
126             )
127             ->addOption(
128                 'db-prefix',
129                 null,
130                 InputOption::VALUE_OPTIONAL,
131                 $this->trans('commands.migrate.execute.options.db-prefix')
132             )
133             ->addOption(
134                 'db-port',
135                 null,
136                 InputOption::VALUE_OPTIONAL,
137                 $this->trans('commands.migrate.execute.options.db-port')
138             )
139             ->addOption(
140                 'site-name',
141                 null,
142                 InputOption::VALUE_REQUIRED,
143                 $this->trans('commands.site.install.options.site-name')
144             )
145             ->addOption(
146                 'site-mail',
147                 null,
148                 InputOption::VALUE_REQUIRED,
149                 $this->trans('commands.site.install.options.site-mail')
150             )
151             ->addOption(
152                 'account-name',
153                 null,
154                 InputOption::VALUE_REQUIRED,
155                 $this->trans('commands.site.install.options.account-name')
156             )
157             ->addOption(
158                 'account-mail',
159                 null,
160                 InputOption::VALUE_REQUIRED,
161                 $this->trans('commands.site.install.options.account-mail')
162             )
163             ->addOption(
164                 'account-pass',
165                 null,
166                 InputOption::VALUE_REQUIRED,
167                 $this->trans('commands.site.install.options.account-pass')
168             )
169             ->addOption(
170                 'force',
171                 null,
172                 InputOption::VALUE_NONE,
173                 $this->trans('commands.site.install.options.force')
174             );
175     }
176
177     /**
178      * {@inheritdoc}
179      */
180     protected function interact(InputInterface $input, OutputInterface $output)
181     {
182         $io = new DrupalStyle($input, $output);
183
184         // --profile option
185         $profile = $input->getArgument('profile');
186         if (!$profile) {
187             $profiles = $this->extensionManager
188                 ->discoverProfiles()
189                 ->showCore()
190                 ->showNoCore()
191                 ->showInstalled()
192                 ->showUninstalled()
193                 ->getList(true);
194
195             $profiles = array_filter(
196                 $profiles,
197                 function ($profile) {
198                     return strpos($profile, 'testing') !== 0;
199                 }
200             );
201
202             $profile = $io->choice(
203                 $this->trans('commands.site.install.questions.profile'),
204                 array_values($profiles)
205             );
206
207             $input->setArgument('profile', $profile);
208         }
209
210         // --langcode option
211         $langcode = $input->getOption('langcode');
212         if (!$langcode) {
213             $languages = $this->site->getStandardLanguages();
214             $defaultLanguage = $this->configurationManager
215                 ->getConfiguration()
216                 ->get('application.language');
217
218             $langcode = $io->choiceNoList(
219                 $this->trans('commands.site.install.questions.langcode'),
220                 $languages,
221                 $languages[$defaultLanguage]
222             );
223
224             $input->setOption('langcode', $langcode);
225         }
226
227         // Use default database setting if is available
228         $database = Database::getConnectionInfo();
229         if (empty($database['default'])) {
230             // --db-type option
231             $dbType = $input->getOption('db-type');
232             if (!$dbType) {
233                 $databases = $this->site->getDatabaseTypes();
234                 $dbType = $io->choice(
235                     $this->trans('commands.migrate.setup.questions.db-type'),
236                     array_column($databases, 'name')
237                 );
238
239                 foreach ($databases as $dbIndex => $database) {
240                     if ($database['name'] == $dbType) {
241                         $dbType = $dbIndex;
242                     }
243                 }
244
245                 $input->setOption('db-type', $dbType);
246             }
247
248             if ($dbType === 'sqlite') {
249                 // --db-file option
250                 $dbFile = $input->getOption('db-file');
251                 if (!$dbFile) {
252                     $dbFile = $io->ask(
253                         $this->trans('commands.migrate.execute.questions.db-file'),
254                         'sites/default/files/.ht.sqlite'
255                     );
256                     $input->setOption('db-file', $dbFile);
257                 }
258             } else {
259                 // --db-host option
260                 $dbHost = $input->getOption('db-host');
261                 if (!$dbHost) {
262                     $dbHost = $this->dbHostQuestion($io);
263                     $input->setOption('db-host', $dbHost);
264                 }
265
266                 // --db-name option
267                 $dbName = $input->getOption('db-name');
268                 if (!$dbName) {
269                     $dbName = $this->dbNameQuestion($io);
270                     $input->setOption('db-name', $dbName);
271                 }
272
273                 // --db-user option
274                 $dbUser = $input->getOption('db-user');
275                 if (!$dbUser) {
276                     $dbUser = $this->dbUserQuestion($io);
277                     $input->setOption('db-user', $dbUser);
278                 }
279
280                 // --db-pass option
281                 $dbPass = $input->getOption('db-pass');
282                 if (!$dbPass) {
283                     $dbPass = $this->dbPassQuestion($io);
284                     $input->setOption('db-pass', $dbPass);
285                 }
286
287                 // --db-port prefix
288                 $dbPort = $input->getOption('db-port');
289                 if (!$dbPort) {
290                     $dbPort = $this->dbPortQuestion($io);
291                     $input->setOption('db-port', $dbPort);
292                 }
293             }
294
295             // --db-prefix
296             $dbPrefix = $input->getOption('db-prefix');
297             if (!$dbPrefix) {
298                 $dbPrefix = $this->dbPrefixQuestion($io);
299                 $input->setOption('db-prefix', $dbPrefix);
300             }
301         } else {
302             $input->setOption('db-type', $database['default']['driver']);
303             $input->setOption('db-host', $database['default']['host']);
304             $input->setOption('db-name', $database['default']['database']);
305             $input->setOption('db-user', $database['default']['username']);
306             $input->setOption('db-pass', $database['default']['password']);
307             $input->setOption('db-port', $database['default']['port']);
308             $input->setOption('db-prefix', $database['default']['prefix']['default']);
309             $io->info(
310                 sprintf(
311                     $this->trans('commands.site.install.messages.using-current-database'),
312                     $database['default']['driver'],
313                     $database['default']['database'],
314                     $database['default']['username']
315                 )
316             );
317         }
318
319         // --site-name option
320         $siteName = $input->getOption('site-name');
321         if (!$siteName) {
322             $siteName = $io->ask(
323                 $this->trans('commands.site.install.questions.site-name'),
324                 'Drupal 8'
325             );
326             $input->setOption('site-name', $siteName);
327         }
328
329         // --site-mail option
330         $siteMail = $input->getOption('site-mail');
331         if (!$siteMail) {
332             $siteMail = $io->ask(
333                 $this->trans('commands.site.install.questions.site-mail'),
334                 'admin@example.com'
335             );
336             $input->setOption('site-mail', $siteMail);
337         }
338
339         // --account-name option
340         $accountName = $input->getOption('account-name');
341         if (!$accountName) {
342             $accountName = $io->ask(
343                 $this->trans('commands.site.install.questions.account-name'),
344                 'admin'
345             );
346             $input->setOption('account-name', $accountName);
347         }
348
349         // --account-pass option
350         $accountPass = $input->getOption('account-pass');
351         if (!$accountPass) {
352             $accountPass = $io->askHidden(
353                 $this->trans('commands.site.install.questions.account-pass')
354             );
355             $input->setOption('account-pass', $accountPass);
356         }
357
358         // --account-mail option
359         $accountMail = $input->getOption('account-mail');
360         if (!$accountMail) {
361             $accountMail = $io->ask(
362                 $this->trans('commands.site.install.questions.account-mail'),
363                 $siteMail
364             );
365             $input->setOption('account-mail', $accountMail);
366         }
367     }
368
369     /**
370      * {@inheritdoc}
371      */
372     protected function execute(InputInterface $input, OutputInterface $output)
373     {
374         $io = new DrupalStyle($input, $output);
375         $uri =  parse_url($input->getParameterOption(['--uri', '-l'], 'default'), PHP_URL_HOST);
376
377         if ($this->site->multisiteMode($uri)) {
378             if (!$this->site->validMultisite($uri)) {
379                 $io->error(
380                     sprintf($this->trans('commands.site.install.messages.invalid-multisite'), $uri, $uri)
381                 );
382                 exit(1);
383             }
384
385             // Modify $_SERVER environment information to enable
386             // the Drupal installer to use the multi-site configuration.
387             $_SERVER['HTTP_HOST'] = $uri;
388         }
389
390         // Database options
391         $dbType = $input->getOption('db-type')?:'mysql';
392         $dbFile = $input->getOption('db-file');
393         $dbHost = $input->getOption('db-host')?:'127.0.0.1';
394         $dbName = $input->getOption('db-name')?:'drupal_'.time();
395         $dbUser = $input->getOption('db-user')?:'root';
396         $dbPass = $input->getOption('db-pass');
397         $dbPrefix = $input->getOption('db-prefix');
398         $dbPort = $input->getOption('db-port')?:'3306';
399         $force = $input->getOption('force');
400
401         $databases = $this->site->getDatabaseTypes();
402
403         if ($dbType === 'sqlite') {
404             $database = [
405               'database' => $dbFile,
406               'prefix' => $dbPrefix,
407               'namespace' => $databases[$dbType]['namespace'],
408               'driver' => $dbType,
409             ];
410
411             if ($force) {
412                 $fs = new Filesystem();
413                 $fs->remove($dbFile);
414             }
415         } else {
416             $database = [
417               'database' => $dbName,
418               'username' => $dbUser,
419               'password' => $dbPass,
420               'prefix' => $dbPrefix,
421               'port' => $dbPort,
422               'host' => $dbHost,
423               'namespace' => $databases[$dbType]['namespace'],
424               'driver' => $dbType,
425             ];
426
427             if ($force && Database::getConnectionInfo()) {
428                 $schema = Database::getConnection()->schema();
429                 $tables = $schema->findTables('%');
430                 foreach ($tables as $table) {
431                     $schema->dropTable($table);
432                 }
433             }
434         }
435
436         try {
437             $drupalFinder = new DrupalFinder();
438             $drupalFinder->locateRoot(getcwd());
439             $composerRoot = $drupalFinder->getComposerRoot();
440             $drupalRoot = $drupalFinder->getDrupalRoot();
441
442             $this->runInstaller($io, $input, $database, $uri);
443
444             $autoload = $this->container->get('class_loader');
445             $drupal = new Drupal($autoload, $composerRoot, $drupalRoot);
446             $container = $drupal->boot();
447             $this->getApplication()->setContainer($container);
448         } catch (Exception $e) {
449             $io->error($e->getMessage());
450             return 1;
451         }
452
453         $this->restoreSitesFile($io);
454
455         return 0;
456     }
457
458     /**
459      * Backs up sites.php to backup.sites.php (if needed).
460      *
461      * This is needed because of a bug with install_drupal() that causes the
462      * install files to be placed directly under /sites instead of the
463      * appropriate subdir when run from a script and a sites.php file exists.
464      *
465      * @param DrupalStyle $output
466      *
467      * @return boolean
468      */
469     protected function backupSitesFile(DrupalStyle $output)
470     {
471         if (!file_exists($this->appRoot . '/sites/sites.php')) {
472             return true;
473         }
474
475         $renamed = rename($this->appRoot . '/sites/sites.php', $this->appRoot . '/sites/backup.sites.php');
476
477         $output->info($this->trans('commands.site.install.messages.sites-backup'));
478
479         return $renamed;
480     }
481
482     /**
483      * Restores backup.sites.php to sites.php (if needed).
484      *
485      * @param DrupalStyle $output
486      *
487      * @return boolean
488      */
489     protected function restoreSitesFile(DrupalStyle $output)
490     {
491         if (!file_exists($this->appRoot . '/sites/backup.sites.php')) {
492             return true;
493         }
494
495         $renamed = rename($this->appRoot . '/sites/backup.sites.php', $this->appRoot . '/sites/sites.php');
496
497         $output->info($this->trans('commands.site.install.messages.sites-restore'));
498
499         return $renamed;
500     }
501
502     protected function runInstaller(
503         DrupalStyle $io,
504         InputInterface $input,
505         $database,
506         $uri
507     ) {
508         $this->site->loadLegacyFile('/core/includes/install.core.inc');
509
510         $driver = (string)$database['driver'];
511
512         $settings = [
513             'parameters' => [
514                 'profile' => $input->getArgument('profile') ?: 'standard',
515                 'langcode' => $input->getOption('langcode') ?: 'en',
516             ],
517             'forms' => [
518                 'install_settings_form' => [
519                     'driver' => $driver,
520                     $driver => $database,
521                     'op' => 'Save and continue',
522                 ],
523                 'install_configure_form' => [
524                     'site_name' => $input->getOption('site-name') ?: 'Drupal 8',
525                     'site_mail' => $input->getOption('site-mail') ?: 'admin@example.org',
526                     'account' => [
527                         'name' => $input->getOption('account-name') ?: 'admin',
528                         'mail' => $input->getOption('account-mail') ?: 'admin@example.org',
529                         'pass' => [
530                             'pass1' => $input->getOption('account-pass') ?: 'admin',
531                             'pass2' => $input->getOption('account-pass') ?: 'admin'
532                         ],
533                     ],
534                     'update_status_module' => [
535                         1 => true,
536                         2 => true,
537                     ],
538                     'clean_url' => true,
539                     'op' => 'Save and continue',
540                 ],
541             ]
542         ];
543
544         if (!$this->site->multisiteMode($uri)) {
545             $this->backupSitesFile($io);
546         }
547
548         $io->newLine();
549         $io->info($this->trans('commands.site.install.messages.installing'));
550
551         try {
552             $autoload = $this->site->getAutoload();
553             install_drupal($autoload, $settings);
554         } catch (AlreadyInstalledException $e) {
555             $io->error($this->trans('commands.site.install.messages.already-installed'));
556             return 1;
557         } catch (\Exception $e) {
558             $io->error($e->getMessage());
559             return 1;
560         }
561
562         if (!$this->site->multisiteMode($uri)) {
563             $this->restoreSitesFile($io);
564         }
565
566         $io->success($this->trans('commands.site.install.messages.installed'));
567
568         return 0;
569     }
570 }