2 namespace TYPO3\CMS\Extbase\Mvc\Cli
;
5 * This file is part of the TYPO3 CMS project.
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.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
17 use TYPO3\CMS\Extbase\Reflection\ClassSchema
;
20 * Represents a Command
22 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
27 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
29 protected $objectManager;
34 protected $controllerClassName;
39 protected $controllerCommandName;
44 protected $commandIdentifier;
47 * Name of the extension to which this command belongs
51 protected $extensionName;
54 * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
56 protected $reflectionService;
61 protected $classSchema;
66 protected $controllerCommandMethod;
69 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
71 public function injectObjectManager(\TYPO3\CMS\Extbase\
Object\ObjectManagerInterface
$objectManager)
73 $this->objectManager
= $objectManager;
77 * @param \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService
79 public function injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService
$reflectionService)
81 $this->reflectionService
= $reflectionService;
87 * @param string $controllerClassName Class name of the controller providing the command
88 * @param string $controllerCommandName Command name, i.e. the method name of the command, without the "Command" suffix
89 * @throws \InvalidArgumentException
91 public function __construct($controllerClassName, $controllerCommandName)
93 $this->controllerClassName
= $controllerClassName;
94 $this->controllerCommandName
= $controllerCommandName;
95 $this->controllerCommandMethod
= $this->controllerCommandName
. 'Command';
96 $classNameParts = explode('\\', $controllerClassName);
97 if (isset($classNameParts[0]) && $classNameParts[0] === 'TYPO3' && isset($classNameParts[1]) && $classNameParts[1] === 'CMS') {
98 $classNameParts[0] .= '\\' . $classNameParts[1];
99 unset($classNameParts[1]);
100 $classNameParts = array_values($classNameParts);
102 $numberOfClassNameParts = count($classNameParts);
103 if ($numberOfClassNameParts < 3) {
104 throw new \
InvalidArgumentException(
105 'Controller class names must at least consist of three parts: vendor, extension name and path.',
109 if (strpos($classNameParts[$numberOfClassNameParts - 1], 'CommandController') === false) {
110 throw new \
InvalidArgumentException(
111 'Invalid controller class name "' . $controllerClassName . '". Class name must end with "CommandController".',
116 $this->extensionName
= $classNameParts[1];
117 $extensionKey = \TYPO3\CMS\Core\Utility\GeneralUtility
::camelCaseToLowerCaseUnderscored($this->extensionName
);
118 $this->commandIdentifier
= strtolower($extensionKey . ':' . substr($classNameParts[$numberOfClassNameParts - 1], 0, -17) . ':' . $controllerCommandName);
121 public function initializeObject()
123 $this->classSchema
= $this->reflectionService
->getClassSchema($this->controllerClassName
);
129 public function getControllerClassName()
131 return $this->controllerClassName
;
137 public function getControllerCommandName()
139 return $this->controllerCommandName
;
143 * Returns the command identifier for this command
145 * @return string The command identifier for this command, following the pattern extensionname:controllername:commandname
147 public function getCommandIdentifier()
149 return $this->commandIdentifier
;
153 * Returns the name of the extension to which this command belongs
157 public function getExtensionName()
159 return $this->extensionName
;
163 * Returns a short description of this command
165 * @return string A short description
167 public function getShortDescription()
169 $lines = explode(LF
, $this->classSchema
->getMethod($this->controllerCommandMethod
)['description']);
170 return !empty($lines) ?
trim($lines[0]) : '<no description available>';
174 * Returns a longer description of this command
175 * This is the complete method description except for the first line which can be retrieved via getShortDescription()
176 * If The command description only consists of one line, an empty string is returned
178 * @return string A longer description of this command
180 public function getDescription()
182 $lines = explode(LF
, $this->classSchema
->getMethod($this->controllerCommandMethod
)['description']);
184 $descriptionLines = [];
185 foreach ($lines as $line) {
186 $trimmedLine = trim($line);
187 if ($descriptionLines !== [] ||
$trimmedLine !== '') {
188 $descriptionLines[] = $trimmedLine;
191 return implode(LF
, $descriptionLines);
195 * Returns TRUE if this command expects required and/or optional arguments, otherwise FALSE
199 public function hasArguments()
201 return !empty($this->classSchema
->getMethod($this->controllerCommandMethod
)['params']);
205 * Returns an array of \TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition that contains
206 * information about required/optional arguments of this command.
207 * If the command does not expect any arguments, an empty array is returned
209 * @return array<\TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition>
211 public function getArgumentDefinitions()
213 if (!$this->hasArguments()) {
216 $commandArgumentDefinitions = [];
217 $commandParameters = $this->classSchema
->getMethod($this->controllerCommandMethod
)['params'];
218 $commandParameterTags = $this->classSchema
->getMethod($this->controllerCommandMethod
)['tags']['param'];
220 foreach ($commandParameters as $commandParameterName => $commandParameterDefinition) {
221 $explodedAnnotation = preg_split('/\s+/', $commandParameterTags[$i], 3);
222 $description = !empty($explodedAnnotation[2]) ?
$explodedAnnotation[2] : '';
223 $required = $commandParameterDefinition['optional'] !== true;
224 $commandArgumentDefinitions[] = $this->objectManager
->get(\TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition
::class, $commandParameterName, $required, $description);
227 return $commandArgumentDefinitions;
231 * Tells if this command is internal and thus should not be exposed through help texts, user documentation etc.
232 * Internall commands are still accessible through the regular command line interface, but should not be used
237 public function isInternal()
239 return isset($this->classSchema
->getMethod($this->controllerCommandMethod
)['tags']['internal']);
243 * Tells if this command is meant to be used on CLI only.
247 * todo: deprecate/remove method in TYPO3 10.x while refactoring the scheduler implementation
249 public function isCliOnly()
251 return isset($this->classSchema
->getMethod($this->controllerCommandMethod
)['tags']['cli']);
255 * Tells if this command flushes all caches and thus needs special attention in the interactive shell.
257 * Note that neither this method nor the @flushesCaches annotation is currently part of the official API.
261 public function isFlushingCaches()
263 return isset($this->classSchema
->getMethod($this->controllerCommandMethod
)['tags']['flushesCaches']);
267 * Returns an array of command identifiers which were specified in the "@see"
268 * annotation of a command method.
272 public function getRelatedCommandIdentifiers()
274 if (!isset($this->classSchema
->getMethod($this->controllerCommandMethod
)['tags']['see'])) {
277 $relatedCommandIdentifiers = [];
278 foreach ($this->classSchema
->getMethod($this->controllerCommandMethod
)['tags']['see'] as $tagValue) {
279 if (preg_match('/^[\\w\\d\\.]+:[\\w\\d]+:[\\w\\d]+$/', $tagValue) === 1) {
280 $relatedCommandIdentifiers[] = $tagValue;
283 return $relatedCommandIdentifiers;