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