‪TYPO3CMS  ‪main
SetupCommand.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Doctrine\DBAL\Exception as DBALException;
21 use Symfony\Component\Console\Command\Command;
22 use Symfony\Component\Console\Helper\QuestionHelper;
23 use Symfony\Component\Console\Input\InputInterface;
24 use Symfony\Component\Console\Input\InputOption;
25 use Symfony\Component\Console\Output\ConsoleOutputInterface;
26 use Symfony\Component\Console\Output\OutputInterface;
27 use Symfony\Component\Console\Question\ChoiceQuestion;
28 use Symfony\Component\Console\Question\ConfirmationQuestion;
29 use Symfony\Component\Console\Question\Question;
30 use TYPO3\CMS\Core\Configuration\ConfigurationManager;
41 
45 class ‪SetupCommand extends Command
46 {
47  protected array ‪$connectionLabels = [
48  'mysqli' => '[MySQLi] Manually configured MySQL TCP/IP connection',
49  'mysqliSocket' => '[MySQLi] Manually configured MySQL socket connection',
50  'pdoMysql' => '[PDO] Manually configured MySQL TCP/IP connection',
51  'pdoMysqlSocket' => '[PDO] Manually configured MySQL socket connection',
52  'postgres' => 'Manually configured PostgreSQL connection',
53  'sqlite' => 'Manually configured SQLite connection',
54  ];
55 
56  public function ‪__construct(
57  string $name,
58  private readonly ‪SetupDatabaseService $setupDatabaseService,
59  private readonly ‪SetupService $setupService,
60  private readonly ConfigurationManager $configurationManager,
61  private readonly ‪LateBootService $lateBootService,
62  private readonly ‪FailsafePackageManager $packageManager,
63  ) {
64  parent::__construct($name);
65  }
66 
67  protected function ‪configure()
68  {
69  $this->setDescription('Setup TYPO3 via CLI using environment variables, CLI options or interactive')
70  // Connection Parameters
71  ->addOption(
72  'driver',
73  null,
74  InputOption::VALUE_OPTIONAL,
75  'Select which database driver to use',
76  )
77  ->addOption(
78  'host',
79  null,
80  InputOption::VALUE_REQUIRED,
81  'Set the database host to use',
82  'db'
83  )
84  ->addOption(
85  'port',
86  null,
87  InputOption::VALUE_OPTIONAL,
88  'Set the database port to use',
89  '3306'
90  )
91  ->addOption(
92  'dbname',
93  null,
94  InputOption::VALUE_REQUIRED,
95  'Set the database name to use',
96  'db'
97  )
98  ->addOption(
99  'username',
100  null,
101  InputOption::VALUE_REQUIRED,
102  'Set the database username to use',
103  'db'
104  )
105  ->addOption(
106  'password',
107  null,
108  InputOption::VALUE_REQUIRED,
109  'Set the database password to use'
110  )
111  // User to be created
112  ->addOption(
113  'admin-username',
114  null,
115  InputOption::VALUE_OPTIONAL,
116  'Set a username',
117  'admin'
118  )
119  ->addOption(
120  'admin-user-password',
121  null,
122  InputOption::VALUE_REQUIRED,
123  'Set users password'
124  )
125  ->addOption(
126  'admin-email',
127  null,
128  InputOption::VALUE_REQUIRED,
129  'Set users email',
130  ''
131  )
132  ->addOption(
133  'project-name',
134  null,
135  InputOption::VALUE_REQUIRED,
136  'Set the TYPO3 project name',
137  'New TYPO3 Project'
138  )
139  ->addOption(
140  'create-site',
141  null,
142  InputOption::VALUE_OPTIONAL,
143  'Create a basic site setup (root page and site configuration) with the given domain',
144  false
145  )
146  ->addOption(
147  'server-type',
148  null,
149  InputOption::VALUE_OPTIONAL,
150  'Define the web server the TYPO3 installation will be running on',
151  'other'
152  )
153  ->addOption(
154  'force',
155  null,
156  InputOption::VALUE_NONE,
157  'Force settings overwrite - use this if TYPO3 has been installed already',
158  )
159  ->addOption(
160  'no-interaction',
161  'n',
162  InputOption::VALUE_NONE,
163  'Do not ask any interactive question',
164  )->setHelp(
165  <<<EOT
166 The command offers 3 ways to setup ‪TYPO3:
167  1. environment variables
168  2. commandline options
169  3. interactive guided walk-through
170 
171 All values are validated no matter where it was set.
172 If a value is missing, the user will be asked for it.
173 
174 <fg=green>Setup using environment variables</>
175 ---------------------------------
176 TYPO3_DB_DRIVER=mysqli \
177 TYPO3_DB_USERNAME=db \
178 TYPO3_DB_PORT=3306 \
179 TYPO3_DB_HOST=db \
180 TYPO3_DB_DBNAME=db \
181 TYPO3_SETUP_ADMIN_EMAIL=admin@example.com \ TYPO3_SETUP_ADMIN_USERNAME=admin \
182 TYPO3_SETUP_CREATE_SITE="https://your-typo3-site.com/" \
183 TYPO3_PROJECT_NAME="Automated Setup" \
184 TYPO3_SERVER_TYPE="apache" \
185 ./bin/typo3 setup --force
186 ---------------------------------
187 
188 <fg=yellow>
189 Variable `TYPO3_DB_PASSWORD` (option `--password`) can be used to provide a
190 password for the database and `TYPO3_SETUP_ADMIN_PASSWORD`
191 (option `--admin-user-password`) for the admin user password.
192 Using this can be a security risk since the password may end up in shell
193 history files. Prefer the interactive mode. Additionally, writing a command
194 to shell history can be suppressed by prefixing the command with a space
195 when using `bash` or `zsh`.
196 </>
197 EOT
198  );
199  }
200 
204  protected function ‪execute(InputInterface $input, OutputInterface ‪$output): int
205  {
206  $input->setInteractive(!$input->getOption('no-interaction'));
208  $questionHelper = $this->getHelper('question');
209 
210  // Ensure all required files and folders exist
211  $serverType = $this->‪getServerType($questionHelper, $input, ‪$output);
212  $folderStructureFactory = GeneralUtility::makeInstance(DefaultFactory::class);
213  $folderStructureFactory->getStructure($serverType)->fix();
214  // Ensure existing PackageStates.php for non-composer installation.
215  $this->packageManager->recreatePackageStatesFileIfMissing(true);
216 
217  try {
218  $force = $input->getOption('force');
219  $this->setupService->prepareSystemSettings($force);
220  } catch (ExistingTargetFileNameException $exception) {
221  $configOverwriteQuestion = new ConfirmationQuestion(
222  'Configuration already exists do you want to overwrite it [default: no] ? ',
223  false
224  );
225  $configOverwrite = $questionHelper->ask($input, ‪$output, $configOverwriteQuestion);
226 
227  if (!$configOverwrite) {
228  return Command::FAILURE;
229  }
230 
231  $this->setupService->prepareSystemSettings(true);
232  }
233 
234  // Get database connection details
235  $databaseConnection = $this->‪getConnectionDetails($questionHelper, $input, ‪$output);
236 
237  // Select the database and prepare it
238  if ($exitCode = $this->‪selectAndImportDatabase($questionHelper, $input, ‪$output, $databaseConnection)) {
239  return $exitCode;
240  }
241 
242  $username = $this->‪getAdminUserName($questionHelper, $input, ‪$output);
243  $password = $this->‪getAdminUserPassword($questionHelper, $input, ‪$output);
244  if ($password !== null) {
245  $email = $this->‪getAdminEmailAddress($questionHelper, $input, ‪$output);
246  $this->setupService->createUser($username, $password, $email);
247  $this->setupService->setInstallToolPassword($password);
248  } elseif (‪$output->isVerbose()) {
249  $errOutput = ‪$output instanceof ConsoleOutputInterface ? ‪$output->getErrorOutput() : ‪$output;
250  $errOutput->writeln('<info>No admin password defined. Skipped user creation.</info>');
251  }
252 
253  $siteName = $this->‪getProjectName($questionHelper, $input, ‪$output);
254  $this->setupService->setSiteName($siteName);
255 
256  $siteUrl = $this->‪getSiteSetup($questionHelper, $input, ‪$output);
257  if ($siteUrl) {
258  $pageUid = $this->setupService->createSite();
259  $this->setupService->createSiteConfiguration('main', (int)$pageUid, $siteUrl);
260  }
261 
262  $container = $this->lateBootService->loadExtLocalconfDatabaseAndExtTables();
263  $this->setupDatabaseService->markWizardsDone($container);
264  $this->‪writeSuccess($output, 'Congratulations - TYPO3 Setup is done.');
265 
266  return Command::SUCCESS;
267  }
268 
269  protected function ‪selectAndImportDatabase(QuestionHelper $questionHelper, InputInterface $input, OutputInterface ‪$output, mixed $databaseConnection): int
270  {
271  if ($databaseConnection['driver'] !== 'pdo_sqlite') {
272  // Set temporary database configuration, so we are able to
273  // get the available databases listed
274  ‪$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections'][‪ConnectionPool::DEFAULT_CONNECTION_NAME] = $databaseConnection;
275 
276  try {
277  $databaseList = $this->setupDatabaseService->getDatabaseList();
278  } catch (DBALException $exception) {
279  $this->‪writeError($output, $exception->getMessage());
280 
281  return Command::FAILURE;
282  }
283 
284  if ($databaseList === []) {
285  $this->‪writeError($output, 'No databases are available to the specified user. At least one usable database needs to be accessible.');
286  return Command::FAILURE;
287  }
288 
289  $dbChoices = [];
290  foreach ($databaseList as $database) {
291  $usable = $database['tables'] > 0 ? '<fg=red>☓</>' : '<fg=green>✓</>';
292  $dbChoices[$database['name']] = $database['name'] . ' (Tables ' . $database['tables'] . ' ' . $usable . ')';
293  }
294 
295  $dbNameValidator = static function ($dbname) use ($dbChoices, $databaseList) {
296  if (!($dbChoices[$dbname] ?? false)) {
297  throw new \RuntimeException(
298  'The selected database "' . $dbname . '" is not available, pick one of these: ' . implode(
299  ', ',
300  array_keys($dbChoices)
301  ) . '.',
302  1669747192,
303  );
304  }
305 
306  $selectedDatabase = $databaseList[array_search($dbname, array_keys($dbChoices), true)];
307  if ($selectedDatabase['tables'] !== 0) {
308  throw new \RuntimeException(
309  'The selected database contains already ' . $selectedDatabase['tables'] . ' tables. Please delete all tables or select another database.',
310  1669747200,
311  );
312  }
313 
314  return $dbname;
315  };
316 
317  $dbnameFromCli = $this->‪getFallbackValueEnvOrOption($input, 'dbname', 'TYPO3_DB_DBNAME');
318  if ($dbnameFromCli === false && $input->isInteractive()) {
319  $dbname = new ChoiceQuestion('Select which database to use: ', $dbChoices);
320  $dbname->setValidator($dbNameValidator);
321  $databaseConnection['database'] = $questionHelper->ask($input, ‪$output, $dbname);
322  } else {
323  try {
324  $dbNameValidator($dbnameFromCli);
325  } catch (\RuntimeException $e) {
326  $this->‪writeError($output, $e->getMessage());
327 
328  return Command::FAILURE;
329  }
330 
331  $databaseConnection['database'] = $dbnameFromCli;
332  }
333 
334  $checkDatabase = $this->setupDatabaseService->checkExistingDatabase($databaseConnection['database']);
335  if ($checkDatabase->getSeverity() !== ContextualFeedbackSeverity::OK) {
336  $this->‪writeError($output, $checkDatabase->getMessage());
337 
338  return Command::FAILURE;
339  }
340  } else {
341  $databaseConnection['availableSet'] = 'sqliteManualConfiguration';
342  }
343 
344  [$success, $messages] = $this->setupDatabaseService->setDefaultConnectionSettings($databaseConnection);
345  if (!$success) {
346  foreach ($messages as $message) {
347  $this->‪writeError($output, $message->getMessage());
348  }
349 
350  return Command::FAILURE;
351  }
352 
353  // Load the actual config written to disk
354  ‪$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections'][‪ConnectionPool::DEFAULT_CONNECTION_NAME] = $this->configurationManager->getLocalConfigurationValueByPath('DB/Connections/Default');
355 
356  $this->setupDatabaseService->checkRequiredDatabasePermissions();
357  $importResults = $this->setupDatabaseService->importDatabaseData();
358  foreach ($importResults as $result) {
359  $this->‪writeError($output, (string)$result);
360  }
361 
362  if (count($importResults) > 0) {
363  $this->‪writeError($output, 'Database import failed. Please see the errors shown above');
364  return Command::FAILURE;
365  }
366 
367  return Command::SUCCESS;
368  }
369 
370  protected function ‪getConnectionDetails(QuestionHelper $questionHelper, InputInterface $input, OutputInterface ‪$output): array
371  {
372  $input->hasParameterOption('--driver');
373  $driverTypeCli = $this->‪getFallbackValueEnvOrOption($input, 'driver', 'TYPO3_DB_DRIVER');
374  $driverOptions = $this->setupDatabaseService->getDriverOptions();
375  $availableConnectionTypes = implode(', ', array_keys($this->connectionLabels));
376 
377  $connectionValidator = static function ($connectionType) use ($driverOptions, $availableConnectionTypes) {
378  if (!isset($driverOptions[$connectionType . 'ManualConfigurationOptions'])) {
379  throw new \RuntimeException(
380  'The connection type "' . $connectionType . '" does not exist. Please use one of the following ' . $availableConnectionTypes,
381  1669905551,
382  );
383  }
384 
385  return $connectionType;
386  };
387 
388  if ($driverTypeCli === false && $input->isInteractive()) {
389  $driver = new ChoiceQuestion('Database driver?', $this->connectionLabels);
390  $driver->setValidator($connectionValidator);
391  $driverType = $questionHelper->ask($input, ‪$output, $driver);
392  } else {
393  $driverType = $connectionValidator($driverTypeCli);
394  }
395 
396  $databaseConnectionOptions = $driverOptions[$driverType . 'ManualConfigurationOptions'];
397 
398  // Ask for connection details
399  foreach ($databaseConnectionOptions as $key => $value) {
400  switch ($key) {
401  case 'database':
402  case 'socket':
403  case 'driver':
404  break;
405  case 'username':
406  $usernameFromCli = $this->‪getFallbackValueEnvOrOption($input, 'username', 'TYPO3_DB_USERNAME');
407  $emptyValidator = static function ($value) {
408  if (empty($value)) {
409  throw new \RuntimeException(
410  'The value must not be empty.',
411  1669747578,
412  );
413  }
414 
415  return $value;
416  };
417 
418  if ($usernameFromCli === false && $input->isInteractive()) {
419  $default = $this->getDefinition()->getOption($key)->getDefault();
420  $defaultLabel = ' [default: ' . $default . ']';
421  $question = new Question('Enter the database "username"' . $defaultLabel . ' ? ', $default);
422  $question->setValidator($emptyValidator);
423  $username = $questionHelper->ask($input, ‪$output, $question);
424  // @todo: Investigate the difference between username and user.... why?
425  $databaseConnectionOptions['username'] = $username;
426  $databaseConnectionOptions['user'] = $username;
427  break;
428  }
429 
430  $validUsername = $emptyValidator($usernameFromCli);
431  $databaseConnectionOptions['username'] = $validUsername;
432  $databaseConnectionOptions['user'] = $validUsername;
433  break;
434  default:
435  $envValue = $this->‪getFallbackValueEnvOrOption($input, $key, 'TYPO3_DB_' . strtoupper($key));
436  $default = $this->getDefinition()->getOption($key)->getDefault();
437  $defaultLabel = empty($value) ? '' : ' [default: ' . $default . ']';
438  $question = new Question('Enter the database "' . $key . '"' . $defaultLabel . ' ? ', $default);
439  if ($key === 'password') {
440  $question = new Question('Enter the database "' . $key . '" ? ', $default);
441  $question->setHidden(true);
442  $question->setHiddenFallback(false);
443  } elseif ($key === 'host') {
444  $hostValidator = function ($host) {
445  if (!$this->setupDatabaseService->isValidDbHost($host)) {
446  throw new \RuntimeException(
447  'Please enter a valid database host name.',
448  1669747572
449  );
450  }
451  return $host;
452  };
453  $question->setValidator($hostValidator);
454  } elseif ($key === 'port') {
455  $portValidator = function ($port) {
456  $port = (int)$port;
457  if (!$this->setupDatabaseService->isValidDbPort($port)) {
458  throw new \RuntimeException(
459  'Please use a port in the range between 1 and 65535.',
460  1669747592,
461  );
462  }
463  return $port;
464  };
465  $question->setValidator($portValidator);
466  } else {
467  $emptyValidator = function ($value) {
468  if (empty($value)) {
469  throw new \RuntimeException(
470  'The value must not be empty.',
471  1669747601,
472  );
473  }
474  return $value;
475  };
476  $question->setValidator($emptyValidator);
477  }
478  if ($envValue === false && $key === 'password') {
479  // Force this question if no `TYPO3_DB_PASSWORD` set via cli.
480  // Thus, the user will always be prompted for a password even --no-interaction is set.
481  $currentlyInteractive = $input->isInteractive();
482  $input->setInteractive(true);
483  $value = $questionHelper->ask($input, ‪$output, $question);
484  $input->setInteractive($currentlyInteractive);
485  } elseif ($envValue === false && $input->isInteractive()) {
486  $value = $questionHelper->ask($input, ‪$output, $question);
487  } else {
488  // All passed in values should go through the set validator,
489  // therefore, we can't break early
490  ‪$validator = $question->getValidator();
491  $envValue = $envValue ?: $default;
492  $value = ‪$validator ? ‪$validator($envValue) : $envValue;
493  }
494  $databaseConnectionOptions[$key] = $value;
495  }
496  }
497 
498  return $databaseConnectionOptions;
499  }
500 
501  protected function ‪getServerType(QuestionHelper $questionHelper, InputInterface $input, OutputInterface ‪$output): ‪WebserverType
502  {
503  $serverTypeValidator = function (string $serverType): ‪WebserverType {
504  if (!array_key_exists($serverType, WebserverType::getDescriptions())) {
505  throw new \RuntimeException(
506  'Webserver must be any of ' . implode(', ', array_keys(WebserverType::getDescriptions())),
507  1682329380,
508  );
509  }
510 
511  return WebserverType::from($serverType);
512  };
513  $serverTypeFromCli = $this->‪getFallbackValueEnvOrOption($input, 'server-type', 'TYPO3_SERVER_TYPE');
514  if ($serverTypeFromCli === false && $input->isInteractive()) {
515  $questionServerType = new ChoiceQuestion('Which web server is used?', WebserverType::getDescriptions());
516  $questionServerType->setValidator($serverTypeValidator);
517  return $questionHelper->ask($input, ‪$output, $questionServerType);
518  }
519 
520  return $serverTypeValidator($serverTypeFromCli);
521  }
522 
523  protected function ‪getAdminUserName(QuestionHelper $questionHelper, InputInterface $input, OutputInterface ‪$output): string
524  {
525  $usernameValidator = static function ($username) {
526  if (empty($username)) {
527  throw new \RuntimeException(
528  'Admin username must not be empty.',
529  1669747607,
530  );
531  }
532 
533  return $username;
534  };
535 
536  $usernameFromCli = $this->‪getFallbackValueEnvOrOption($input, 'admin-username', 'TYPO3_SETUP_ADMIN_USERNAME');
537  if ($usernameFromCli === false && $input->isInteractive()) {
538  $questionUsername = new Question('Admin username (user will be "system maintainer") ? ');
539  $questionUsername->setValidator($usernameValidator);
540  return $questionHelper->ask($input, ‪$output, $questionUsername);
541  }
542 
543  // Use default value for 'admin-username' if in non-interactive mode
544  if ($usernameFromCli === false && !$input->isInteractive()) {
545  $usernameFromCli = $this->getDefinition()->getOption('admin-username')->getDefault();
546  }
547 
548  return $usernameValidator($usernameFromCli);
549  }
550 
551  protected function ‪getAdminUserPassword(QuestionHelper $questionHelper, InputInterface $input, OutputInterface ‪$output): ?string
552  {
553  $passwordValidator = function ($password) {
554  $passwordValidationErrors = $this->setupDatabaseService->getBackendUserPasswordValidationErrors((string)$password);
555  if (!empty($passwordValidationErrors)) {
556  throw new \RuntimeException(
557  'Administrator password not secure enough!' . PHP_EOL
558  . '* ' . implode(PHP_EOL . '* ', $passwordValidationErrors),
559  1669747614,
560  );
561  }
562 
563  return $password;
564  };
565 
566  $passwordFromCli = $this->‪getFallbackValueEnvOrOption($input, 'admin-user-password', 'TYPO3_SETUP_ADMIN_PASSWORD');
567  if ($passwordFromCli === false && $input->isInteractive()) {
568  $currentlyInteractive = $input->isInteractive();
569  $input->setInteractive(true);
570  $questionPassword = new Question('Admin user and installer password ? ');
571  $questionPassword->setHidden(true);
572  $questionPassword->setHiddenFallback(false);
573  $questionPassword->setValidator($passwordValidator);
574  $password = $questionHelper->ask($input, ‪$output, $questionPassword);
575  $input->setInteractive($currentlyInteractive);
576 
577  return $password;
578  }
579 
580  if ($passwordFromCli === false) {
581  return null;
582  }
583 
584  return $passwordValidator($passwordFromCli);
585  }
586 
587  protected function ‪getAdminEmailAddress(QuestionHelper $questionHelper, InputInterface $input, OutputInterface ‪$output): string
588  {
589  $emailValidator = static function ($email) {
590  if (!empty($email) && !GeneralUtility::validEmail($email)) {
591  throw new \RuntimeException(
592  'The given Email is not valid! Please try again.',
593  1669747620,
594  );
595  }
596 
597  return $email;
598  };
599 
600  $emailFromCli = $this->‪getFallbackValueEnvOrOption($input, 'admin-email', 'TYPO3_SETUP_ADMIN_EMAIL');
601  if ($emailFromCli === false && $input->isInteractive()) {
602  $questionEmail = new Question('Admin user email ? ', '');
603  $questionEmail->setValidator($emailValidator);
604 
605  return $questionHelper->ask($input, ‪$output, $questionEmail);
606  }
607 
608  return (string)$emailValidator($emailFromCli);
609  }
610 
611  protected function ‪getProjectName(QuestionHelper $questionHelper, InputInterface $input, OutputInterface ‪$output): string
612  {
613  $nameFromCli = $this->‪getFallbackValueEnvOrOption($input, 'project-name', 'TYPO3_PROJECT_NAME');
614  $defaultProjectName = $this->getDefinition()->getOption('project-name')->getDefault();
615 
616  if ($nameFromCli === false && $input->isInteractive()) {
617  $question = new Question(
618  'Give your project a name [default: ' . $defaultProjectName . '] ? ',
619  $defaultProjectName
620  );
621 
622  return $questionHelper->ask($input, ‪$output, $question);
623  }
624 
625  return $nameFromCli ?: $defaultProjectName;
626  }
627 
628  protected function ‪getSiteSetup(QuestionHelper $questionHelper, InputInterface $input, OutputInterface ‪$output): string|bool
629  {
630  $urlValidator = static function (‪$url) {
632  throw new \RuntimeException(
633  'The given url for the site name is not valid! Please try again.',
634  1669747625,
635  );
636  }
637 
638  return ‪$url;
639  };
640 
641  $createSiteFromCli = $this->‪getFallbackValueEnvOrOption($input, 'create-site', 'TYPO3_SETUP_CREATE_SITE');
642 
643  if ($createSiteFromCli === false && $input->isInteractive()) {
644  $questionCreateSite = new Question('Create a basic site? Please enter a URL [default: no] ', false);
645  $questionCreateSite->setValidator($urlValidator);
646 
647  return $questionHelper->ask($input, ‪$output, $questionCreateSite);
648  }
649 
650  return $urlValidator($createSiteFromCli);
651  }
652 
653  protected function ‪writeSuccess(OutputInterface ‪$output, string $message): void
654  {
655  ‪$output->writeln('<fg=green>✓</> ' . $message);
656  }
657 
658  protected function ‪writeError(OutputInterface ‪$output, string $message): void
659  {
660  ‪$output->writeln('<fg=red>☓</> [Error]: ' . $message);
661  }
662 
668  protected function ‪getFallbackValueEnvOrOption(InputInterface $input, string $option, string $envVar): string|false
669  {
670  return $input->hasParameterOption('--' . $option) ? $input->getOption($option) : getenv($envVar);
671  }
672 }
673 
‪TYPO3\CMS\Core\Package\FailsafePackageManager
Definition: FailsafePackageManager.php:27
‪TYPO3\CMS\Install\Command\SetupCommand\$connectionLabels
‪array $connectionLabels
Definition: SetupCommand.php:47
‪TYPO3
‪TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException
Definition: ExistingTargetFileNameException.php:23
‪TYPO3\CMS\Install\FolderStructure\DefaultFactory
Definition: DefaultFactory.php:26
‪TYPO3\CMS\Install\Service\SetupService
Definition: SetupService.php:42
‪TYPO3\CMS\Install\Command\SetupCommand\writeError
‪writeError(OutputInterface $output, string $message)
Definition: SetupCommand.php:656
‪TYPO3\CMS\Install\WebserverType
‪WebserverType
Definition: WebserverType.php:26
‪TYPO3\CMS\Core\Database\ConnectionPool\DEFAULT_CONNECTION_NAME
‪const DEFAULT_CONNECTION_NAME
Definition: ConnectionPool.php:50
‪TYPO3\CMS\Core\Type\ContextualFeedbackSeverity
‪ContextualFeedbackSeverity
Definition: ContextualFeedbackSeverity.php:25
‪TYPO3\CMS\Install\Command\SetupCommand\getAdminUserName
‪getAdminUserName(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output)
Definition: SetupCommand.php:521
‪TYPO3\CMS\Install\Command\SetupCommand\configure
‪configure()
Definition: SetupCommand.php:67
‪TYPO3\CMS\Install\Command
Definition: BackendUserGroupType.php:18
‪$validator
‪if(isset($args['d'])) $validator
Definition: validateRstFiles.php:262
‪TYPO3\CMS\Install\Service\LateBootService
Definition: LateBootService.php:27
‪TYPO3\CMS\Install\Command\SetupCommand\getProjectName
‪getProjectName(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output)
Definition: SetupCommand.php:609
‪TYPO3\CMS\Install\Service\SetupDatabaseService
Definition: SetupDatabaseService.php:52
‪TYPO3\CMS\Install\Command\SetupCommand\execute
‪execute(InputInterface $input, OutputInterface $output)
Definition: SetupCommand.php:202
‪$output
‪$output
Definition: annotationChecker.php:114
‪TYPO3\CMS\Install\Command\SetupCommand\getAdminEmailAddress
‪getAdminEmailAddress(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output)
Definition: SetupCommand.php:585
‪TYPO3\CMS\Webhooks\Message\$url
‪identifier readonly UriInterface $url
Definition: LoginErrorOccurredMessage.php:36
‪TYPO3\CMS\Install\Command\SetupCommand\selectAndImportDatabase
‪selectAndImportDatabase(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output, mixed $databaseConnection)
Definition: SetupCommand.php:267
‪TYPO3\CMS\Install\Command\SetupCommand\getConnectionDetails
‪getConnectionDetails(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output)
Definition: SetupCommand.php:368
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Install\Command\SetupCommand\__construct
‪__construct(string $name, private readonly SetupDatabaseService $setupDatabaseService, private readonly SetupService $setupService, private readonly ConfigurationManager $configurationManager, private readonly LateBootService $lateBootService, private readonly FailsafePackageManager $packageManager,)
Definition: SetupCommand.php:56
‪TYPO3\CMS\Core\Utility\GeneralUtility\isValidUrl
‪static bool isValidUrl(string $url)
Definition: GeneralUtility.php:713
‪TYPO3\CMS\Install\Command\SetupCommand\getSiteSetup
‪getSiteSetup(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output)
Definition: SetupCommand.php:626
‪TYPO3\CMS\Install\Command\SetupCommand\getServerType
‪getServerType(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output)
Definition: SetupCommand.php:499
‪TYPO3\CMS\Install\Command\SetupCommand\writeSuccess
‪writeSuccess(OutputInterface $output, string $message)
Definition: SetupCommand.php:651
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Install\Command\SetupCommand\getAdminUserPassword
‪getAdminUserPassword(QuestionHelper $questionHelper, InputInterface $input, OutputInterface $output)
Definition: SetupCommand.php:549
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Install\Command\SetupCommand\getFallbackValueEnvOrOption
‪getFallbackValueEnvOrOption(InputInterface $input, string $option, string $envVar)
Definition: SetupCommand.php:666
‪TYPO3\CMS\Install\Command\SetupCommand
Definition: SetupCommand.php:46