[TASK] Streamline PHPDoc comment matches function/method signature
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Command / UpgradeWizardCommand.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Install\Command;
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 TYPO3\CMS\Core\Registry;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26 use TYPO3\CMS\Install\Service\UpgradeWizardsService;
27 use TYPO3\CMS\Install\Updates\ChattyInterface;
28 use TYPO3\CMS\Install\Updates\ConfirmableInterface;
29 use TYPO3\CMS\Install\Updates\PrerequisiteCollection;
30 use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
31
32 /**
33 * Core function for updating language packs
34 */
35 class UpgradeWizardCommand extends Command
36 {
37 /**
38 * @var UpgradeWizardsService
39 */
40 private $upgradeWizardsService;
41
42 protected function bootstrap(): void
43 {
44 \TYPO3\CMS\Core\Core\Bootstrap::loadTypo3LoadedExtAndExtLocalconf(false);
45 \TYPO3\CMS\Core\Core\Bootstrap::unsetReservedGlobalVariables();
46 \TYPO3\CMS\Core\Core\Bootstrap::loadBaseTca(false);
47 \TYPO3\CMS\Core\Core\Bootstrap::loadExtTables(false);
48 }
49
50 /**
51 * Configure the command by defining the name, options and arguments
52 */
53 protected function configure()
54 {
55 $this->setAliases(['install:wizards']);
56 $this->setDescription('Update the language files of all activated extensions')
57 ->addArgument(
58 'wizardName',
59 InputArgument::OPTIONAL
60 )->addOption('dry-run', 'd');
61 }
62
63 /**
64 * Update language packs of all active languages for all active extensions
65 *
66 * @param InputInterface $input
67 * @param OutputInterface $output
68 */
69 protected function execute(InputInterface $input, OutputInterface $output)
70 {
71 $this->bootstrap();
72 $this->upgradeWizardsService = new UpgradeWizardsService();
73
74 if ($input->getArgument('wizardName')) {
75 $wizardToExecute = $input->getArgument('wizardName');
76 $this->runSingleWizard($input, $output, $wizardToExecute);
77 } else {
78 $this->runAllWizards($input, $output);
79 }
80 }
81
82 /**
83 * Handles prerequisites of update wizards, allows a more flexible definition and declaration of dependencies
84 * Currently implemented prerequisites include "database needs to be up-to-date" and "referenceIndex needs to be up-
85 * to-date"
86 * At the moment the install tool automatically displays the database updates when necessary but can't do more
87 * prerequisites
88 *
89 * @todo handle in install tool
90 * @param \Symfony\Component\Console\Output\OutputInterface $output
91 * @param UpgradeWizardInterface[]
92 */
93 protected function handlePrerequisites(OutputInterface $output, array $instances): void
94 {
95 $collection = GeneralUtility::makeInstance(PrerequisiteCollection::class);
96 foreach ($instances as $instance) {
97 foreach ($instance->getPrerequisites() as $prerequisite) {
98 $collection->addPrerequisite($prerequisite);
99 }
100 }
101 foreach ($collection->getPrerequisites() as $prerequisite) {
102 if (!$prerequisite->met()) {
103 $output->writeln('Prerequisite "' . $prerequisite->getName() . '" not met, will ensure.');
104 $prerequisite->ensure();
105 } else {
106 $output->writeln('Prerequisite "' . $prerequisite->getName() . '" met.');
107 }
108 }
109 }
110
111 /**
112 * @param \Symfony\Component\Console\Input\InputInterface $input
113 * @param \Symfony\Component\Console\Output\OutputInterface $output
114 * @param UpgradeWizardInterface $instance
115 * @return int
116 */
117 protected function runSingleWizard(
118 InputInterface $input,
119 OutputInterface $output,
120 UpgradeWizardInterface $instance
121 ): int {
122 $output->writeln('Running Wizard ' . $instance->getTitle());
123 if ($instance instanceof ConfirmableInterface) {
124 $defaultString = $instance->getConfirmationDefault() ? '(Y/n)' : '(y/N)';
125 $question = new ConfirmationQuestion(
126 '<info>' .
127 $instance->getConfirmationTitle() .
128 '</info>' .
129 "\r\n" .
130 $instance->getConfirmationMessage() .
131 ' ' .
132 $defaultString,
133 $instance->getConfirmationDefault()
134 );
135 $helper = $this->getHelper('question');
136 if (!$helper->ask($input, $output, $question)) {
137 $this->upgradeWizardsService->markWizardAsDone($instance->getIdentifier());
138 return 0;
139 }
140 }
141 if ($instance->executeUpdate()) {
142 $output->writeln('<info>Successfully ran wizard ' . $instance->getTitle() . '</info>');
143 $this->upgradeWizardsService->markWizardAsDone($instance->getIdentifier());
144 return 0;
145 }
146 $output->writeln('<error>Something went wrong while running ' . $instance->getTitle() . '</error>');
147 return 1;
148 }
149
150 /**
151 * Get list of registered upgrade wizards.
152 *
153 * @param InputInterface $input
154 * @param OutputInterface $output
155 * @return array List of upgrade wizards in correct order with detail information
156 */
157 public function runAllWizards(InputInterface $input, OutputInterface $output): array
158 {
159 $wizards = [];
160 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'] as $identifier => $class) {
161 $wizardInstance = GeneralUtility::makeInstance($class);
162 $registry = GeneralUtility::makeInstance(Registry::class);
163 $markedDoneInRegistry = $registry->get(
164 'installUpdate',
165 $identifier,
166 false
167 );
168 // already done
169 if ($markedDoneInRegistry) {
170 continue;
171 }
172 // not cli runnable
173 if (!($wizardInstance instanceof UpgradeWizardInterface)) {
174 continue;
175 }
176
177 if ($wizardInstance instanceof ChattyInterface) {
178 $wizardInstance->setOutput($output);
179 }
180
181 if ($wizardInstance->updateNecessary()) {
182 $wizardInstances = [];
183 if (!($wizardInstance instanceof UpgradeWizardInterface)) {
184 $output->writeln(
185 'Wizard ' .
186 $class .
187 ' needs to be manually run from the install tool, as it does not implement ' .
188 UpgradeWizardInterface::class
189 );
190 } else {
191 $wizardInstances[] = $wizardInstance;
192 }
193 if (count($wizardInstances) > 0) {
194 $this->handlePrerequisites($output, $wizardInstances);
195 foreach ($wizardInstances as $wizardInstance) {
196 $this->runSingleWizard($input, $output, $wizardInstance);
197 }
198 }
199 }
200 }
201 return $wizards;
202 }
203 }