5c11d89c1dfa18c13296b050ce9f4a6d4167081d
[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 */
35 abstract class Tx_Extbase_MVC_Controller_AbstractController implements Tx_Extbase_MVC_Controller_ControllerInterface {
36
37 /**
38 * @var Tx_Extbase_Object_ManagerInterface
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 * Constructs the controller.
108 */
109 public function __construct() {
110 $this->objectManager = t3lib_div::makeInstance('Tx_Extbase_Object_Manager');
111 $this->arguments = t3lib_div::makeInstance('Tx_Extbase_MVC_Controller_Arguments');
112 $this->arguments->injectPersistenceManager(Tx_Extbase_Dispatcher::getPersistenceManager());
113 $this->arguments->injectQueryFactory(t3lib_div::makeInstance('Tx_Extbase_Persistence_QueryFactory'));
114 list(, $this->extensionName) = explode('_', get_class($this));
115 }
116
117 /**
118 * Injects the property mapper
119 *
120 * @param Tx_Extbase_Property_Mapper $propertyMapper The property mapper
121 * @return void
122 */
123 public function injectPropertyMapper(Tx_Extbase_Property_Mapper $propertyMapper) {
124 $this->propertyMapper = $propertyMapper;
125 }
126
127 /**
128 * Injects the settings of the extension.
129 *
130 * @param array $settings Settings container of the current extension
131 * @return void
132 */
133 public function injectSettings(array $settings) {
134 $this->settings = $settings;
135 }
136
137 /**
138 * Injects the object manager
139 *
140 * @param Tx_Extbase_Object_ManagerInterface $objectManager
141 * @return void
142 */
143 public function injectObjectManager(Tx_Extbase_Object_ManagerInterface $objectManager) {
144 $this->objectManager = $objectManager;
145 }
146
147 /**
148 * Injects the validator resolver
149 *
150 * @param Tx_Extbase_Validation_ValidatorResolver $validatorResolver
151 * @return void
152 */
153 public function injectValidatorResolver(Tx_Extbase_Validation_ValidatorResolver $validatorResolver) {
154 $this->validatorResolver = $validatorResolver;
155 }
156
157 /**
158 * Checks if the current request type is supported by the controller.
159 *
160 * If your controller only supports certain request types, either
161 * replace / modify the supporteRequestTypes property or override this
162 * method.
163 *
164 * @param Tx_Extbase_MVC_Request $request The current request
165 * @return boolean TRUE if this request type is supported, otherwise FALSE
166 * @api
167 */
168 public function canProcessRequest(Tx_Extbase_MVC_Request $request) {
169 foreach ($this->supportedRequestTypes as $supportedRequestType) {
170 if ($request instanceof $supportedRequestType) return TRUE;
171 }
172 return FALSE;
173 }
174
175 /**
176 * Processes a general request. The result can be returned by altering the given response.
177 *
178 * @param Tx_Extbase_MVC_Request $request The request object
179 * @param Tx_Extbase_MVC_Response $response The response, modified by this handler
180 * @return void
181 * @throws Tx_Extbase_MVC_Exception_UnsupportedRequestType if the controller doesn't support the current request type
182 * @api
183 */
184 public function processRequest(Tx_Extbase_MVC_Request $request, Tx_Extbase_MVC_Response $response) {
185 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);
186
187 $this->request = $request;
188 $this->request->setDispatched(TRUE);
189 $this->response = $response;
190
191 $this->URIBuilder = t3lib_div::makeInstance('Tx_Extbase_MVC_Web_Routing_URIBuilder');
192 $this->URIBuilder->setRequest($request);
193
194 $this->initializeControllerArgumentsBaseValidators();
195 $this->mapRequestArgumentsToControllerArguments();
196 }
197
198 /**
199 * Initialize the controller context
200 *
201 * @return Tx_Extbase_MVC_Controller_ControllerContext ControllerContext to be passed to the view
202 * @api
203 */
204 protected function buildControllerContext() {
205 $controllerContext = t3lib_div::makeInstance('Tx_Extbase_MVC_Controller_ControllerContext');
206 $controllerContext->setRequest($this->request);
207 $controllerContext->setResponse($this->response);
208 if ($this->arguments !== NULL) {
209 $controllerContext->setArguments($this->arguments);
210 }
211 if ($this->argumentsMappingResults !== NULL) {
212 $controllerContext->setArgumentsMappingResults($this->argumentsMappingResults);
213 }
214 $controllerContext->setURIBuilder($this->URIBuilder);
215 return $controllerContext;
216 }
217
218 /**
219 * Forwards the request to another controller.
220 *
221 * @param string $actionName Name of the action to forward to
222 * @param string $controllerName Unqualified object name of the controller to forward to. If not specified, the current controller is used.
223 * @param string $extensionName Name of the extension containing the controller to forward to. If not specified, the current extension is assumed.
224 * @param Tx_Extbase_MVC_Controller_Arguments $arguments Arguments to pass to the target action
225 * @return void
226 * @throws Tx_Extbase_MVC_Exception_StopAction
227 * @api
228 */
229 public function forward($actionName, $controllerName = NULL, $extensionName = NULL, array $arguments = NULL) {
230 $this->request->setDispatched(FALSE);
231 $this->request->setControllerActionName($actionName);
232 if ($controllerName !== NULL) $this->request->setControllerName($controllerName);
233 if ($extensionName !== NULL) $this->request->setControllerExtensionName($extensionName);
234 if ($arguments !== NULL) $this->request->setArguments($arguments);
235 throw new Tx_Extbase_MVC_Exception_StopAction();
236 }
237
238 /**
239 * Forwards the request to another action and / or controller.
240 *
241 * NOTE: This method only supports web requests and will thrown an exception
242 * if used with other request types.
243 *
244 * @param string $actionName Name of the action to forward to
245 * @param string $controllerName Unqualified object name of the controller to forward to. If not specified, the current controller is used.
246 * @param string $extensionName Name of the extension containing the controller to forward to. If not specified, the current extension is assumed.
247 * @param Tx_Extbase_MVC_Controller_Arguments $arguments Arguments to pass to the target action
248 * @param integer $pageUid Target page uid. If NULL, the current page uid is used
249 * @param integer $delay (optional) The delay in seconds. Default is no delay.
250 * @param integer $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other"
251 * @return void
252 * @throws Tx_Extbase_MVC_Exception_UnsupportedRequestType If the request is not a web request
253 * @throws Tx_Extbase_MVC_Exception_StopAction
254 * @api
255 */
256 protected function redirect($actionName, $controllerName = NULL, $extensionName = NULL, array $arguments = NULL, $pageUid = NULL, $delay = 0, $statusCode = 303) {
257 if (!$this->request instanceof Tx_Extbase_MVC_Web_Request) throw new Tx_Extbase_MVC_Exception_UnsupportedRequestType('redirect() only supports web requests.', 1220539734);
258
259 if ($controllerName === NULL) {
260 $controllerName = $this->request->getControllerName();
261 }
262 if ($pageUid === NULL) {
263 $pageUid = $GLOBALS['TSFE']->id;
264 }
265
266 $uri = $this->URIBuilder->URIFor($pageUid, $actionName, $arguments, $controllerName, $extensionName);
267 $this->redirectToURI($uri, $delay, $statusCode);
268 }
269
270 /**
271 * Redirects the web request to another uri.
272 *
273 * NOTE: This method only supports web requests and will thrown an exception if used with other request types.
274 *
275 * @param mixed $uri A string representation of a URI
276 * @param integer $delay (optional) The delay in seconds. Default is no delay.
277 * @param integer $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other"
278 * @throws Tx_Extbase_MVC_Exception_UnsupportedRequestType If the request is not a web request
279 * @throws Tx_Extbase_MVC_Exception_StopAction
280 * @api
281 */
282 protected function redirectToURI($uri, $delay = 0, $statusCode = 303) {
283 if (!$this->request instanceof Tx_Extbase_MVC_Web_Request) throw new Tx_Extbase_MVC_Exception_UnsupportedRequestType('redirect() only supports web requests.', 1220539734);
284
285 $uri = $this->request->getBaseURI() . (string)$uri;
286 $escapedUri = htmlentities($uri, ENT_QUOTES, 'utf-8');
287 $this->response->setContent('<html><head><meta http-equiv="refresh" content="' . intval($delay) . ';url=' . $escapedUri . '"/></head></html>');
288 $this->response->setStatus($statusCode);
289 $this->response->setHeader('Location', (string)$uri);
290 throw new Tx_Extbase_MVC_Exception_StopAction();
291 }
292
293 /**
294 * Sends the specified HTTP status immediately.
295 *
296 * NOTE: This method only supports web requests and will thrown an exception if used with other request types.
297 *
298 * @param integer $statusCode The HTTP status code
299 * @param string $statusMessage A custom HTTP status message
300 * @param string $content Body content which further explains the status
301 * @throws Tx_Extbase_MVC_Exception_UnsupportedRequestType If the request is not a web request
302 * @throws Tx_Extbase_MVC_Exception_StopAction
303 * @api
304 */
305 public function throwStatus($statusCode, $statusMessage = NULL, $content = NULL) {
306 if (!$this->request instanceof Tx_Extbase_MVC_Web_Request) throw new Tx_Extbase_MVC_Exception_UnsupportedRequestType('throwStatus() only supports web requests.', 1220539739);
307
308 $this->response->setStatus($statusCode, $statusMessage);
309 if ($content === NULL) $content = $this->response->getStatus();
310 $this->response->setContent($content);
311 throw new Tx_Extbase_MVC_Exception_StopAction();
312 }
313
314 /**
315 * Collects the base validators which were defined for the data type of each
316 * controller argument and adds them to the argument's validator chain.
317 *
318 * @return void
319 */
320 public function initializeControllerArgumentsBaseValidators() {
321 foreach ($this->arguments as $argument) {
322 $validator = $this->validatorResolver->getBaseValidatorConjunction($argument->getDataType());
323 if ($validator !== NULL) $argument->setValidator($validator);
324 }
325 }
326
327 /**
328 * Maps arguments delivered by the request object to the local controller arguments.
329 *
330 * @return void
331 */
332 protected function mapRequestArgumentsToControllerArguments() {
333 $optionalPropertyNames = array();
334 $allPropertyNames = $this->arguments->getArgumentNames();
335 foreach ($allPropertyNames as $propertyName) {
336 if ($this->arguments[$propertyName]->isRequired() === FALSE) $optionalPropertyNames[] = $propertyName;
337 }
338
339 $validator = t3lib_div::makeInstance('Tx_Extbase_MVC_Controller_ArgumentsValidator');
340 $this->propertyMapper->mapAndValidate($allPropertyNames, $this->request->getArguments(), $this->arguments, $optionalPropertyNames, $validator);
341 $this->argumentsMappingResults = $this->propertyMapper->getMappingResults();
342 }
343 }
344 ?>