[BUGFIX] Use class name to mark upgrade wizards done
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Command / UpgradeWizardListCommand.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\InputInterface;
21 use Symfony\Component\Console\Input\InputOption;
22 use Symfony\Component\Console\Output\OutputInterface;
23 use Symfony\Component\Console\Style\SymfonyStyle;
24 use TYPO3\CMS\Core\Authentication\CommandLineUserAuthentication;
25 use TYPO3\CMS\Core\Core\Bootstrap;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27 use TYPO3\CMS\Install\Service\UpgradeWizardsService;
28 use TYPO3\CMS\Install\Updates\ChattyInterface;
29 use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
30
31 /**
32 * Upgrade wizard command for listing wizards
33 *
34 * @internal
35 */
36 class UpgradeWizardListCommand extends Command
37 {
38 /**
39 * @var UpgradeWizardsService
40 */
41 private $upgradeWizardsService;
42
43 /**
44 * @var OutputInterface|\Symfony\Component\Console\Style\StyleInterface
45 */
46 private $output;
47
48 /**
49 * @var InputInterface
50 */
51 private $input;
52
53 /**
54 * Bootstrap running of upgradeWizards
55 */
56 protected function bootstrap(): void
57 {
58 Bootstrap::loadTypo3LoadedExtAndExtLocalconf(false);
59 Bootstrap::unsetReservedGlobalVariables();
60 Bootstrap::loadBaseTca(false);
61 Bootstrap::loadExtTables(false);
62 Bootstrap::initializeBackendUser(CommandLineUserAuthentication::class);
63 Bootstrap::initializeBackendAuthentication();
64 }
65
66 /**
67 * Configure the command by defining the name, options and arguments
68 */
69 protected function configure()
70 {
71 $this->setDescription('List available upgrade wizards.')
72 ->addOption(
73 'all',
74 'a',
75 InputOption::VALUE_NONE,
76 'Include wizards already done.'
77 );
78 }
79
80 /**
81 * List available upgrade wizards. If -all is given, already done wizards are listed, too.
82 *
83 * @param InputInterface $input
84 * @param \Symfony\Component\Console\Output\OutputInterface $output
85 * @return int
86 */
87 protected function execute(InputInterface $input, OutputInterface $output)
88 {
89 $this->output = new SymfonyStyle($input, $output);
90 $this->input = $input;
91 $this->bootstrap();
92 $this->upgradeWizardsService = new UpgradeWizardsService();
93
94 $result = 0;
95 $wizards = [];
96 $all = $input->getOption('all');
97 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'] as $identifier => $wizardToExecute) {
98 $upgradeWizard = $this->getWizard($wizardToExecute, $identifier, (bool)$all);
99 if ($upgradeWizard !== null) {
100 $wizardInfo = [
101 'identifier' => $upgradeWizard->getIdentifier(),
102 'title' => $upgradeWizard->getTitle(),
103 'description' => wordwrap($upgradeWizard->getDescription()),
104 ];
105 if ($all === true) {
106 $wizardInfo['status'] = $this->upgradeWizardsService->isWizardDone($identifier) ? 'DONE' : 'AVAILABLE';
107 }
108 $wizards[] = $wizardInfo;
109 }
110 }
111 if (empty($wizards)) {
112 $this->output->success('No wizards available.');
113 } else {
114 if ($all === true) {
115 $this->output->table(['Identifier', 'Title', 'Description', 'Status'], $wizards);
116 } else {
117 $this->output->table(['Identifier', 'Title', 'Description'], $wizards);
118 }
119 }
120 return $result;
121 }
122
123 /**
124 * Get Wizard instance by class name and identifier
125 * Returns null if wizard is already done
126 *
127 * @param string $className
128 * @param string $identifier
129 * @param bool $all
130 * @return \TYPO3\CMS\Install\Updates\UpgradeWizardInterface|null
131 */
132 protected function getWizard(string $className, string $identifier, $all = false): ?UpgradeWizardInterface
133 {
134 // already done
135 if (!$all && $this->upgradeWizardsService->isWizardDone($identifier)) {
136 return null;
137 }
138
139 $wizardInstance = GeneralUtility::makeInstance($className);
140 if ($wizardInstance instanceof ChattyInterface) {
141 $wizardInstance->setOutput($this->output);
142 }
143
144 if (!($wizardInstance instanceof UpgradeWizardInterface)) {
145 return null;
146 }
147
148 return !$all ? $wizardInstance->updateNecessary() ? $wizardInstance : null : $wizardInstance;
149 }
150 }