‪TYPO3CMS  10.4
UpgradeWizardRunCommand.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 Symfony\Component\Console\Command\Command;
21 use Symfony\Component\Console\Input\InputArgument;
22 use Symfony\Component\Console\Input\InputInterface;
23 use Symfony\Component\Console\Output\OutputInterface;
24 use Symfony\Component\Console\Question\ConfirmationQuestion;
25 use Symfony\Component\Console\Style\SymfonyStyle;
36 
42 class ‪UpgradeWizardRunCommand extends Command
43 {
47  private ‪$lateBootService;
48 
53 
57  private ‪$output;
58 
62  private ‪$input;
63 
64  public function ‪__construct(
65  string $name,
68  ) {
69  $this->lateBootService = ‪$lateBootService;
70  $this->upgradeWizardsService = ‪$upgradeWizardsService;
71  parent::__construct($name);
72  }
73 
78  protected function ‪bootstrap(): void
79  {
80  $this->lateBootService->loadExtLocalconfDatabaseAndExtTables();
81  ‪Bootstrap::initializeBackendUser(CommandLineUserAuthentication::class);
83  $this->upgradeWizardsService->isDatabaseCharsetUtf8() ?: $this->upgradeWizardsService->setDatabaseCharsetUtf8();
84  }
85 
89  protected function ‪configure()
90  {
91  $this->setDescription('Run upgrade wizard. Without arguments all available wizards will be run.')
92  ->addArgument(
93  'wizardName',
94  InputArgument::OPTIONAL
95  )->setHelp(
96  'This command allows running upgrade wizards on CLI. To run a single wizard add the ' .
97  'identifier of the wizard as argument. The identifier of the wizard is the name it is ' .
98  'registered with in ext_localconf.'
99  );
100  }
101 
109  protected function ‪execute(InputInterface ‪$input, OutputInterface ‪$output)
110  {
111  $this->output = new SymfonyStyle(‪$input, ‪$output);
112  $this->input = ‪$input;
113  $this->‪bootstrap();
114 
115  $result = 0;
116  if (‪$input->getArgument('wizardName')) {
117  $wizardToExecute = ‪$input->getArgument('wizardName');
118  $wizardToExecute = is_string($wizardToExecute) ? $wizardToExecute : '';
119  if (isset(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][$wizardToExecute])) {
120  $className = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][$wizardToExecute];
121  $upgradeWizard = $this->‪getWizard($className, $wizardToExecute);
122  if ($upgradeWizard !== null) {
123  $prerequisitesFulfilled = $this->‪handlePrerequisites([$upgradeWizard]);
124  if ($prerequisitesFulfilled === true) {
125  $result = $this->‪runSingleWizard($upgradeWizard);
126  } else {
127  $result = 1;
128  }
129  }
130  } else {
131  $this->output->error('No such wizard: ' . $wizardToExecute);
132  $result = 1;
133  }
134  } else {
135  $result = $this->‪runAllWizards();
136  }
137  return $result;
138  }
139 
148  protected function ‪getWizard(string $className, string $identifier): ?UpgradeWizardInterface
149  {
150  // already done
151  if ($this->upgradeWizardsService->isWizardDone($identifier)) {
152  return null;
153  }
154 
155  $wizardInstance = GeneralUtility::makeInstance($className);
156  if ($wizardInstance instanceof ChattyInterface) {
157  $wizardInstance->setOutput($this->output);
158  }
159 
160  if (!($wizardInstance instanceof UpgradeWizardInterface)) {
161  $this->output->writeln(
162  'Wizard ' .
163  $identifier .
164  ' needs to be manually run from the install tool, as it does not implement ' .
165  UpgradeWizardInterface::class
166  );
167  return null;
168  }
169 
170  if ($wizardInstance->updateNecessary()) {
171  return $wizardInstance;
172  }
173  if ($wizardInstance instanceof RepeatableInterface) {
174  $this->output->note('Wizard ' . $identifier . ' does not need to make changes.');
175  } else {
176  $this->output->note('Wizard ' . $identifier . ' does not need to make changes. Marking wizard as done.');
177  $this->upgradeWizardsService->markWizardAsDone($identifier);
178  }
179  return null;
180  }
181 
192  protected function ‪handlePrerequisites(array $instances): bool
193  {
194  $prerequisites = GeneralUtility::makeInstance(PrerequisiteCollection::class);
195  foreach ($instances as $instance) {
196  foreach ($instance->getPrerequisites() as $prerequisite) {
197  $prerequisites->add($prerequisite);
198  }
199  }
200  $result = true;
201  foreach ($prerequisites as $prerequisite) {
202  if ($prerequisite instanceof ChattyInterface) {
203  $prerequisite->setOutput($this->output);
204  }
205  if (!$prerequisite->isFulfilled()) {
206  $this->output->writeln('Prerequisite "' . $prerequisite->getTitle() . '" not fulfilled, will ensure.');
207  $result = $prerequisite->ensure();
208  if ($result === false) {
209  $this->output->error(
210  '<error>Error running ' .
211  $prerequisite->getTitle() .
212  '. Please ensure this prerequisite manually and try again.</error>'
213  );
214  break;
215  }
216  } else {
217  $this->output->writeln('Prerequisite "' . $prerequisite->getTitle() . '" fulfilled.');
218  }
219  }
220  return $result;
221  }
222 
227  protected function ‪runSingleWizard(
228  UpgradeWizardInterface $instance
229  ): int {
230  $this->output->title('Running Wizard ' . $instance->getTitle());
231  if ($instance instanceof ConfirmableInterface) {
232  $confirmation = $instance->getConfirmation();
233  $defaultString = $confirmation->getDefaultValue() ? 'Y/n' : 'y/N';
234  $question = new ConfirmationQuestion(
235  sprintf(
236  '<info>%s</info>' . LF . '%s' . LF . '%s %s (%s)',
237  $confirmation->getTitle(),
238  $confirmation->getMessage(),
239  $confirmation->getConfirm(),
240  $confirmation->getDeny(),
241  $defaultString
242  ),
243  $confirmation->getDefaultValue()
244  );
245  $helper = $this->getHelper('question');
246  if (!$helper->ask($this->input, $this->output, $question)) {
247  if ($confirmation->isRequired()) {
248  $this->output->error('You have to acknowledge this wizard to continue');
249  return 1;
250  }
251  if ($instance instanceof RepeatableInterface) {
252  $this->output->note('No changes applied.');
253  } else {
254  $this->upgradeWizardsService->markWizardAsDone($instance->getIdentifier());
255  $this->output->note('No changes applied, marking wizard as done.');
256  }
257  return 0;
258  }
259  }
260  if ($instance->executeUpdate()) {
261  $this->output->success('Successfully ran wizard ' . $instance->getTitle());
262  if (!$instance instanceof RepeatableInterface) {
263  $this->upgradeWizardsService->markWizardAsDone($instance->getIdentifier());
264  }
265  return 0;
266  }
267  $this->output->error('<error>Something went wrong while running ' . $instance->getTitle() . '</error>');
268  return 1;
269  }
270 
276  public function ‪runAllWizards(): int
277  {
278  $returnCode = 0;
279  $wizardInstances = [];
280  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'] as $identifier => $class) {
281  $wizardInstances[] = $this->‪getWizard($class, $identifier);
282  }
283  $wizardInstances = array_filter($wizardInstances);
284  if (count($wizardInstances) > 0) {
285  $prerequisitesResult = $this->‪handlePrerequisites($wizardInstances);
286  if ($prerequisitesResult === false) {
287  $returnCode = 1;
288  $this->output->error('Error handling prerequisites, aborting.');
289  } else {
290  $this->output->title('Found ' . count($wizardInstances) . ' wizard(s) to run.');
291  foreach ($wizardInstances as $wizardInstance) {
292  $result = $this->‪runSingleWizard($wizardInstance);
293  if ($result > 0) {
294  $returnCode = 1;
295  }
296  }
297  }
298  } else {
299  $this->output->success('No wizards left to run.');
300  }
301  return $returnCode;
302  }
303 }
‪TYPO3\CMS\Install\Updates\RepeatableInterface
Definition: RepeatableInterface.php:26
‪TYPO3\CMS\Install\Updates\UpgradeWizardInterface\executeUpdate
‪bool executeUpdate()
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\bootstrap
‪bootstrap()
Definition: UpgradeWizardRunCommand.php:74
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\$input
‪InputInterface $input
Definition: UpgradeWizardRunCommand.php:58
‪TYPO3\CMS\Install\Updates\UpgradeWizardInterface\getTitle
‪string getTitle()
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\runSingleWizard
‪int runSingleWizard(UpgradeWizardInterface $instance)
Definition: UpgradeWizardRunCommand.php:223
‪TYPO3\CMS\Install\Updates\ChattyInterface
Definition: ChattyInterface.php:26
‪TYPO3\CMS\Core\Core\Bootstrap\initializeBackendAuthentication
‪static initializeBackendAuthentication($proceedIfNoUserIsLoggedIn=false)
Definition: Bootstrap.php:607
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\execute
‪int execute(InputInterface $input, OutputInterface $output)
Definition: UpgradeWizardRunCommand.php:105
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\getWizard
‪TYPO3 CMS Install Updates UpgradeWizardInterface null getWizard(string $className, string $identifier)
Definition: UpgradeWizardRunCommand.php:144
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\$lateBootService
‪LateBootService $lateBootService
Definition: UpgradeWizardRunCommand.php:46
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\handlePrerequisites
‪bool handlePrerequisites(array $instances)
Definition: UpgradeWizardRunCommand.php:188
‪TYPO3\CMS\Install\Service\UpgradeWizardsService
Definition: UpgradeWizardsService.php:43
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\configure
‪configure()
Definition: UpgradeWizardRunCommand.php:85
‪TYPO3\CMS\Install\Command
Definition: LanguagePackCommand.php:18
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\$output
‪OutputInterface Symfony Component Console Style StyleInterface $output
Definition: UpgradeWizardRunCommand.php:54
‪TYPO3\CMS\Core\Core\Bootstrap\initializeBackendUser
‪static initializeBackendUser($className=BackendUserAuthentication::class)
Definition: Bootstrap.php:591
‪TYPO3\CMS\Install\Service\LateBootService
Definition: LateBootService.php:34
‪TYPO3\CMS\Install\Updates\UpgradeWizardInterface
Definition: UpgradeWizardInterface.php:24
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand
Definition: UpgradeWizardRunCommand.php:43
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Install\Updates\UpgradeWizardInterface\getIdentifier
‪string getIdentifier()
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:66
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\__construct
‪__construct(string $name, LateBootService $lateBootService, UpgradeWizardsService $upgradeWizardsService)
Definition: UpgradeWizardRunCommand.php:60
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Install\Updates\PrerequisiteCollection
Definition: PrerequisiteCollection.php:23
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\$upgradeWizardsService
‪UpgradeWizardsService $upgradeWizardsService
Definition: UpgradeWizardRunCommand.php:50
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\runAllWizards
‪int runAllWizards()
Definition: UpgradeWizardRunCommand.php:272
‪TYPO3\CMS\Install\Updates\ConfirmableInterface
Definition: ConfirmableInterface.php:24
‪TYPO3\CMS\Core\Authentication\CommandLineUserAuthentication
Definition: CommandLineUserAuthentication.php:30