[TASK] Deprecate @cli annotation
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Command / HelpCommandController.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Command;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 /**
18 * A Command Controller which provides help for available commands
19 *
20 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
21 */
22 class HelpCommandController extends \TYPO3\CMS\Extbase\Mvc\Controller\CommandController
23 {
24 /**
25 * @var \TYPO3\CMS\Extbase\Mvc\Cli\CommandManager
26 */
27 protected $commandManager;
28
29 /**
30 * @var array
31 */
32 protected $commandsByExtensionsAndControllers = [];
33
34 /**
35 * @param \TYPO3\CMS\Extbase\Mvc\Cli\CommandManager $commandManager
36 */
37 public function injectCommandManager(\TYPO3\CMS\Extbase\Mvc\Cli\CommandManager $commandManager)
38 {
39 $this->commandManager = $commandManager;
40 }
41
42 /**
43 * Displays a short, general help message
44 *
45 * This only outputs the Extbase version number, context and some hint about how to
46 * get more help about commands.
47 *
48 * @internal
49 */
50 public function helpStubCommand()
51 {
52 $this->outputLine('Extbase %s', [TYPO3_version]);
53 $this->outputLine('usage: ' . $this->request->getCallingScript() . ' <command identifier>');
54 $this->outputLine();
55 $this->outputLine('See \'' . $this->request->getCallingScript() . ' help\' for a list of all available commands.');
56 $this->outputLine();
57 }
58
59 /**
60 * Display help for a command
61 *
62 * The help command displays help for a given command:
63 * ./typo3/sysext/core/bin/typo3 extbase:help <command identifier>
64 *
65 * @param string $commandIdentifier Identifier of a command for more details
66 */
67 public function helpCommand($commandIdentifier = null)
68 {
69 if ($commandIdentifier === null) {
70 $this->displayHelpIndex();
71 } else {
72 try {
73 $command = $this->commandManager->getCommandByIdentifier($commandIdentifier);
74 } catch (\TYPO3\CMS\Extbase\Mvc\Exception\CommandException $exception) {
75 $this->outputLine($exception->getMessage());
76 return;
77 }
78 $this->displayHelpForCommand($command);
79 }
80 }
81
82 /**
83 * Builds an index of all commands that are available
84 */
85 protected function displayHelpIndex()
86 {
87 $this->buildCommandsIndex();
88 $this->outputLine('Extbase %s', [TYPO3_version]);
89 $this->outputLine('usage: ' . $this->request->getCallingScript() . ' <command identifier>');
90 $this->outputLine();
91 $this->outputLine('The following commands are currently available:');
92 foreach ($this->commandsByExtensionsAndControllers as $extensionKey => $commandControllers) {
93 $this->outputLine('');
94 $this->outputLine('EXTENSION "%s":', [strtoupper($extensionKey)]);
95 $this->outputLine(str_repeat('-', $this->output->getMaximumLineLength()));
96 foreach ($commandControllers as $commands) {
97 foreach ($commands as $command) {
98 $description = wordwrap($command->getShortDescription(), $this->output->getMaximumLineLength() - 43, PHP_EOL . str_repeat(' ', 43), true);
99 $shortCommandIdentifier = $this->commandManager->getShortestIdentifierForCommand($command);
100 $this->outputLine('%-2s%-40s %s', [' ', $shortCommandIdentifier, $description]);
101 }
102 $this->outputLine();
103 }
104 }
105 $this->outputLine('See \'' . $this->request->getCallingScript() . ' help <command identifier>\' for more information about a specific command.');
106 $this->outputLine();
107 }
108
109 /**
110 * Render help text for a single command
111 *
112 * @param \TYPO3\CMS\Extbase\Mvc\Cli\Command $command
113 */
114 protected function displayHelpForCommand(\TYPO3\CMS\Extbase\Mvc\Cli\Command $command)
115 {
116 $this->outputLine();
117 $this->outputLine($command->getShortDescription());
118 $this->outputLine();
119 $this->outputLine('COMMAND:');
120 $this->outputLine('%-2s%s', [' ', $command->getCommandIdentifier()]);
121 $commandArgumentDefinitions = $command->getArgumentDefinitions();
122 $usage = '';
123 $hasOptions = false;
124 foreach ($commandArgumentDefinitions as $commandArgumentDefinition) {
125 if (!$commandArgumentDefinition->isRequired()) {
126 $hasOptions = true;
127 } else {
128 $usage .= sprintf(' <%s>', strtolower(preg_replace('/([A-Z])/', ' $1', $commandArgumentDefinition->getName())));
129 }
130 }
131 $usage = $this->request->getCallingScript() . ' ' . $this->commandManager->getShortestIdentifierForCommand($command) . ($hasOptions ? ' [<options>]' : '') . $usage;
132 $this->outputLine();
133 $this->outputLine('USAGE:');
134 $this->outputLine(' ' . $usage);
135 $argumentDescriptions = [];
136 $optionDescriptions = [];
137 if ($command->hasArguments()) {
138 foreach ($commandArgumentDefinitions as $commandArgumentDefinition) {
139 $argumentDescription = $commandArgumentDefinition->getDescription();
140 $argumentDescription = wordwrap($argumentDescription, $this->output->getMaximumLineLength() - 23, PHP_EOL . str_repeat(' ', 23), true);
141 if ($commandArgumentDefinition->isRequired()) {
142 $argumentDescriptions[] = vsprintf(' %-20s %s', [$commandArgumentDefinition->getDashedName(), $argumentDescription]);
143 } else {
144 $optionDescriptions[] = vsprintf(' %-20s %s', [$commandArgumentDefinition->getDashedName(), $argumentDescription]);
145 }
146 }
147 }
148 if (!empty($argumentDescriptions)) {
149 $this->outputLine();
150 $this->outputLine('ARGUMENTS:');
151 foreach ($argumentDescriptions as $argumentDescription) {
152 $this->outputLine($argumentDescription);
153 }
154 }
155 if (!empty($optionDescriptions)) {
156 $this->outputLine();
157 $this->outputLine('OPTIONS:');
158 foreach ($optionDescriptions as $optionDescription) {
159 $this->outputLine($optionDescription);
160 }
161 }
162 if ($command->getDescription() !== '') {
163 $this->outputLine();
164 $this->outputLine('DESCRIPTION:');
165 $descriptionLines = explode(LF, $command->getDescription());
166 foreach ($descriptionLines as $descriptionLine) {
167 $this->outputLine('%-2s%s', [' ', $descriptionLine]);
168 }
169 }
170 $relatedCommandIdentifiers = $command->getRelatedCommandIdentifiers();
171 if ($relatedCommandIdentifiers !== []) {
172 $this->outputLine();
173 $this->outputLine('SEE ALSO:');
174 foreach ($relatedCommandIdentifiers as $commandIdentifier) {
175 $command = $this->commandManager->getCommandByIdentifier($commandIdentifier);
176 $this->outputLine('%-2s%s (%s)', [' ', $commandIdentifier, $command->getShortDescription()]);
177 }
178 }
179 $this->outputLine();
180 }
181
182 /**
183 * Displays an error message
184 *
185 * @internal
186 * @param \TYPO3\CMS\Extbase\Mvc\Exception\CommandException $exception
187 */
188 public function errorCommand(\TYPO3\CMS\Extbase\Mvc\Exception\CommandException $exception)
189 {
190 $this->outputLine($exception->getMessage());
191 if ($exception instanceof \TYPO3\CMS\Extbase\Mvc\Exception\AmbiguousCommandIdentifierException) {
192 $this->outputLine('Please specify the complete command identifier. Matched commands:');
193 foreach ($exception->getMatchingCommands() as $matchingCommand) {
194 $this->outputLine(' %s', [$matchingCommand->getCommandIdentifier()]);
195 }
196 }
197 $this->outputLine('');
198 $this->outputLine('Enter "' . $this->request->getCallingScript() . ' help" for an overview of all available commands');
199 $this->outputLine('or "' . $this->request->getCallingScript() . ' help <command identifier>" for a detailed description of the corresponding command.');
200 }
201
202 /**
203 * Builds an index of available commands. For each of them a Command object is
204 * added to the commands array of this class.
205 */
206 protected function buildCommandsIndex()
207 {
208 $availableCommands = $this->commandManager->getAvailableCommands();
209 foreach ($availableCommands as $command) {
210 if ($command->isInternal()) {
211 continue;
212 }
213 $commandIdentifier = $command->getCommandIdentifier();
214 $extensionKey = strstr($commandIdentifier, ':', true);
215 $commandControllerClassName = $command->getControllerClassName();
216 $commandName = $command->getControllerCommandName();
217 $this->commandsByExtensionsAndControllers[$extensionKey][$commandControllerClassName][$commandName] = $command;
218 }
219 }
220 }