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