b553d58599829926473b46db38ec68a1f2911e29
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Mvc / Controller / CommandController.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Mvc\Controller;
3
4 /***************************************************************
5 * Copyright notice
6 * All rights reserved
7 *
8 * This class is a backport of the corresponding class of TYPO3 Flow.
9 * All credits go to the TYPO3 Flow team.
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 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * A controller which processes requests from the command line
29 *
30 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
31 */
32 class CommandController implements \TYPO3\CMS\Extbase\Mvc\Controller\CommandControllerInterface {
33
34 const MAXIMUM_LINE_LENGTH = 79;
35
36 /**
37 * @var \TYPO3\CMS\Extbase\Mvc\Cli\Request
38 */
39 protected $request;
40
41 /**
42 * @var \TYPO3\CMS\Extbase\Mvc\Cli\Response
43 */
44 protected $response;
45
46 /**
47 * @var \TYPO3\CMS\Extbase\Mvc\Controller\Arguments
48 */
49 protected $arguments;
50
51 /**
52 * Name of the command method
53 *
54 * @var string
55 */
56 protected $commandMethodName = '';
57
58 /**
59 * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
60 */
61 protected $reflectionService;
62
63 /**
64 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
65 */
66 protected $objectManager;
67
68 /**
69 * @param \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService
70 * @return void
71 */
72 public function injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService) {
73 $this->reflectionService = $reflectionService;
74 }
75
76 /**
77 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
78 * @return void
79 */
80 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) {
81 $this->objectManager = $objectManager;
82 $this->arguments = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\Arguments');
83 }
84
85 /**
86 * Checks if the current request type is supported by the controller.
87 *
88 * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request The current request
89 * @return boolean TRUE if this request type is supported, otherwise FALSE
90 */
91 public function canProcessRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request) {
92 return $request instanceof \TYPO3\CMS\Extbase\Mvc\Cli\Request;
93 }
94
95 /**
96 * Processes a command line request.
97 *
98 * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request The request object
99 * @param \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response The response, modified by this controller
100 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
101 * @return void
102 * @api
103 */
104 public function processRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request, \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response) {
105 if (!$this->canProcessRequest($request)) {
106 throw new \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException(get_class($this) . ' does not support requests of type "' . get_class($request) . '".', 1300787096);
107 }
108 $this->request = $request;
109 $this->request->setDispatched(TRUE);
110 $this->response = $response;
111 $this->commandMethodName = $this->resolveCommandMethodName();
112 $this->initializeCommandMethodArguments();
113 $this->mapRequestArgumentsToControllerArguments();
114 $this->callCommandMethod();
115 }
116
117 /**
118 * Resolves and checks the current command method name
119 *
120 * Note: The resulting command method name might not have the correct case, which isn't a problem because PHP is
121 * case insensitive regarding method names.
122 *
123 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchCommandException
124 * @return string Method name of the current command
125 */
126 protected function resolveCommandMethodName() {
127 $commandMethodName = $this->request->getControllerCommandName() . 'Command';
128 if (!is_callable(array($this, $commandMethodName))) {
129 throw new \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchCommandException('A command method "' . $commandMethodName . '()" does not exist in controller "' . get_class($this) . '".', 1300902143);
130 }
131 return $commandMethodName;
132 }
133
134 /**
135 * Initializes the arguments array of this controller by creating an empty argument object for each of the
136 * method arguments found in the designated command method.
137 *
138 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentTypeException
139 * @return void
140 */
141 protected function initializeCommandMethodArguments() {
142 $methodParameters = $this->reflectionService->getMethodParameters(get_class($this), $this->commandMethodName);
143 foreach ($methodParameters as $parameterName => $parameterInfo) {
144 $dataType = NULL;
145 if (isset($parameterInfo['type'])) {
146 $dataType = $parameterInfo['type'];
147 } elseif ($parameterInfo['array']) {
148 $dataType = 'array';
149 }
150 if ($dataType === NULL) {
151 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentTypeException('The argument type for parameter $' . $parameterName . ' of method ' . get_class($this) . '->' . $this->commandMethodName . '() could not be detected.', 1306755296);
152 }
153 $defaultValue = isset($parameterInfo['defaultValue']) ? $parameterInfo['defaultValue'] : NULL;
154 $this->arguments->addNewArgument($parameterName, $dataType, $parameterInfo['optional'] === FALSE, $defaultValue);
155 }
156 }
157
158 /**
159 * Maps arguments delivered by the request object to the local controller arguments.
160 *
161 * @return void
162 */
163 protected function mapRequestArgumentsToControllerArguments() {
164 foreach ($this->arguments as $argument) {
165 $argumentName = $argument->getName();
166 if ($this->request->hasArgument($argumentName)) {
167 $argument->setValue($this->request->getArgument($argumentName));
168 } elseif ($argument->isRequired()) {
169 $exception = new \TYPO3\CMS\Extbase\Mvc\Exception\CommandException('Required argument "' . $argumentName . '" is not set.', 1306755520);
170 $this->forward('error', 'TYPO3\\CMS\\Extbase\\Command\\HelpCommandController', array('exception' => $exception));
171 }
172 }
173 }
174
175 /**
176 * Forwards the request to another command and / or CommandController.
177 *
178 * Request is directly transferred to the other command / controller
179 * without the need for a new request.
180 *
181 * @param string $commandName
182 * @param string $controllerObjectName
183 * @param array $arguments
184 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
185 * @return void
186 */
187 protected function forward($commandName, $controllerObjectName = NULL, array $arguments = array()) {
188 $this->request->setDispatched(FALSE);
189 $this->request->setControllerCommandName($commandName);
190 if ($controllerObjectName !== NULL) {
191 $this->request->setControllerObjectName($controllerObjectName);
192 }
193 $this->request->setArguments($arguments);
194 $this->arguments->removeAll();
195 throw new \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException();
196 }
197
198 /**
199 * Calls the specified command method and passes the arguments.
200 *
201 * If the command returns a string, it is appended to the content in the
202 * response object. If the command doesn't return anything and a valid
203 * view exists, the view is rendered automatically.
204 *
205 * @return void
206 */
207 protected function callCommandMethod() {
208 $preparedArguments = array();
209 foreach ($this->arguments as $argument) {
210 $preparedArguments[] = $argument->getValue();
211 }
212 $commandResult = call_user_func_array(array($this, $this->commandMethodName), $preparedArguments);
213 if (is_string($commandResult) && strlen($commandResult) > 0) {
214 $this->response->appendContent($commandResult);
215 } elseif (is_object($commandResult) && method_exists($commandResult, '__toString')) {
216 $this->response->appendContent((string) $commandResult);
217 }
218 }
219
220 /**
221 * Outputs specified text to the console window
222 * You can specify arguments that will be passed to the text via sprintf
223 *
224 * @see http://www.php.net/sprintf
225 * @param string $text Text to output
226 * @param array $arguments Optional arguments to use for sprintf
227 * @return void
228 */
229 protected function output($text, array $arguments = array()) {
230 if ($arguments !== array()) {
231 $text = vsprintf($text, $arguments);
232 }
233 $this->response->appendContent($text);
234 }
235
236 /**
237 * Outputs specified text to the console window and appends a line break
238 *
239 * @param string $text Text to output
240 * @param array $arguments Optional arguments to use for sprintf
241 * @return string
242 * @see output()
243 */
244 protected function outputLine($text = '', array $arguments = array()) {
245 return $this->output($text . PHP_EOL, $arguments);
246 }
247
248 /**
249 * Exits the CLI through the dispatcher
250 * An exit status code can be specified @see http://www.php.net/exit
251 *
252 * @param integer $exitCode Exit code to return on exit
253 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
254 * @return void
255 */
256 protected function quit($exitCode = 0) {
257 $this->response->setExitCode($exitCode);
258 throw new \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException();
259 }
260
261 /**
262 * Sends the response and exits the CLI without any further code execution
263 * Should be used for commands that flush code caches.
264 *
265 * @param integer $exitCode Exit code to return on exit
266 * @return void
267 */
268 protected function sendAndExit($exitCode = 0) {
269 $this->response->send();
270 die($exitCode);
271 }
272 }
273
274 ?>