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