[TASK] Add FlashMessage API to Extbase AbstractController
[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 text file 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 two versions after Extbase 6.1
85 * @inject
86 */
87 protected $deprecatedPropertyMapper;
88
89 /**
90 * @var \TYPO3\CMS\Extbase\Validation\ValidatorResolver
91 * @inject
92 */
93 protected $validatorResolver;
94
95 /**
96 * @var \TYPO3\CMS\Extbase\Mvc\Controller\Arguments Arguments passed to the controller
97 */
98 protected $arguments;
99
100 /**
101 * The results of the mapping of request arguments to controller arguments
102 *
103 * @var \TYPO3\CMS\Extbase\Property\MappingResults
104 * @api
105 * @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
106 */
107 protected $argumentsMappingResults;
108
109 /**
110 * An array of supported request types. By default only web requests are supported.
111 * Modify or replace this array if your specific controller supports certain
112 * (additional) request types.
113 *
114 * @var array
115 */
116 protected $supportedRequestTypes = array('TYPO3\\CMS\\Extbase\\Mvc\\Request');
117
118 /**
119 * @var \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext
120 * @api
121 */
122 protected $controllerContext;
123
124 /**
125 * @return ControllerContext
126 * @api
127 */
128 public function getControllerContext() {
129 return $this->controllerContext;
130 }
131
132 /**
133 * @var \TYPO3\CMS\Extbase\Mvc\Controller\FlashMessageContainer
134 * @api
135 */
136 protected $flashMessageContainer;
137
138 /**
139 * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
140 */
141 protected $configurationManager;
142
143 /**
144 * Constructs the controller.
145 */
146 public function __construct() {
147 $className = get_class($this);
148 if (strpos($className, '\\') !== FALSE) {
149 $classNameParts = explode('\\', $className, 4);
150 // Skip vendor and product name for core classes
151 if (strpos($className, 'TYPO3\\CMS\\') === 0) {
152 $this->extensionName = $classNameParts[2];
153 } else {
154 $this->extensionName = $classNameParts[1];
155 }
156 } else {
157 list(, $this->extensionName) = explode('_', $className);
158 }
159 }
160
161 /**
162 * @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
163 * @return void
164 */
165 public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager) {
166 $this->configurationManager = $configurationManager;
167 $this->settings = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS);
168 }
169
170 /**
171 * Injects the object manager
172 *
173 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
174 * @return void
175 */
176 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) {
177 $this->objectManager = $objectManager;
178 $this->arguments = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\Arguments');
179 }
180
181 /**
182 * This method is deprecated! For further information have a look at
183 * the PhpDoc of class \TYPO3\CMS\Extbase\Mvc\Controller\FlashMessageContainer
184 *
185 * @param \TYPO3\CMS\Extbase\Mvc\Controller\FlashMessageContainer $flashMessageContainer
186 * @return void
187 *
188 * @deprecated since Extbase 6.1, will be removed 2 versions later
189 */
190 public function injectFlashMessageContainer(\TYPO3\CMS\Extbase\Mvc\Controller\FlashMessageContainer $flashMessageContainer) {
191 $this->flashMessageContainer = $flashMessageContainer;
192 }
193
194 /**
195 * Creates a Message object and adds it to the FlashMessageQueue.
196 *
197 * @param string $messageBody The message
198 * @param string $messageTitle Optional message title
199 * @param integer $severity Optional severity, must be one of \TYPO3\CMS\Core\Messaging\FlashMessage constants
200 * @param boolean $storeInSession Optional, defines whether the message should be stored in the session (default) or not
201 * @return void
202 * @throws \InvalidArgumentException if the message body is no string
203 * @see \TYPO3\CMS\Core\Messaging\FlashMessage
204 * @api
205 */
206 public function addFlashMessage($messageBody, $messageTitle = '', $severity = \TYPO3\CMS\Core\Messaging\AbstractMessage::OK, $storeInSession = TRUE) {
207 if (!is_string($messageBody)) {
208 throw new \InvalidArgumentException('The message body must be of type string, "' . gettype($messageBody) . '" given.', 1243258395);
209 }
210 /* @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */
211 $flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
212 'TYPO3\\CMS\\Core\\Messaging\\FlashMessage', $messageBody, $messageTitle, $severity, $storeInSession
213 );
214 $this->controllerContext->getFlashMessageQueue()->enqueue($flashMessage);
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->get('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 /** @var $controllerContext \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext */
269 $controllerContext = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\ControllerContext');
270 $controllerContext->setRequest($this->request);
271 $controllerContext->setResponse($this->response);
272 if ($this->arguments !== NULL) {
273 $controllerContext->setArguments($this->arguments);
274 }
275 if ($this->argumentsMappingResults !== NULL) {
276 $controllerContext->setArgumentsMappingResults($this->argumentsMappingResults);
277 }
278 $controllerContext->setUriBuilder($this->uriBuilder);
279
280 $controllerContext->setFlashMessageContainer($this->flashMessageContainer);
281 return $controllerContext;
282 }
283
284 /**
285 * Forwards the request to another action and / or controller.
286 *
287 * Request is directly transfered to the other action / controller
288 * without the need for a new request.
289 *
290 * @param string $actionName Name of the action to forward to
291 * @param string $controllerName Unqualified object name of the controller to forward to. If not specified, the current controller is used.
292 * @param string $extensionName Name of the extension containing the controller to forward to. If not specified, the current extension is assumed.
293 * @param array $arguments Arguments to pass to the target action
294 * @return void
295 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
296 * @see redirect()
297 * @api
298 */
299 public function forward($actionName, $controllerName = NULL, $extensionName = NULL, array $arguments = NULL) {
300 $this->request->setDispatched(FALSE);
301 $this->request->setControllerActionName($actionName);
302 if ($controllerName !== NULL) {
303 $this->request->setControllerName($controllerName);
304 }
305 if ($extensionName !== NULL) {
306 $this->request->setControllerExtensionName($extensionName);
307 }
308 if ($arguments !== NULL) {
309 $this->request->setArguments($arguments);
310 }
311 throw new \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException();
312 }
313
314 /**
315 * Redirects the request to another action and / or controller.
316 *
317 * Redirect will be sent to the client which then performs another request to the new URI.
318 *
319 * NOTE: This method only supports web requests and will thrown an exception
320 * if used with other request types.
321 *
322 * @param string $actionName Name of the action to forward to
323 * @param string $controllerName Unqualified object name of the controller to forward to. If not specified, the current controller is used.
324 * @param string $extensionName Name of the extension containing the controller to forward to. If not specified, the current extension is assumed.
325 * @param array $arguments Arguments to pass to the target action
326 * @param integer $pageUid Target page uid. If NULL, the current page uid is used
327 * @param integer $delay (optional) The delay in seconds. Default is no delay.
328 * @param integer $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other
329 * @return void
330 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException If the request is not a web request
331 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
332 * @see forward()
333 * @api
334 */
335 protected function redirect($actionName, $controllerName = NULL, $extensionName = NULL, array $arguments = NULL, $pageUid = NULL, $delay = 0, $statusCode = 303) {
336 if (!$this->request instanceof \TYPO3\CMS\Extbase\Mvc\Web\Request) {
337 throw new \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException('redirect() only supports web requests.', 1220539734);
338 }
339 if ($controllerName === NULL) {
340 $controllerName = $this->request->getControllerName();
341 }
342 $this->uriBuilder->reset()->setTargetPageUid($pageUid)->setCreateAbsoluteUri(TRUE);
343 if (\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SSL')) {
344 $this->uriBuilder->setAbsoluteUriScheme('https');
345 }
346 $uri = $this->uriBuilder->uriFor($actionName, $arguments, $controllerName, $extensionName);
347 $this->redirectToUri($uri, $delay, $statusCode);
348 }
349
350 /**
351 * Redirects the web request to another uri.
352 *
353 * NOTE: This method only supports web requests and will thrown an exception if used with other request types.
354 *
355 * @param mixed $uri A string representation of a URI
356 * @param integer $delay (optional) The delay in seconds. Default is no delay.
357 * @param integer $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other
358 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException If the request is not a web request
359 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
360 * @api
361 */
362 protected function redirectToUri($uri, $delay = 0, $statusCode = 303) {
363 if (!$this->request instanceof \TYPO3\CMS\Extbase\Mvc\Web\Request) {
364 throw new \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException('redirect() only supports web requests.', 1220539734);
365 }
366
367 $this->objectManager->get('TYPO3\CMS\Extbase\Service\CacheService')->clearCachesOfRegisteredPageIds();
368
369 $uri = $this->addBaseUriIfNecessary($uri);
370 $escapedUri = htmlentities($uri, ENT_QUOTES, 'utf-8');
371 $this->response->setContent('<html><head><meta http-equiv="refresh" content="' . intval($delay) . ';url=' . $escapedUri . '"/></head></html>');
372 $this->response->setStatus($statusCode);
373 $this->response->setHeader('Location', (string) $uri);
374 throw new \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException();
375 }
376
377 /**
378 * Adds the base uri if not already in place.
379 *
380 * @param string $uri The URI
381 * @return string
382 */
383 protected function addBaseUriIfNecessary($uri) {
384 return \TYPO3\CMS\Core\Utility\GeneralUtility::locationHeaderUrl((string) $uri);
385 }
386
387 /**
388 * Sends the specified HTTP status immediately.
389 *
390 * NOTE: This method only supports web requests and will thrown an exception if used with other request types.
391 *
392 * @param integer $statusCode The HTTP status code
393 * @param string $statusMessage A custom HTTP status message
394 * @param string $content Body content which further explains the status
395 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException If the request is not a web request
396 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
397 * @api
398 */
399 public function throwStatus($statusCode, $statusMessage = NULL, $content = NULL) {
400 if (!$this->request instanceof \TYPO3\CMS\Extbase\Mvc\Web\Request) {
401 throw new \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException('throwStatus() only supports web requests.', 1220539739);
402 }
403 $this->response->setStatus($statusCode, $statusMessage);
404 if ($content === NULL) {
405 $content = $this->response->getStatus();
406 }
407 $this->response->setContent($content);
408 throw new \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException();
409 }
410
411 /**
412 * Collects the base validators which were defined for the data type of each
413 * controller argument and adds them to the argument's validator chain.
414 *
415 * @return void
416 */
417 public function initializeControllerArgumentsBaseValidators() {
418 foreach ($this->arguments as $argument) {
419 $validator = $this->validatorResolver->getBaseValidatorConjunction($argument->getDataType());
420 if ($validator !== NULL) {
421 $argument->setValidator($validator);
422 }
423 }
424 }
425
426 /**
427 * Maps arguments delivered by the request object to the local controller arguments.
428 *
429 * @throws Exception\RequiredArgumentMissingException
430 * @return void
431 */
432 protected function mapRequestArgumentsToControllerArguments() {
433 if ($this->configurationManager->isFeatureEnabled('rewrittenPropertyMapper')) {
434 foreach ($this->arguments as $argument) {
435 $argumentName = $argument->getName();
436 if ($this->request->hasArgument($argumentName)) {
437 $argument->setValue($this->request->getArgument($argumentName));
438 } elseif ($argument->isRequired()) {
439 throw new \TYPO3\CMS\Extbase\Mvc\Controller\Exception\RequiredArgumentMissingException('Required argument "' . $argumentName . '" is not set.', 1298012500);
440 }
441 }
442 } else {
443 // @deprecated since Extbase 1.4, will be removed two versions after Extbase 6.1
444 $optionalPropertyNames = array();
445 $allPropertyNames = $this->arguments->getArgumentNames();
446 foreach ($allPropertyNames as $propertyName) {
447 if ($this->arguments[$propertyName]->isRequired() === FALSE) {
448 $optionalPropertyNames[] = $propertyName;
449 }
450 }
451 /** @var $validator ArgumentsValidator */
452 $validator = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\ArgumentsValidator');
453 $this->deprecatedPropertyMapper->mapAndValidate($allPropertyNames, $this->request->getArguments(), $this->arguments, $optionalPropertyNames, $validator);
454 $this->argumentsMappingResults = $this->deprecatedPropertyMapper->getMappingResults();
455 }
456 }
457 }