PageRenderTime 52ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/Classes/TYPO3/FLOW3/Command/HelpCommandController.php

https://github.com/christianjul/FLOW3-Composer
PHP | 285 lines | 172 code | 33 blank | 80 comment | 17 complexity | c80ad24eb977180f5df5c2ef4762706c MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0
  1. <?php
  2. namespace TYPO3\FLOW3\Command;
  3. /* *
  4. * This script belongs to the FLOW3 framework. *
  5. * *
  6. * It is free software; you can redistribute it and/or modify it under *
  7. * the terms of the GNU Lesser General Public License, either version 3 *
  8. * of the License, or (at your option) any later version. *
  9. * *
  10. * The TYPO3 project - inspiring people to share! *
  11. * */
  12. use TYPO3\FLOW3\Annotations as FLOW3;
  13. use TYPO3\FLOW3\Cli\Command;
  14. use TYPO3\FLOW3\Cli\CommandManager;
  15. /**
  16. * A Command Controller which provides help for available commands
  17. *
  18. * @FLOW3\Scope("singleton")
  19. */
  20. class HelpCommandController extends \TYPO3\FLOW3\Cli\CommandController {
  21. /**
  22. * @var \TYPO3\FLOW3\Package\PackageManagerInterface
  23. */
  24. protected $packageManager;
  25. /**
  26. * @var \TYPO3\FLOW3\Core\Bootstrap
  27. */
  28. protected $bootstrap;
  29. /**
  30. * @var CommandManager
  31. */
  32. protected $commandManager;
  33. /**
  34. * @param \TYPO3\FLOW3\Package\PackageManagerInterface $packageManager
  35. * @return void
  36. */
  37. public function injectPackageManager(\TYPO3\FLOW3\Package\PackageManagerInterface $packageManager) {
  38. $this->packageManager = $packageManager;
  39. }
  40. /**
  41. * @param \TYPO3\FLOW3\Core\Bootstrap $bootstrap
  42. * @return void
  43. */
  44. public function injectBootstrap(\TYPO3\FLOW3\Core\Bootstrap $bootstrap) {
  45. $this->bootstrap = $bootstrap;
  46. }
  47. /**
  48. * @param CommandManager $commandManager
  49. * @return void
  50. */
  51. public function injectCommandManager(CommandManager $commandManager) {
  52. $this->commandManager = $commandManager;
  53. }
  54. /**
  55. * Displays a short, general help message
  56. *
  57. * This only outputs the FLOW3 version number, context and some hint about how to
  58. * get more help about commands.
  59. *
  60. * @return void
  61. * @FLOW3\Internal
  62. */
  63. public function helpStubCommand() {
  64. $context = $this->bootstrap->getContext();
  65. $this->outputLine('<b>FLOW3 %s ("%s" context)</b>', array($this->packageManager->getPackage('TYPO3.FLOW3')->getPackageMetaData()->getVersion(), $context));
  66. $this->outputLine('<i>usage: %s <command identifier></i>', array($this->getFlow3InvocationString()));
  67. $this->outputLine();
  68. $this->outputLine('See "%s help" for a list of all available commands.', array($this->getFlow3InvocationString()));
  69. $this->outputLine();
  70. }
  71. /**
  72. * Display help for a command
  73. *
  74. * The help command displays help for a given command:
  75. * ./flow3 help <commandIdentifier>
  76. *
  77. * @param string $commandIdentifier Identifier of a command for more details
  78. * @return void
  79. */
  80. public function helpCommand($commandIdentifier = NULL) {
  81. $exceedingArguments = $this->request->getExceedingArguments();
  82. if (count($exceedingArguments) > 0 && $commandIdentifier === NULL) {
  83. $commandIdentifier = $exceedingArguments[0];
  84. }
  85. if ($commandIdentifier === NULL) {
  86. $this->displayHelpIndex();
  87. } else {
  88. $matchingCommands = $this->commandManager->getCommandsByIdentifier($commandIdentifier);
  89. $numberOfMatchingCommands = count($matchingCommands);
  90. if ($numberOfMatchingCommands === 0) {
  91. $this->outputLine('No command could be found that matches the command identifier "%s".', array($commandIdentifier));
  92. } elseif ($numberOfMatchingCommands > 1) {
  93. $this->outputLine('%d commands match the command identifier "%s":', array($numberOfMatchingCommands, $commandIdentifier));
  94. $this->displayShortHelpForCommands($matchingCommands);
  95. } else {
  96. $this->displayHelpForCommand(array_shift($matchingCommands));
  97. }
  98. }
  99. }
  100. /**
  101. * @return void
  102. */
  103. protected function displayHelpIndex() {
  104. $context = $this->bootstrap->getContext();
  105. $this->outputLine('<b>FLOW3 %s ("%s" context)</b>', array($this->packageManager->getPackage('TYPO3.FLOW3')->getPackageMetaData()->getVersion(), $context));
  106. $this->outputLine('<i>usage: %s <command identifier></i>', array($this->getFlow3InvocationString()));
  107. $this->outputLine();
  108. $this->outputLine('The following commands are currently available:');
  109. $this->displayShortHelpForCommands($this->commandManager->getAvailableCommands());
  110. $this->outputLine('* = compile time command');
  111. $this->outputLine();
  112. $this->outputLine('See "%s help <commandidentifier>" for more information about a specific command.', array($this->getFlow3InvocationString()));
  113. $this->outputLine();
  114. }
  115. /**
  116. * @param array<\TYPO3\FLOW3\Cli\Command> $commands
  117. * @return void
  118. */
  119. protected function displayShortHelpForCommands(array $commands) {
  120. $commandsByPackagesAndControllers = $this->buildCommandsIndex($commands);
  121. foreach ($commandsByPackagesAndControllers as $packageKey => $commandControllers) {
  122. $this->outputLine('');
  123. $this->outputLine('PACKAGE "%s":', array(strtoupper($packageKey)));
  124. $this->outputLine(str_repeat('-', self::MAXIMUM_LINE_LENGTH));
  125. foreach ($commandControllers as $commands) {
  126. foreach ($commands as $command) {
  127. $description = wordwrap($command->getShortDescription(), self::MAXIMUM_LINE_LENGTH - 43, PHP_EOL . str_repeat(' ', 43), TRUE);
  128. $shortCommandIdentifier = $this->commandManager->getShortestIdentifierForCommand($command);
  129. $compileTimeSymbol = ($this->bootstrap->isCompileTimeCommand($shortCommandIdentifier) ? '*' : '');
  130. $this->outputLine('%-2s%-40s %s', array($compileTimeSymbol, $shortCommandIdentifier , $description));
  131. }
  132. $this->outputLine();
  133. }
  134. }
  135. }
  136. /**
  137. * Render help text for a single command
  138. *
  139. * @param \TYPO3\FLOW3\Cli\Command $command
  140. * @return void
  141. */
  142. protected function displayHelpForCommand(\TYPO3\FLOW3\Cli\Command $command) {
  143. $this->outputLine();
  144. $this->outputLine('<u>' . $command->getShortDescription() . '</u>');
  145. $this->outputLine();
  146. $this->outputLine('<b>COMMAND:</b>');
  147. $name = '<i>' . $command->getCommandIdentifier() . '</i>';
  148. $this->outputLine('%-2s%s', array(' ', $name));
  149. $commandArgumentDefinitions = $command->getArgumentDefinitions();
  150. $usage = '';
  151. $hasOptions = FALSE;
  152. foreach ($commandArgumentDefinitions as $commandArgumentDefinition) {
  153. if (!$commandArgumentDefinition->isRequired()) {
  154. $hasOptions = TRUE;
  155. } else {
  156. $usage .= sprintf(' <%s>', strtolower(preg_replace('/([A-Z])/', ' $1', $commandArgumentDefinition->getName())));
  157. }
  158. }
  159. $usage = $this->commandManager->getShortestIdentifierForCommand($command) . ($hasOptions ? ' [<options>]' : '') . $usage;
  160. $this->outputLine();
  161. $this->outputLine('<b>USAGE:</b>');
  162. $this->outputLine(' %s %s', array($this->getFlow3InvocationString(), $usage));
  163. $argumentDescriptions = array();
  164. $optionDescriptions = array();
  165. if ($command->hasArguments()) {
  166. foreach ($commandArgumentDefinitions as $commandArgumentDefinition) {
  167. $argumentDescription = $commandArgumentDefinition->getDescription();
  168. $argumentDescription = wordwrap($argumentDescription, self::MAXIMUM_LINE_LENGTH - 23, PHP_EOL . str_repeat(' ', 23), TRUE);
  169. if ($commandArgumentDefinition->isRequired()) {
  170. $argumentDescriptions[] = vsprintf(' %-20s %s', array($commandArgumentDefinition->getDashedName(), $argumentDescription));
  171. } else {
  172. $optionDescriptions[] = vsprintf(' %-20s %s', array($commandArgumentDefinition->getDashedName(), $argumentDescription));
  173. }
  174. }
  175. }
  176. if (count($argumentDescriptions) > 0) {
  177. $this->outputLine();
  178. $this->outputLine('<b>ARGUMENTS:</b>');
  179. foreach ($argumentDescriptions as $argumentDescription) {
  180. $this->outputLine($argumentDescription);
  181. }
  182. }
  183. if (count($optionDescriptions) > 0) {
  184. $this->outputLine();
  185. $this->outputLine('<b>OPTIONS:</b>');
  186. foreach ($optionDescriptions as $optionDescription) {
  187. $this->outputLine($optionDescription);
  188. }
  189. }
  190. if ($command->getDescription() !== '') {
  191. $this->outputLine();
  192. $this->outputLine('<b>DESCRIPTION:</b>');
  193. $descriptionLines = explode(chr(10), $command->getDescription());
  194. foreach ($descriptionLines as $descriptionLine) {
  195. $this->outputLine('%-2s%s', array(' ', $descriptionLine));
  196. }
  197. }
  198. $relatedCommandIdentifiers = $command->getRelatedCommandIdentifiers();
  199. if ($relatedCommandIdentifiers !== array()) {
  200. $this->outputLine();
  201. $this->outputLine('<b>SEE ALSO:</b>');
  202. foreach ($relatedCommandIdentifiers as $commandIdentifier) {
  203. try {
  204. $command = $this->commandManager->getCommandByIdentifier($commandIdentifier);
  205. $this->outputLine('%-2s%s (%s)', array(' ', $commandIdentifier, $command->getShortDescription()));
  206. } catch (\TYPO3\FLOW3\Mvc\Exception\CommandException $exception) {
  207. $this->outputLine('%-2s%s (%s)', array(' ', $commandIdentifier, '<i>Command not available</i>'));
  208. }
  209. }
  210. }
  211. $this->outputLine();
  212. }
  213. /**
  214. * Displays an error message
  215. *
  216. * @FLOW3\Internal
  217. * @param \TYPO3\FLOW3\Mvc\Exception\CommandException $exception
  218. * @return void
  219. */
  220. public function errorCommand(\TYPO3\FLOW3\Mvc\Exception\CommandException $exception) {
  221. $this->outputLine($exception->getMessage());
  222. if ($exception instanceof \TYPO3\FLOW3\Mvc\Exception\AmbiguousCommandIdentifierException) {
  223. $this->outputLine('Please specify the complete command identifier. Matched commands:');
  224. $this->displayShortHelpForCommands($exception->getMatchingCommands());
  225. }
  226. $this->outputLine();
  227. $this->outputLine('Enter "%s help" for an overview of all available commands', array($this->getFlow3InvocationString()));
  228. $this->outputLine('or "%s help <commandIdentifier>" for a detailed description of the corresponding command.', array($this->getFlow3InvocationString()));
  229. }
  230. /**
  231. * Builds an index of available commands. For each of them a Command object is
  232. * added to the commands array of this class.
  233. *
  234. * @param array<\TYPO3\FLOW3\Cli\Command> $commands
  235. * @return array in the format array('<packageKey>' => array('<CommandControllerClassName>', array('<command1>' => $command1, '<command2>' => $command2)))
  236. */
  237. protected function buildCommandsIndex(array $commands) {
  238. $commandsByPackagesAndControllers = array();
  239. foreach ($commands as $command) {
  240. if ($command->isInternal()) {
  241. continue;
  242. }
  243. $commandIdentifier = $command->getCommandIdentifier();
  244. $packageKey = strstr($commandIdentifier, ':', TRUE);
  245. $commandControllerClassName = $command->getControllerClassName();
  246. $commandName = $command->getControllerCommandName();
  247. $commandsByPackagesAndControllers[$packageKey][$commandControllerClassName][$commandName] = $command;
  248. }
  249. return $commandsByPackagesAndControllers;
  250. }
  251. }
  252. ?>