Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
InstallCommand.php
Go to the documentation of this file.
1 <?php
6 declare(strict_types=1);
7 
9 
13 use Magento\Framework\Setup\Declaration\Schema\Request;
18 use Symfony\Component\Console\Input\InputInterface;
19 use Symfony\Component\Console\Output\OutputInterface;
20 use Symfony\Component\Console\Input\InputOption;
21 use Symfony\Component\Console\Input\ArrayInput;
22 use Symfony\Component\Console\Question\Question;
23 use Symfony\Component\Console\Question\ChoiceQuestion;
24 use Symfony\Component\Console\Helper\QuestionHelper;
25 
31 {
35  const INPUT_KEY_CLEANUP_DB = 'cleanup-database';
36 
40  const INPUT_KEY_SALES_ORDER_INCREMENT_PREFIX = 'sales-order-increment-prefix';
41 
45  const INPUT_KEY_USE_SAMPLE_DATA = 'use-sample-data';
46 
51  const INPUT_KEY_ENABLE_MODULES = 'enable-modules';
52 
58  const INPUT_KEY_DISABLE_MODULES = 'disable-modules';
59 
64  const CONVERT_OLD_SCRIPTS_KEY = 'convert-old-scripts';
65 
69  const INPUT_KEY_INTERACTIVE_SETUP = 'interactive';
70 
75 
79  const INPUT_KEY_SAFE_INSTALLER_MODE = 'safe-mode';
80 
84  const INPUT_KEY_DATA_RESTORE = 'data-restore';
85 
89  const SALES_ORDER_INCREMENT_PREFIX_RULE = '/^.{0,20}$/';
90 
96  private $installerFactory;
97 
101  protected $configModel;
102 
106  protected $userConfig;
107 
111  protected $adminUser;
112 
121  public function __construct(
122  InstallerFactory $installerFactory,
126  ) {
127  $this->installerFactory = $installerFactory;
128  $this->configModel = $configModel;
129  $this->userConfig = $userConfig;
130  $this->adminUser = $adminUser;
131  parent::__construct();
132  }
133 
137  protected function configure()
138  {
139  $inputOptions = $this->configModel->getAvailableOptions();
140  $inputOptions = array_merge($inputOptions, $this->userConfig->getOptionsList());
141  $inputOptions = array_merge($inputOptions, $this->adminUser->getOptionsList(InputOption::VALUE_OPTIONAL));
142  $inputOptions = array_merge($inputOptions, [
143  new InputOption(
144  self::INPUT_KEY_CLEANUP_DB,
145  null,
146  InputOption::VALUE_NONE,
147  'Cleanup the database before installation'
148  ),
149  new InputOption(
150  self::INPUT_KEY_SALES_ORDER_INCREMENT_PREFIX,
151  null,
152  InputOption::VALUE_REQUIRED,
153  'Sales order number prefix'
154  ),
155  new InputOption(
156  self::INPUT_KEY_USE_SAMPLE_DATA,
157  null,
158  InputOption::VALUE_NONE,
159  'Use sample data'
160  ),
161  new InputOption(
162  self::INPUT_KEY_ENABLE_MODULES,
163  null,
164  InputOption::VALUE_OPTIONAL,
165  'List of comma-separated module names. That must be included during installation. '
166  . 'Available magic param "all".'
167  ),
168  new InputOption(
169  self::INPUT_KEY_DISABLE_MODULES,
170  null,
171  InputOption::VALUE_OPTIONAL,
172  'List of comma-separated module names. That must be avoided during installation. '
173  . 'Available magic param "all".'
174  ),
175  new InputOption(
176  self::CONVERT_OLD_SCRIPTS_KEY,
177  null,
178  InputOption::VALUE_OPTIONAL,
179  'Allows to convert old scripts (InstallSchema, UpgradeSchema) to db_schema.xml format',
180  false
181  ),
182  new InputOption(
183  self::INPUT_KEY_INTERACTIVE_SETUP,
184  self::INPUT_KEY_INTERACTIVE_SETUP_SHORTCUT,
185  InputOption::VALUE_NONE,
186  'Interactive Magento instalation'
187  ),
188  new InputOption(
190  null,
191  InputOption::VALUE_OPTIONAL,
192  'Safe installation of Magento with dumps on destructive operations, like column removal'
193  ),
194  new InputOption(
196  null,
197  InputOption::VALUE_OPTIONAL,
198  'Restore removed data from dumps'
199  ),
200  new InputOption(
202  null,
203  InputOption::VALUE_OPTIONAL,
204  'Magento Installation will be run in dry-run mode',
205  false
206  ),
207  ]);
208  $this->setName('setup:install')
209  ->setDescription('Installs the Magento application')
210  ->setDefinition($inputOptions);
211  parent::configure();
212  }
213 
217  protected function execute(InputInterface $input, OutputInterface $output)
218  {
219  $consoleLogger = new ConsoleLogger($output);
220  $installer = $this->installerFactory->create($consoleLogger);
221  $installer->install($input->getOptions());
222 
223  $importConfigCommand = $this->getApplication()->find(ConfigImportCommand::COMMAND_NAME);
224  $arrayInput = new ArrayInput([]);
225  $arrayInput->setInteractive($input->isInteractive());
226  $importConfigCommand->run($arrayInput, $output);
227  }
228 
232  protected function initialize(InputInterface $input, OutputInterface $output)
233  {
234  $inputOptions = $input->getOptions();
235 
236  if ($inputOptions['interactive']) {
237  $configOptionsToValidate = $this->interactiveQuestions($input, $output);
238  } else {
239  $configOptionsToValidate = [];
240  foreach ($this->configModel->getAvailableOptions() as $option) {
241  if (array_key_exists($option->getName(), $inputOptions)) {
242  $configOptionsToValidate[$option->getName()] = $inputOptions[$option->getName()];
243  }
244  }
245  }
246 
247  if ($inputOptions['interactive']) {
248  $command = '';
249  foreach ($configOptionsToValidate as $key => $value) {
250  $command .= " --{$key}={$value}";
251  }
252  $output->writeln("<comment>Try re-running command: php bin/magento setup:install{$command}</comment>");
253  }
254 
255  $errors = $this->configModel->validate($configOptionsToValidate);
256  $errors = array_merge($errors, $this->validateAdmin($input));
257  $errors = array_merge($errors, $this->validate($input));
258  $errors = array_merge($errors, $this->userConfig->validate($input));
259 
260  if (!empty($errors)) {
261  foreach ($errors as $error) {
262  $output->writeln("<error>$error</error>");
263  }
264  throw new \InvalidArgumentException('Parameter validation failed');
265  }
266  }
267 
277  public function validate(InputInterface $input) : array
278  {
279  $errors = [];
280  $value = $input->getOption(self::INPUT_KEY_SALES_ORDER_INCREMENT_PREFIX);
281  if (preg_match(self::SALES_ORDER_INCREMENT_PREFIX_RULE, (string) $value) != 1) {
282  $errors[] = 'Validation failed, ' . self::INPUT_KEY_SALES_ORDER_INCREMENT_PREFIX
283  . ' must be 20 characters or less';
284  }
285  return $errors;
286  }
287 
297  private function interactiveQuestions(InputInterface $input, OutputInterface $output) : array
298  {
299  $helper = $this->getHelper('question');
300  $configOptionsToValidate = [];
301 
302  foreach ($this->configModel->getAvailableOptions() as $option) {
303  $configOptionsToValidate[$option->getName()] = $this->askQuestion(
304  $input,
305  $output,
306  $helper,
307  $option,
308  true
309  );
310  }
311 
312  $output->writeln("");
313 
314  foreach ($this->userConfig->getOptionsList() as $option) {
315  $configOptionsToValidate[$option->getName()] = $this->askQuestion(
316  $input,
317  $output,
318  $helper,
319  $option
320  );
321  }
322 
323  $output->writeln("");
324 
325  foreach ($this->adminUser->getOptionsList(InputOption::VALUE_OPTIONAL) as $option) {
326  $configOptionsToValidate[$option->getName()] = $this->askQuestion(
327  $input,
328  $output,
329  $helper,
330  $option
331  );
332  }
333 
334  $output->writeln("");
335 
336  $returnConfigOptionsToValidate = [];
337  foreach ($configOptionsToValidate as $key => $value) {
338  if ($value != '') {
339  $returnConfigOptionsToValidate[$key] = $value;
340  }
341  }
342 
343  return $returnConfigOptionsToValidate;
344  }
345 
358  private function askQuestion(
359  InputInterface $input,
360  OutputInterface $output,
361  QuestionHelper $helper,
362  $option,
363  $validateInline = false
364  ) {
365  if ($option instanceof \Magento\Framework\Setup\Option\SelectConfigOption) {
366  if ($option->isValueRequired()) {
367  $question = new ChoiceQuestion(
368  $option->getDescription() . '? ',
369  $option->getSelectOptions(),
370  $option->getDefault()
371  );
372  } else {
373  $question = new ChoiceQuestion(
374  $option->getDescription() . ' [optional]? ',
375  $option->getSelectOptions(),
376  $option->getDefault()
377  );
378  }
379  } else {
380  if ($option->isValueRequired()) {
381  $question = new Question(
382  $option->getDescription() . '? ',
383  $option->getDefault()
384  );
385  } else {
386  $question = new Question(
387  $option->getDescription() . ' [optional]? ',
388  $option->getDefault()
389  );
390  }
391  }
392 
393  $question->setValidator(function ($answer) use ($option, $validateInline) {
394 
395  if ($option instanceof \Magento\Framework\Setup\Option\SelectConfigOption) {
396  $answer = $option->getSelectOptions()[$answer];
397  }
398 
399  if ($answer == null) {
400  $answer = '';
401  } else {
402  $answer = trim($answer);
403  }
404 
405  if ($validateInline) {
406  $option->validate($answer);
407  }
408 
409  return $answer;
410  });
411 
412  $value = $helper->ask($input, $output, $question);
413 
414  return $value;
415  }
416 
423  private function validateAdmin(InputInterface $input): array
424  {
425  if ($input->getOption(AdminAccount::KEY_FIRST_NAME)
426  || $input->getOption(AdminAccount::KEY_LAST_NAME)
427  || $input->getOption(AdminAccount::KEY_EMAIL)
428  || $input->getOption(AdminAccount::KEY_USER)
429  || $input->getOption(AdminAccount::KEY_PASSWORD)
430  ) {
431  return $this->adminUser->validate($input);
432  }
433 
434  return [];
435  }
436 }
$helper
Definition: iframe.phtml:13
execute(InputInterface $input, OutputInterface $output)
$value
Definition: gender.phtml:16
__construct(InstallerFactory $installerFactory, ConfigModel $configModel, InstallStoreConfigurationCommand $userConfig, AdminUserCreateCommand $adminUser)
initialize(InputInterface $input, OutputInterface $output)
$errors
Definition: overview.phtml:9