1499fdf4bcbc557777d8c42cad6204ca3bf75577
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / MVC / Controller / AbstractController.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
6 * All rights reserved
7 *
8 * This class is a backport of the corresponding class of FLOW3.
9 * All credits go to the v5 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
28 /**
29 * An abstract base class for Controllers
30 *
31 * @package Extbase
32 * @subpackage MVC\Controller
33 * @version $ID:$
34 * @api
35 */
36 abstract class Tx_Extbase_MVC_Controller_AbstractController implements Tx_Extbase_MVC_Controller_ControllerInterface {
37 /**
38 * @var Tx_Extbase_Object_ObjectManagerInterface
39 */
40 protected $objectManager;
41
42 /**
43 * @var Tx_Extbase_MVC_Web_Routing_UriBuilder
44 */
45 protected $uriBuilder;
46
47 /**
48 * @var string Key of the extension this controller belongs to
49 */
50 protected $extensionName;
51
52 /**
53 * Contains the settings of the current extension
54 *
55 * @var array
56 * @api
57 */
58 protected $settings;
59
60 /**
61 * The current request.
62 *
63 * @var Tx_Extbase_MVC_Request
64 * @api
65 */
66 protected $request;
67
68 /**
69 * The response which will be returned by this action controller
70 *
71 * @var Tx_Extbase_MVC_Response
72 * @api
73 */
74 protected $response;
75
76 /**
77 * @var Tx_Extbase_Property_Mapper
78 */
79 protected $propertyMapper;
80
81 /**
82 * @var Tx_Extbase_Validation_ValidatorResolver
83 */
84 protected $validatorResolver;
85
86 /**
87 * @var Tx_Extbase_MVC_Controller_Arguments Arguments passed to the controller
88 */
89 protected $arguments;
90
91 /**
92 * The results of the mapping of request arguments to controller arguments
93 * @var Tx_Extbase_Property_MappingResults
94 * @api
95 */
96 protected $argumentsMappingResults;
97
98 /**
99 * An array of supported request types. By default only web requests are supported.
100 * Modify or replace this array if your specific controller supports certain
101 * (additional) request types.
102 * @var array
103 */
104 protected $supportedRequestTypes = array('Tx_Extbase_MVC_Request');
105
106 /**
107 * @var Tx_Extbase_MVC_Controller_ControllerContext
108 * @api
109 */
110 protected $controllerContext;
111
112 /**
113 * @var Tx_Extbase_MVC_Controller_FlashMessages
114 * @deprecated since Extbase 1.1; will be removed in Extbase 1.6
115 */
116 protected $flashMessages;
117
118 /**
119 * The flash messages. Use $this->flashMessageContainer->add(...) to add a new Flash message.
120 *
121 * @var Tx_Extbase_MVC_Controller_FlashMessages
122 * @api
123 */
124 protected $flashMessageContainer;
125
126 /**
127 * @var Tx_Extbase_Configuration_ConfigurationManager
128 */
129 protected $configurationManager;
130
131 /**
132 * Constructs the controller.
133 */
134 public function __construct() {
135 list(, $this->extensionName) = explode('_', get_class($this));
136 }
137
138 /**
139 * @param Tx_Extbase_Configuration_ConfigurationManager $configurationManager
140 * @return void
141 */
142 public function injectConfigurationManager(Tx_Extbase_Configuration_ConfigurationManager $configurationManager) {
143 $this->configurationManager = $configurationManager;
144 $this->settings = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS);
145 }
146
147 /**
148 * Injects the property mapper
149 *
150 * @param Tx_Extbase_Property_Mapper $propertyMapper The property mapper
151 * @return void
152 */
153 public function injectPropertyMapper(Tx_Extbase_Property_Mapper $propertyMapper) {
154 $this->propertyMapper = $propertyMapper;
155 }
156
157 /**
158 * Injects the object manager
159 *
160 * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager
161 * @return void
162 */
163 public function injectObjectManager(Tx_Extbase_Object_ObjectManagerInterface $objectManager) {
164 $this->objectManager = $objectManager;
165 $this->arguments = $this->objectManager->create('Tx_Extbase_MVC_Controller_Arguments');
166 }
167
168 /**
169 * Injects the validator resolver
170 *
171 * @param Tx_Extbase_Validation_ValidatorResolver $validatorResolver
172 * @return void
173 */
174 public function injectValidatorResolver(Tx_Extbase_Validation_ValidatorResolver $validatorResolver) {
175 $this->validatorResolver = $validatorResolver;
176 }
177
178 /**
179 * Injects the flash messages container
180 *
181 * @param Tx_Extbase_MVC_Controller_FlashMessages $flashMessageContainer
182 * @return void
183 */
184 public function injectFlashMessageContainer(Tx_Extbase_MVC_Controller_FlashMessages $flashMessageContainer) {
185 $this->flashMessageContainer = $flashMessageContainer;
186 // @deprecated since Extbase 1.1; will be removed in Extbase 1.6
187 $this->flashMessages = $flashMessageContainer;
188 }
189
190 /**
191 * Checks if the current request type is supported by the controller.
192 *
193 * If your controller only supports certain request types, either
194 * replace / modify the supporteRequestTypes property or override this
195 * method.
196 *
197 * @param Tx_Extbase_MVC_Request $request The current request
198 * @return boolean TRUE if this request type is supported, otherwise FALSE
199 * @api
200 */
201 public function canProcessRequest(Tx_Extbase_MVC_RequestInterface $request) {
202 foreach ($this->supportedRequestTypes as $supportedRequestType) {
203 if ($request instanceof $supportedRequestType) return TRUE;
204 }
205 return FALSE;
206 }
207
208 /**
209 * Processes a general request. The result can be returned by altering the given response.
210 *
211 * @param Tx_Extbase_MVC_Request $request The request object
212 * @param Tx_Extbase_MVC_Response $response The response, modified by this handler
213 * @return void
214 * @throws Tx_Extbase_MVC_Exception_UnsupportedRequestType if the controller doesn't support the current request type
215 * @api
216 */
217 public function processRequest(Tx_Extbase_MVC_RequestInterface $request, Tx_Extbase_MVC_ResponseInterface $response) {
218 if (!$this->canProcessRequest($request)) throw new Tx_Extbase_MVC_Exception_UnsupportedRequestType(get_class($this) . ' does not support requests of type "' . get_class($request) . '". Supported types are: ' . implode(' ', $this->supportedRequestTypes) , 1187701131);
219
220 $this->request = $request;
221 $this->request->setDispatched(TRUE);
222 $this->response = $response;
223
224 $this->uriBuilder = $this->objectManager->create('Tx_Extbase_MVC_Web_Routing_UriBuilder');
225 $this->uriBuilder->setRequest($request);
226
227 $this->initializeControllerArgumentsBaseValidators();
228 $this->mapRequestArgumentsToControllerArguments();
229 $this->controllerContext = $this->buildControllerContext();
230 }
231
232 /**
233 * Initialize the controller context
234 *
235 * @return Tx_Extbase_MVC_Controller_ControllerContext ControllerContext to be passed to the view
236 * @api
237 */
238 protected function buildControllerContext() {
239 $controllerContext = $this->objectManager->create('Tx_Extbase_MVC_Controller_ControllerContext');
240 $controllerContext->setRequest($this->request);
241 $controllerContext->setResponse($this->response);
242 if ($this->arguments !== NULL) {
243 $controllerContext->setArguments($this->arguments);
244 }
245 if ($this->argumentsMappingResults !== NULL) {
246 $controllerContext->setArgumentsMappingResults($this->argumentsMappingResults);
247 }
248 $controllerContext->setUriBuilder($this->uriBuilder);
249 $controllerContext->setFlashMessageContainer($this->flashMessageContainer);
250 return $controllerContext;
251 }
252
253 /**
254 * Forwards the request to another controller.
255 *
256 * @param string $actionName Name of the action to forward to
257 * @param string $controllerName Unqualified object name of the controller to forward to. If not specified, the current controller is used.
258 * @param string $extensionName Name of the extension containing the controller to forward to. If not specified, the current extension is assumed.
259 * @param Tx_Extbase_MVC_Controller_Arguments $arguments Arguments to pass to the target action
260 * @return void
261 * @throws Tx_Extbase_MVC_Exception_StopAction
262 * @api
263 */
264 public function forward($actionName, $controllerName = NULL, $extensionName = NULL, array $arguments = NULL) {
265 $this->request->setDispatched(FALSE);
266 $this->request->setControllerActionName($actionName);
267 if ($controllerName !== NULL) $this->request->setControllerName($controllerName);
268 if ($extensionName !== NULL) $this->request->setControllerExtensionName($extensionName);
269 if ($arguments !== NULL) $this->request->setArguments($arguments);
270 throw new Tx_Extbase_MVC_Exception_StopAction();
271 }
272
273 /**
274 * Forwards the request to another action and / or controller.
275 *
276 * NOTE: This method only supports web requests and will thrown an exception
277 * if used with other request types.
278 *
279 * @param string $actionName Name of the action to forward to
280 * @param string $controllerName Unqualified object name of the controller to forward to. If not specified, the current controller is used.
281 * @param string $extensionName Name of the extension containing the controller to forward to. If not specified, the current extension is assumed.
282 * @param Tx_Extbase_MVC_Controller_Arguments $arguments Arguments to pass to the target action
283 * @param integer $pageUid Target page uid. If NULL, the current page uid is used
284 * @param integer $delay (optional) The delay in seconds. Default is no delay.
285 * @param integer $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other"
286 * @return void
287 * @throws Tx_Extbase_MVC_Exception_UnsupportedRequestType If the request is not a web request
288 * @throws Tx_Extbase_MVC_Exception_StopAction
289 * @api
290 */
291 protected function redirect($actionName, $controllerName = NULL, $extensionName = NULL, array $arguments = NULL, $pageUid = NULL, $delay = 0, $statusCode = 303) {
292 if (!$this->request instanceof Tx_Extbase_MVC_Web_Request) throw new Tx_Extbase_MVC_Exception_UnsupportedRequestType('redirect() only supports web requests.', 1220539734);
293
294 if ($controllerName === NULL) {
295 $controllerName = $this->request->getControllerName();
296 }
297
298 $uri = $this->uriBuilder
299 ->reset()
300 ->setTargetPageUid($pageUid)
301 ->uriFor($actionName, $arguments, $controllerName, $extensionName);
302 $this->redirectToURI($uri, $delay, $statusCode);
303 }
304
305 /**
306 * Redirects the web request to another uri.
307 *
308 * NOTE: This method only supports web requests and will thrown an exception if used with other request types.
309 *
310 * @param mixed $uri A string representation of a URI
311 * @param integer $delay (optional) The delay in seconds. Default is no delay.
312 * @param integer $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other"
313 * @throws Tx_Extbase_MVC_Exception_UnsupportedRequestType If the request is not a web request
314 * @throws Tx_Extbase_MVC_Exception_StopAction
315 * @api
316 */
317 protected function redirectToURI($uri, $delay = 0, $statusCode = 303) {
318 if (!$this->request instanceof Tx_Extbase_MVC_Web_Request) throw new Tx_Extbase_MVC_Exception_UnsupportedRequestType('redirect() only supports web requests.', 1220539734);
319
320 $uri = $this->addBaseUriIfNecessary($uri);
321 $escapedUri = htmlentities($uri, ENT_QUOTES, 'utf-8');
322 $this->response->setContent('<html><head><meta http-equiv="refresh" content="' . intval($delay) . ';url=' . $escapedUri . '"/></head></html>');
323 $this->response->setStatus($statusCode);
324 $this->response->setHeader('Location', (string)$uri);
325 throw new Tx_Extbase_MVC_Exception_StopAction();
326 }
327
328 /**
329 * Adds the base uri if not already in place.
330 *
331 * @param string $uri The URI
332 * @return void
333 */
334 protected function addBaseUriIfNecessary($uri) {
335 $baseUri = $this->request->getBaseURI();
336 if(stripos($uri, $baseUri) !== 0) {
337 $uri = $baseUri . (string)$uri;
338 }
339 return $uri;
340 }
341
342 /**
343 * Sends the specified HTTP status immediately.
344 *
345 * NOTE: This method only supports web requests and will thrown an exception if used with other request types.
346 *
347 * @param integer $statusCode The HTTP status code
348 * @param string $statusMessage A custom HTTP status message
349 * @param string $content Body content which further explains the status
350 * @throws Tx_Extbase_MVC_Exception_UnsupportedRequestType If the request is not a web request
351 * @throws Tx_Extbase_MVC_Exception_StopAction
352 * @api
353 */
354 public function throwStatus($statusCode, $statusMessage = NULL, $content = NULL) {
355 if (!$this->request instanceof Tx_Extbase_MVC_Web_Request) throw new Tx_Extbase_MVC_Exception_UnsupportedRequestType('throwStatus() only supports web requests.', 1220539739);
356
357 $this->response->setStatus($statusCode, $statusMessage);
358 if ($content === NULL) $content = $this->response->getStatus();
359 $this->response->setContent($content);
360 throw new Tx_Extbase_MVC_Exception_StopAction();
361 }
362
363 /**
364 * Collects the base validators which were defined for the data type of each
365 * controller argument and adds them to the argument's validator chain.
366 *
367 * @return void
368 */
369 public function initializeControllerArgumentsBaseValidators() {
370 foreach ($this->arguments as $argument) {
371 $validator = $this->validatorResolver->getBaseValidatorConjunction($argument->getDataType());
372 if ($validator !== NULL) $argument->setValidator($validator);
373 }
374 }
375
376 /**
377 * Maps arguments delivered by the request object to the local controller arguments.
378 *
379 * @return void
380 */
381 protected function mapRequestArgumentsToControllerArguments() {
382 $optionalPropertyNames = array();
383 $allPropertyNames = $this->arguments->getArgumentNames();
384 foreach ($allPropertyNames as $propertyName) {
385 if ($this->arguments[$propertyName]->isRequired() === FALSE) $optionalPropertyNames[] = $propertyName;
386 }
387
388 $validator = $this->objectManager->create('Tx_Extbase_MVC_Controller_ArgumentsValidator');
389 $this->propertyMapper->mapAndValidate($allPropertyNames, $this->request->getArguments(), $this->arguments, $optionalPropertyNames, $validator);
390
391 $this->argumentsMappingResults = $this->propertyMapper->getMappingResults();
392 }
393 }
394 ?>