‪TYPO3CMS  9.5
UpgradeWizardRunCommand.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
3 
5 
6 /*
7  * This file is part of the TYPO3 CMS project.
8  *
9  * It is free software; you can redistribute it and/or modify it under
10  * the terms of the GNU General Public License, either version 2
11  * of the License, or any later version.
12  *
13  * For the full copyright and license information, please read the
14  * LICENSE.txt file that was distributed with this source code.
15  *
16  * The TYPO3 project - inspiring people to share!
17  */
18 
19 use Symfony\Component\Console\Command\Command;
20 use Symfony\Component\Console\Input\InputArgument;
21 use Symfony\Component\Console\Input\InputInterface;
22 use Symfony\Component\Console\Output\OutputInterface;
23 use Symfony\Component\Console\Question\ConfirmationQuestion;
24 use Symfony\Component\Console\Style\SymfonyStyle;
34 
40 class ‪UpgradeWizardRunCommand extends Command
41 {
46 
50  private ‪$output;
51 
55  private ‪$input;
56 
61  protected function ‪bootstrap(): void
62  {
67  ‪Bootstrap::initializeBackendUser(CommandLineUserAuthentication::class);
69  $this->upgradeWizardsService = new ‪UpgradeWizardsService();
70  $this->upgradeWizardsService->isDatabaseCharsetUtf8() ?: $this->upgradeWizardsService->setDatabaseCharsetUtf8();
71  }
72 
76  protected function ‪configure()
77  {
78  $this->setDescription('Run upgrade wizard. Without arguments all available wizards will be run.')
79  ->addArgument(
80  'wizardName',
81  InputArgument::OPTIONAL
82  )->setHelp(
83  'This command allows running upgrade wizards on CLI. To run a single wizard add the ' .
84  'identifier of the wizard as argument. The identifier of the wizard is the name it is ' .
85  'registered with in ext_localconf.'
86  );
87  }
88 
96  protected function ‪execute(InputInterface ‪$input, OutputInterface ‪$output)
97  {
98  $this->output = new SymfonyStyle(‪$input, ‪$output);
99  $this->input = ‪$input;
100  $this->‪bootstrap();
101 
102  $result = 0;
103  if (‪$input->getArgument('wizardName')) {
104  $wizardToExecute = ‪$input->getArgument('wizardName');
105  if (isset(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][$wizardToExecute])) {
106  $className = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][$wizardToExecute];
107  $upgradeWizard = $this->‪getWizard($className, $wizardToExecute);
108  if ($upgradeWizard !== null) {
109  $prerequisitesFulfilled = $this->‪handlePrerequisites([$upgradeWizard]);
110  if ($prerequisitesFulfilled === true) {
111  $result = $this->‪runSingleWizard($upgradeWizard);
112  } else {
113  $result = 1;
114  }
115  }
116  } else {
117  $this->output->error('No such wizard: ' . $wizardToExecute);
118  $result = 1;
119  }
120  } else {
121  $result = $this->‪runAllWizards();
122  }
123  return $result;
124  }
125 
134  protected function ‪getWizard(string $className, string $identifier): ?‪UpgradeWizardInterface
135  {
136  // already done
137  if ($this->upgradeWizardsService->isWizardDone($identifier)) {
138  return null;
139  }
140 
141  $wizardInstance = GeneralUtility::makeInstance($className);
142  if ($wizardInstance instanceof ‪ChattyInterface) {
143  $wizardInstance->setOutput($this->output);
144  }
145 
146  if (!($wizardInstance instanceof ‪UpgradeWizardInterface)) {
147  $this->output->writeln(
148  'Wizard ' .
149  $identifier .
150  ' needs to be manually run from the install tool, as it does not implement ' .
151  UpgradeWizardInterface::class
152  );
153  return null;
154  }
155 
156  if ($wizardInstance->updateNecessary()) {
157  return $wizardInstance;
158  }
159  if ($wizardInstance instanceof ‪RepeatableInterface) {
160  $this->output->note('Wizard ' . $identifier . ' does not need to make changes.');
161  } else {
162  $this->output->note('Wizard ' . $identifier . ' does not need to make changes. Marking wizard as done.');
163  $this->upgradeWizardsService->markWizardAsDone($identifier);
164  }
165  return null;
166  }
167 
178  protected function ‪handlePrerequisites(array $instances): bool
179  {
180  $prerequisites = GeneralUtility::makeInstance(PrerequisiteCollection::class);
181  foreach ($instances as $instance) {
182  foreach ($instance->getPrerequisites() as $prerequisite) {
183  $prerequisites->add($prerequisite);
184  }
185  }
186  $result = true;
187  foreach ($prerequisites as $prerequisite) {
188  if ($prerequisite instanceof ‪ChattyInterface) {
189  $prerequisite->setOutput($this->output);
190  }
191  if (!$prerequisite->isFulfilled()) {
192  $this->output->writeln('Prerequisite "' . $prerequisite->getTitle() . '" not fulfilled, will ensure.');
193  $result = $prerequisite->ensure();
194  if ($result === false) {
195  $this->output->error(
196  '<error>Error running ' .
197  $prerequisite->getTitle() .
198  '. Please ensure this prerequisite manually and try again.</error>'
199  );
200  break;
201  }
202  } else {
203  $this->output->writeln('Prerequisite "' . $prerequisite->getTitle() . '" fulfilled.');
204  }
205  }
206  return $result;
207  }
208 
213  protected function ‪runSingleWizard(
214  ‪UpgradeWizardInterface $instance
215  ): int {
216  $this->output->title('Running Wizard ' . $instance->‪getTitle());
217  if ($instance instanceof ‪ConfirmableInterface) {
218  $confirmation = $instance->getConfirmation();
219  $defaultString = $confirmation->getDefaultValue() ? 'Y/n' : 'y/N';
220  $question = new ConfirmationQuestion(
221  sprintf(
222  '<info>%s</info>' . LF . '%s' . LF . '%s %s (%s)',
223  $confirmation->getTitle(),
224  $confirmation->getMessage(),
225  $confirmation->getConfirm(),
226  $confirmation->getDeny(),
227  $defaultString
228  ),
229  $confirmation->getDefaultValue()
230  );
231  $helper = $this->getHelper('question');
232  if (!$helper->ask($this->input, $this->output, $question)) {
233  if ($confirmation->isRequired()) {
234  $this->output->error('You have to acknowledge this wizard to continue');
235  return 1;
236  }
237  if ($instance instanceof ‪RepeatableInterface) {
238  $this->output->note('No changes applied.');
239  } else {
240  $this->upgradeWizardsService->markWizardAsDone($instance->‪getIdentifier());
241  $this->output->note('No changes applied, marking wizard as done.');
242  }
243  return 0;
244  }
245  }
246  if ($instance->‪executeUpdate()) {
247  $this->output->success('Successfully ran wizard ' . $instance->‪getTitle());
248  if (!$instance instanceof ‪RepeatableInterface) {
249  $this->upgradeWizardsService->markWizardAsDone($instance->‪getIdentifier());
250  }
251  return 0;
252  }
253  $this->output->error('<error>Something went wrong while running ' . $instance->‪getTitle() . '</error>');
254  return 1;
255  }
256 
262  public function ‪runAllWizards(): int
263  {
264  $returnCode = 0;
265  $wizardInstances = [];
266  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'] as $identifier => $class) {
267  $wizardInstances[] = $this->‪getWizard($class, $identifier);
268  }
269  $wizardInstances = array_filter($wizardInstances);
270  if (count($wizardInstances) > 0) {
271  $prerequisitesResult = $this->‪handlePrerequisites($wizardInstances);
272  if ($prerequisitesResult === false) {
273  $returnCode = 1;
274  $this->output->error('Error handling prerequisites, aborting.');
275  } else {
276  $this->output->title('Found ' . count($wizardInstances) . ' wizard(s) to run.');
277  foreach ($wizardInstances as $wizardInstance) {
278  $result = $this->‪runSingleWizard($wizardInstance);
279  if ($result > 0) {
280  $returnCode = 1;
281  }
282  }
283  }
284  } else {
285  $this->output->success('No wizards left to run.');
286  }
287  return $returnCode;
288  }
289 }
‪TYPO3\CMS\Core\Core\Bootstrap\loadBaseTca
‪static Bootstrap null loadBaseTca(bool $allowCaching=true, FrontendInterface $coreCache=null)
Definition: Bootstrap.php:832
‪TYPO3\CMS\Core\Core\Bootstrap\unsetReservedGlobalVariables
‪static Bootstrap null unsetReservedGlobalVariables()
Definition: Bootstrap.php:808
‪TYPO3\CMS\Install\Updates\RepeatableInterface
Definition: RepeatableInterface.php:25
‪TYPO3\CMS\Install\Updates\UpgradeWizardInterface\executeUpdate
‪bool executeUpdate()
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\bootstrap
‪bootstrap()
Definition: UpgradeWizardRunCommand.php:58
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\$input
‪InputInterface $input
Definition: UpgradeWizardRunCommand.php:52
‪TYPO3\CMS\Install\Updates\UpgradeWizardInterface\getTitle
‪string getTitle()
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\runSingleWizard
‪int runSingleWizard(UpgradeWizardInterface $instance)
Definition: UpgradeWizardRunCommand.php:210
‪TYPO3\CMS\Install\Updates\ChattyInterface
Definition: ChattyInterface.php:25
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\execute
‪int execute(InputInterface $input, OutputInterface $output)
Definition: UpgradeWizardRunCommand.php:93
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\getWizard
‪TYPO3 CMS Install Updates UpgradeWizardInterface null getWizard(string $className, string $identifier)
Definition: UpgradeWizardRunCommand.php:131
‪TYPO3\CMS\Core\Core\Bootstrap\initializeBackendUser
‪static Bootstrap null initializeBackendUser($className=\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class)
Definition: Bootstrap.php:956
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\handlePrerequisites
‪bool handlePrerequisites(array $instances)
Definition: UpgradeWizardRunCommand.php:175
‪TYPO3\CMS\Install\Service\UpgradeWizardsService
Definition: UpgradeWizardsService.php:42
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\configure
‪configure()
Definition: UpgradeWizardRunCommand.php:73
‪TYPO3\CMS\Install\Command
Definition: LanguagePackCommand.php:3
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\$output
‪OutputInterface Symfony Component Console Style StyleInterface $output
Definition: UpgradeWizardRunCommand.php:48
‪TYPO3\CMS\Core\Core\Bootstrap\initializeBackendAuthentication
‪static Bootstrap null initializeBackendAuthentication($proceedIfNoUserIsLoggedIn=false)
Definition: Bootstrap.php:974
‪TYPO3\CMS\Core\Core\Bootstrap\loadTypo3LoadedExtAndExtLocalconf
‪static Bootstrap null loadTypo3LoadedExtAndExtLocalconf($allowCaching=true, FrontendInterface $coreCache=null)
Definition: Bootstrap.php:551
‪TYPO3\CMS\Core\Core\Bootstrap\loadExtTables
‪static Bootstrap null loadExtTables(bool $allowCaching=true)
Definition: Bootstrap.php:864
‪TYPO3\CMS\Install\Updates\UpgradeWizardInterface
Definition: UpgradeWizardInterface.php:22
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand
Definition: UpgradeWizardRunCommand.php:41
‪$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:50
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Install\Updates\PrerequisiteCollection
Definition: PrerequisiteCollection.php:21
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\$upgradeWizardsService
‪UpgradeWizardsService $upgradeWizardsService
Definition: UpgradeWizardRunCommand.php:44
‪TYPO3\CMS\Install\Command\UpgradeWizardRunCommand\runAllWizards
‪int runAllWizards()
Definition: UpgradeWizardRunCommand.php:259
‪TYPO3\CMS\Install\Updates\ConfirmableInterface
Definition: ConfirmableInterface.php:23
‪TYPO3\CMS\Core\Authentication\CommandLineUserAuthentication
Definition: CommandLineUserAuthentication.php:29