Revert "[FEATURE] Introduce beforeCallActionMethod signal"
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Mvc / Controller / AbstractController.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Mvc\Controller;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2012 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 textfile 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 * An abstract base class for Controllers
32 *
33 * @api
34 */
35 abstract class AbstractController implements \TYPO3\CMS\Extbase\Mvc\Controller\ControllerInterface {
36
37 /**
38 * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
39 * @inject
40 */
41 protected $signalSlotDispatcher;
42
43 /**
44 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
45 */
46 protected $objectManager;
47
48 /**
49 * @var \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder
50 */
51 protected $uriBuilder;
52
53 /**
54 * @var string Key of the extension this controller belongs to
55 */
56 protected $extensionName;
57
58 /**
59 * Contains the settings of the current extension
60 *
61 * @var array
62 * @api
63 */
64 protected $settings;
65
66 /**
67 * The current request.
68 *
69 * @var \TYPO3\CMS\Extbase\Mvc\Request
70 * @api
71 */
72 protected $request;
73
74 /**
75 * The response which will be returned by this action controller
76 *
77 * @var \TYPO3\CMS\Extbase\Mvc\Response
78 * @api
79 */
80 protected $response;
81
82 /**
83 * @var \TYPO3\CMS\Extbase\Property\Mapper
84 * @deprecated since Extbase 1.4.0, will be removed in Extbase 6.1
85 */
86 protected $deprecatedPropertyMapper;
87
88 /**
89 * @var \TYPO3\CMS\Extbase\Validation\ValidatorResolver
90 */
91 protected $validatorResolver;
92
93 /**
94 * @var \TYPO3\CMS\Extbase\Mvc\Controller\Arguments Arguments passed to the controller
95 */
96 protected $arguments;
97
98 /**
99 * The results of the mapping of request arguments to controller arguments
100 *
101 * @var \TYPO3\CMS\Extbase\Property\MappingResults
102 * @api
103 * @deprecated since Extbase 1.4.0, will be removed in Extbase 6.1
104 */
105 protected $argumentsMappingResults;
106
107 /**
108 * An array of supported request types. By default only web requests are supported.
109 * Modify or replace this array if your specific controller supports certain
110 * (additional) request types.
111 *
112 * @var array
113 */
114 protected $supportedRequestTypes = array('TYPO3\\CMS\\Extbase\\Mvc\\Request');
115
116 /**
117 * @var \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext
118 * @api
119 */
120 protected $controllerContext;
121
122 /**
123 * The flash messages. Use $this->flashMessageContainer->add(...) to add a new Flash message.
124 *
125 * @var \TYPO3\CMS\Extbase\Mvc\Controller\FlashMessageContainer
126 * @api
127 */
128 protected $flashMessageContainer;
129
130 /**
131 * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
132 */
133 protected $configurationManager;
134
135 /**
136 * Constructs the controller.
137 */
138 public function __construct() {
139 $className = get_class($this);
140 if (strpos($className, '\\') !== FALSE) {
141 $classNameParts = explode('\\', $className, 4);
142 // Skip vendor and product name for core classes
143 if (strpos($className, 'TYPO3\\CMS\\') === 0) {
144 $this->extensionName = $classNameParts[2];
145 } else {
146 $this->extensionName = $classNameParts[1];
147 }
148 } else {
149 list(, $this->extensionName) = explode('_', $className);
150 }
151 }
152
153 /**
154 * @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
155 * @return void
156 */
157 public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager) {
158 $this->configurationManager = $configurationManager;
159 $this->settings = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS);
160 }
161
162 /**
163 * Injects the property mapper
164 *
165 * @param \TYPO3\CMS\Extbase\Property\Mapper $deprecatedPropertyMapper The property mapper
166 * @return void
167 * @deprecated since Extbase 1.4.0, will be removed in Extbase 6.1
168 */
169 public function injectDeprecatedPropertyMapper(\TYPO3\CMS\Extbase\Property\Mapper $deprecatedPropertyMapper) {
170 $this->deprecatedPropertyMapper = $deprecatedPropertyMapper;
171 }
172
173 /**
174 * Injects the object manager
175 *
176 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
177 * @return void
178 */
179 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) {
180 $this->objectManager = $objectManager;
181 $this->arguments = $this->objectManager->create('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\Arguments');
182 }
183
184 /**
185 * Injects the validator resolver
186 *
187 * @param \TYPO3\CMS\Extbase\Validation\ValidatorResolver $validatorResolver
188 * @return void
189 */
190 public function injectValidatorResolver(\TYPO3\CMS\Extbase\Validation\ValidatorResolver $validatorResolver) {
191 $this->validatorResolver = $validatorResolver;
192 }
193
194 /**
195 * Injects the flash messages container
196 *
197 * @param \TYPO3\CMS\Extbase\Mvc\Controller\FlashMessageContainer $flashMessageContainer
198 * @return void
199 */
200 public function injectFlashMessageContainer(\TYPO3\CMS\Extbase\Mvc\Controller\FlashMessageContainer $flashMessageContainer) {
201 $this->flashMessageContainer = $flashMessageContainer;
202 }
203
204 /**
205 * Checks if the current request type is supported by the controller.
206 *
207 * If your controller only supports certain request types, either
208 * replace / modify the supporteRequestTypes property or override this
209 * method.
210 *
211 * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request The current request
212 * @return boolean TRUE if this request type is supported, otherwise FALSE
213 * @api
214 */
215 public function canProcessRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request) {
216 foreach ($this->supportedRequestTypes as $supportedRequestType) {
217 if ($request instanceof $supportedRequestType) {
218 return TRUE;
219 }
220 }
221 return FALSE;
222 }
223
224 /**
225 * Processes a general request. The result can be returned by altering the given response.
226 *
227 * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request The request object
228 * @param \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response The response, modified by this handler
229 * @return void
230 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException if the controller doesn't support the current request type
231 * @api
232 */
233 public function processRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request, \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response) {
234 if (!$this->canProcessRequest($request)) {
235 throw new \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException(get_class($this) . ' does not support requests of type "' . get_class($request) . '". Supported types are: ' . implode(' ', $this->supportedRequestTypes), 1187701131);
236 }
237 $response->setRequest($request);
238 $this->request = $request;
239 $this->request->setDispatched(TRUE);
240 $this->response = $response;
241 $this->uriBuilder = $this->objectManager->create('TYPO3\\CMS\\Extbase\\Mvc\\Web\\Routing\\UriBuilder');
242 $this->uriBuilder->setRequest($request);
243 $this->initializeControllerArgumentsBaseValidators();
244 $this->mapRequestArgumentsToControllerArguments();
245 $this->controllerContext = $this->buildControllerContext();
246 }
247
248 /**
249 * Initialize the controller context
250 *
251 * @return \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext ControllerContext to be passed to the view
252 * @api
253 */
254 protected function buildControllerContext() {
255 $controllerContext = $this->objectManager->create('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\ControllerContext');
256 $controllerContext->setRequest($this->request);
257 $controllerContext->setResponse($this->response);
258 if ($this->arguments !== NULL) {
259 $controllerContext->setArguments($this->arguments);
260 }
261 if ($this->argumentsMappingResults !== NULL) {
262 $controllerContext->setArgumentsMappingResults($this->argumentsMappingResults);
263 }
264 $controllerContext->setUriBuilder($this->uriBuilder);
265 $controllerContext->setFlashMessageContainer($this->flashMessageContainer);
266 return $controllerContext;
267 }
268
269 /**
270 * Forwards the request to another action and / or controller.
271 *
272 * Request is directly transfered to the other action / controller
273 * without the need for a new request.
274 *
275 * @param string $actionName Name of the action to forward to
276 * @param string $controllerName Unqualified object name of the controller to forward to. If not specified, the current controller is used.
277 * @param string $extensionName Name of the extension containing the controller to forward to. If not specified, the current extension is assumed.
278 * @param array $arguments Arguments to pass to the target action
279 * @return void
280 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
281 * @see redirect()
282 * @api
283 */
284 public function forward($actionName, $controllerName = NULL, $extensionName = NULL, array $arguments = NULL) {
285 $this->request->setDispatched(FALSE);
286 $this->request->setControllerActionName($actionName);
287 if ($controllerName !== NULL) {
288 $this->request->setControllerName($controllerName);
289 }
290 if ($extensionName !== NULL) {
291 $this->request->setControllerExtensionName($extensionName);
292 }
293 if ($arguments !== NULL) {
294 $this->request->setArguments($arguments);
295 }
296 throw new \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException();
297 }
298
299 /**
300 * Redirects the request to another action and / or controller.
301 *
302 * Redirect will be sent to the client which then performs another request to the new URI.
303 *
304 * NOTE: This method only supports web requests and will thrown an exception
305 * if used with other request types.
306 *
307 * @param string $actionName Name of the action to forward to
308 * @param string $controllerName Unqualified object name of the controller to forward to. If not specified, the current controller is used.
309 * @param string $extensionName Name of the extension containing the controller to forward to. If not specified, the current extension is assumed.
310 * @param array $arguments Arguments to pass to the target action
311 * @param integer $pageUid Target page uid. If NULL, the current page uid is used
312 * @param integer $delay (optional) The delay in seconds. Default is no delay.
313 * @param integer $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other
314 * @return void
315 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException If the request is not a web request
316 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
317 * @see forward()
318 * @api
319 */
320 protected function redirect($actionName, $controllerName = NULL, $extensionName = NULL, array $arguments = NULL, $pageUid = NULL, $delay = 0, $statusCode = 303) {
321 if (!$this->request instanceof \TYPO3\CMS\Extbase\Mvc\Web\Request) {
322 throw new \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException('redirect() only supports web requests.', 1220539734);
323 }
324 if ($controllerName === NULL) {
325 $controllerName = $this->request->getControllerName();
326 }
327 $uri = $this->uriBuilder->reset()->setTargetPageUid($pageUid)->setCreateAbsoluteUri(TRUE)->uriFor($actionName, $arguments, $controllerName, $extensionName);
328 $this->redirectToUri($uri, $delay, $statusCode);
329 }
330
331 /**
332 * Redirects the web request to another uri.
333 *
334 * NOTE: This method only supports web requests and will thrown an exception if used with other request types.
335 *
336 * @param mixed $uri A string representation of a URI
337 * @param integer $delay (optional) The delay in seconds. Default is no delay.
338 * @param integer $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other
339 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException If the request is not a web request
340 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
341 * @api
342 */
343 protected function redirectToUri($uri, $delay = 0, $statusCode = 303) {
344 if (!$this->request instanceof \TYPO3\CMS\Extbase\Mvc\Web\Request) {
345 throw new \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException('redirect() only supports web requests.', 1220539734);
346 }
347 $uri = $this->addBaseUriIfNecessary($uri);
348 $escapedUri = htmlentities($uri, ENT_QUOTES, 'utf-8');
349 $this->response->setContent('<html><head><meta http-equiv="refresh" content="' . intval($delay) . ';url=' . $escapedUri . '"/></head></html>');
350 $this->response->setStatus($statusCode);
351 $this->response->setHeader('Location', (string) $uri);
352 throw new \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException();
353 }
354
355 /**
356 * Adds the base uri if not already in place.
357 *
358 * @param string $uri The URI
359 * @return string
360 */
361 protected function addBaseUriIfNecessary($uri) {
362 return \TYPO3\CMS\Core\Utility\GeneralUtility::locationHeaderUrl((string) $uri);
363 }
364
365 /**
366 * Sends the specified HTTP status immediately.
367 *
368 * NOTE: This method only supports web requests and will thrown an exception if used with other request types.
369 *
370 * @param integer $statusCode The HTTP status code
371 * @param string $statusMessage A custom HTTP status message
372 * @param string $content Body content which further explains the status
373 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException If the request is not a web request
374 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
375 * @api
376 */
377 public function throwStatus($statusCode, $statusMessage = NULL, $content = NULL) {
378 if (!$this->request instanceof \TYPO3\CMS\Extbase\Mvc\Web\Request) {
379 throw new \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException('throwStatus() only supports web requests.', 1220539739);
380 }
381 $this->response->setStatus($statusCode, $statusMessage);
382 if ($content === NULL) {
383 $content = $this->response->getStatus();
384 }
385 $this->response->setContent($content);
386 throw new \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException();
387 }
388
389 /**
390 * Collects the base validators which were defined for the data type of each
391 * controller argument and adds them to the argument's validator chain.
392 *
393 * @return void
394 */
395 public function initializeControllerArgumentsBaseValidators() {
396 foreach ($this->arguments as $argument) {
397 $validator = $this->validatorResolver->getBaseValidatorConjunction($argument->getDataType());
398 if ($validator !== NULL) {
399 $argument->setValidator($validator);
400 }
401 }
402 }
403
404 /**
405 * Maps arguments delivered by the request object to the local controller arguments.
406 *
407 * @throws Exception\RequiredArgumentMissingException
408 * @return void
409 */
410 protected function mapRequestArgumentsToControllerArguments() {
411 if ($this->configurationManager->isFeatureEnabled('rewrittenPropertyMapper')) {
412 foreach ($this->arguments as $argument) {
413 $argumentName = $argument->getName();
414 if ($this->request->hasArgument($argumentName)) {
415 $argument->setValue($this->request->getArgument($argumentName));
416 } elseif ($argument->isRequired()) {
417 throw new \TYPO3\CMS\Extbase\Mvc\Controller\Exception\RequiredArgumentMissingException('Required argument "' . $argumentName . '" is not set.', 1298012500);
418 }
419 }
420 } else {
421 // @deprecated since Extbase 1.4, will be removed in Extbase 6.1
422 $optionalPropertyNames = array();
423 $allPropertyNames = $this->arguments->getArgumentNames();
424 foreach ($allPropertyNames as $propertyName) {
425 if ($this->arguments[$propertyName]->isRequired() === FALSE) {
426 $optionalPropertyNames[] = $propertyName;
427 }
428 }
429 /** @var $validator ArgumentsValidator */
430 $validator = $this->objectManager->create('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\ArgumentsValidator');
431 $this->deprecatedPropertyMapper->mapAndValidate($allPropertyNames, $this->request->getArguments(), $this->arguments, $optionalPropertyNames, $validator);
432 $this->argumentsMappingResults = $this->deprecatedPropertyMapper->getMappingResults();
433 }
434 }
435 }
436
437 ?>