[BUGFIX] Improve the formatting of help of the CommandController
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Mvc / Cli / Command.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Mvc\Cli;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2013 Extbase Team (http://forge.typo3.org/projects/typo3v4-mvc)
8 * Extbase is a backport of TYPO3 Flow. All credits go to the TYPO3 Flow team.
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the text file GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30 /**
31 * Represents a Command
32 *
33 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
34 */
35 class Command {
36
37 /**
38 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
39 * @inject
40 */
41 protected $objectManager;
42
43 /**
44 * @var string
45 */
46 protected $controllerClassName;
47
48 /**
49 * @var string
50 */
51 protected $controllerCommandName;
52
53 /**
54 * @var string
55 */
56 protected $commandIdentifier;
57
58 /**
59 * @var \TYPO3\CMS\Extbase\Reflection\MethodReflection
60 */
61 protected $commandMethodReflection;
62
63 /**
64 * Name of the extension to which this command belongs
65 *
66 * @var string
67 */
68 protected $extensionName;
69
70 /**
71 * Reflection service
72 *
73 * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
74 * @inject
75 */
76 protected $reflectionService;
77
78 /**
79 * Constructor
80 *
81 * @param string $controllerClassName Class name of the controller providing the command
82 * @param string $controllerCommandName Command name, i.e. the method name of the command, without the "Command" suffix
83 * @throws \InvalidArgumentException
84 */
85 public function __construct($controllerClassName, $controllerCommandName) {
86 $this->controllerClassName = $controllerClassName;
87 $this->controllerCommandName = $controllerCommandName;
88 $delimiter = strpos($controllerClassName, '\\') !== FALSE ? '\\' : '_';
89 $classNameParts = explode($delimiter, $controllerClassName);
90 if (isset($classNameParts[0]) && $classNameParts[0] === 'TYPO3' && isset($classNameParts[1]) && $classNameParts[1] === 'CMS') {
91 $classNameParts[0] .= '\\' . $classNameParts[1];
92 unset($classNameParts[1]);
93 $classNameParts = array_values($classNameParts);
94 }
95 if (count($classNameParts) !== 4 || strpos($classNameParts[3], 'CommandController') === FALSE) {
96 throw new \InvalidArgumentException('Invalid controller class name "' . $controllerClassName . '"', 1305100019);
97 }
98 $this->extensionName = $classNameParts[1];
99 $extensionKey = \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($this->extensionName);
100 $this->commandIdentifier = strtolower($extensionKey . ':' . substr($classNameParts[3], 0, -17) . ':' . $controllerCommandName);
101 }
102
103 /**
104 * @return string
105 */
106 public function getControllerClassName() {
107 return $this->controllerClassName;
108 }
109
110 /**
111 * @return string
112 */
113 public function getControllerCommandName() {
114 return $this->controllerCommandName;
115 }
116
117 /**
118 * Returns the command identifier for this command
119 *
120 * @return string The command identifier for this command, following the pattern extensionname:controllername:commandname
121 */
122 public function getCommandIdentifier() {
123 return $this->commandIdentifier;
124 }
125
126 /**
127 * Returns the name of the extension to which this command belongs
128 *
129 * @return string
130 */
131 public function getExtensionName() {
132 return $this->extensionName;
133 }
134
135 /**
136 * Returns a short description of this command
137 *
138 * @return string A short description
139 */
140 public function getShortDescription() {
141 $lines = explode(chr(10), $this->getCommandMethodReflection()->getDescription());
142 return count($lines) > 0 ? trim($lines[0]) : '<no description available>';
143 }
144
145 /**
146 * Returns a longer description of this command
147 * This is the complete method description except for the first line which can be retrieved via getShortDescription()
148 * If The command description only consists of one line, an empty string is returned
149 *
150 * @return string A longer description of this command
151 */
152 public function getDescription() {
153 $lines = explode(chr(10), $this->getCommandMethodReflection()->getDescription());
154 array_pop($lines);
155 $descriptionLines = array();
156 foreach ($lines as $line) {
157 $trimmedLine = trim($line);
158 if ($descriptionLines !== array() || $trimmedLine !== '') {
159 $descriptionLines[] = $trimmedLine;
160 }
161 }
162 return implode(chr(10), $descriptionLines);
163 }
164
165 /**
166 * Returns TRUE if this command expects required and/or optional arguments, otherwise FALSE
167 *
168 * @return boolean
169 */
170 public function hasArguments() {
171 return count($this->getCommandMethodReflection()->getParameters()) > 0;
172 }
173
174 /**
175 * Returns an array of \TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition that contains
176 * information about required/optional arguments of this command.
177 * If the command does not expect any arguments, an empty array is returned
178 *
179 * @return array<\TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition>
180 */
181 public function getArgumentDefinitions() {
182 if (!$this->hasArguments()) {
183 return array();
184 }
185 $commandArgumentDefinitions = array();
186 $commandMethodReflection = $this->getCommandMethodReflection();
187 $annotations = $commandMethodReflection->getTagsValues();
188 $commandParameters = $this->reflectionService->getMethodParameters($this->controllerClassName, $this->controllerCommandName . 'Command');
189 $i = 0;
190 foreach ($commandParameters as $commandParameterName => $commandParameterDefinition) {
191 $explodedAnnotation = explode(' ', $annotations['param'][$i]);
192 array_shift($explodedAnnotation);
193 array_shift($explodedAnnotation);
194 $description = ltrim(implode(' ', $explodedAnnotation));
195 $required = $commandParameterDefinition['optional'] !== TRUE;
196 $commandArgumentDefinitions[] = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Mvc\\Cli\\CommandArgumentDefinition', $commandParameterName, $required, $description);
197 $i++;
198 }
199 return $commandArgumentDefinitions;
200 }
201
202 /**
203 * Tells if this command is internal and thus should not be exposed through help texts, user documentation etc.
204 * Internall commands are still accessible through the regular command line interface, but should not be used
205 * by users.
206 *
207 * @return boolean
208 */
209 public function isInternal() {
210 return $this->getCommandMethodReflection()->isTaggedWith('internal');
211 }
212
213 /**
214 * Tells if this command flushes all caches and thus needs special attention in the interactive shell.
215 *
216 * Note that neither this method nor the @flushesCaches annotation is currently part of the official API.
217 *
218 * @return boolean
219 */
220 public function isFlushingCaches() {
221 return $this->getCommandMethodReflection()->isTaggedWith('flushesCaches');
222 }
223
224 /**
225 * Returns an array of command identifiers which were specified in the "@see"
226 * annotation of a command method.
227 *
228 * @return array
229 */
230 public function getRelatedCommandIdentifiers() {
231 $commandMethodReflection = $this->getCommandMethodReflection();
232 if (!$commandMethodReflection->isTaggedWith('see')) {
233 return array();
234 }
235 $relatedCommandIdentifiers = array();
236 foreach ($commandMethodReflection->getTagValues('see') as $tagValue) {
237 if (preg_match('/^[\\w\\d\\.]+:[\\w\\d]+:[\\w\\d]+$/', $tagValue) === 1) {
238 $relatedCommandIdentifiers[] = $tagValue;
239 }
240 }
241 return $relatedCommandIdentifiers;
242 }
243
244 /**
245 * @return \TYPO3\CMS\Extbase\Reflection\MethodReflection
246 */
247 protected function getCommandMethodReflection() {
248 if ($this->commandMethodReflection === NULL) {
249 $this->commandMethodReflection = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Reflection\\MethodReflection', $this->controllerClassName, $this->controllerCommandName . 'Command');
250 }
251 return $this->commandMethodReflection;
252 }
253 }