[!!!] Extbase: Reintegrating branch "dispatcher" to trunk. Resolves: #10605
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / MVC / Request.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 * Represents a generic request.
30 *
31 * @package Extbase
32 * @subpackage MVC
33 * @version $ID:$
34 * @scope prototype
35 * @api
36 */
37 class Tx_Extbase_MVC_Request implements Tx_Extbase_MVC_RequestInterface {
38
39 const PATTERN_MATCH_FORMAT = '/^[a-z0-9]{1,5}$/';
40
41 /**
42 * Pattern after which the controller object name is built
43 *
44 * @var string
45 */
46 protected $controllerObjectNamePattern = 'Tx_@extension_@subpackage_Controller_@controllerController';
47
48 /**
49 * @var string Key of the plugin which identifies the plugin. It must be a string containing [a-z0-9]
50 */
51 protected $pluginName = '';
52
53 /**
54 * @var string Name of the extension which is supposed to handle this request. This is the extension name converted to UpperCamelCase
55 */
56 protected $controllerExtensionName = NULL;
57
58 /**
59 * Subpackage key of the controller which is supposed to handle this request.
60 *
61 * @var string
62 */
63 protected $controllerSubpackageKey = NULL;
64
65 /**
66 * @var string Object name of the controller which is supposed to handle this request.
67 */
68 protected $controllerName = 'Standard';
69
70 /**
71 * @var string Name of the action the controller is supposed to take.
72 */
73 protected $controllerActionName = 'index';
74
75 /**
76 * @var array The arguments for this request
77 */
78 protected $arguments = array();
79
80 /**
81 * @var string The requested representation format
82 */
83 protected $format = 'txt';
84
85 /**
86 * @var boolean If this request has been changed and needs to be dispatched again
87 */
88 protected $dispatched = FALSE;
89
90 /**
91 * @var array Errors that occured during this request
92 */
93 protected $errors = array();
94
95 /**
96 * Sets the dispatched flag
97 *
98 * @param boolean $flag If this request has been dispatched
99 * @return void
100 * @api
101 */
102 public function setDispatched($flag) {
103 $this->dispatched = $flag ? TRUE : FALSE;
104 }
105
106 /**
107 * If this request has been dispatched and addressed by the responsible
108 * controller and the response is ready to be sent.
109 *
110 * The dispatcher will try to dispatch the request again if it has not been
111 * addressed yet.
112 *
113 * @return boolean TRUE if this request has been disptached sucessfully
114 * @api
115 */
116 public function isDispatched() {
117 return $this->dispatched;
118 }
119
120 /**
121 * Returns the object name of the controller defined by the extension name and
122 * controller name
123 *
124 * @return string The controller's Object Name
125 * @throws Tx_Extbase_MVC_Exception_NoSuchController if the controller does not exist
126 * @api
127 */
128 public function getControllerObjectName() {
129 $lowercaseObjectName = str_replace('@extension', $this->controllerExtensionName, $this->controllerObjectNamePattern);
130 $lowercaseObjectName = str_replace('@subpackage', $this->controllerSubpackageKey, $lowercaseObjectName);
131 $lowercaseObjectName = str_replace('@controller', $this->controllerName, $lowercaseObjectName);
132 $lowercaseObjectName = str_replace('__', '_', $lowercaseObjectName);
133 // TODO implement getCaseSensitiveObjectName()
134 $objectName = $lowercaseObjectName;
135 if ($objectName === FALSE) throw new Tx_Extbase_MVC_Exception_NoSuchController('The controller object "' . $lowercaseObjectName . '" does not exist.', 1220884009);
136
137 return $objectName;
138 }
139
140 /**
141 * Explicitly sets the object name of the controller
142 *
143 * @param string $controllerObjectName The fully qualified controller object name
144 * @return void
145 */
146 public function setControllerObjectName($controllerObjectName) {
147 $matches = array();
148 preg_match('/
149 ^Tx
150 _(?P<extensionName>[^_]+)
151 _
152 (
153 Controller
154 |
155 (?P<subpackageKey>.+)_Controller
156 )
157 _(?P<controllerName>[a-z_]+)Controller
158 $/ix', $controllerObjectName, $matches
159 );
160
161 $this->controllerExtensionName = $matches['extensionName'];
162 $this->controllerSubpackageKey = (isset($matches['subpackageKey'])) ? $matches['subpackageKey'] : NULL;
163 $this->controllerName = $matches['controllerName'];
164 }
165
166 /**
167 * Sets the plugin name.
168 *
169 * @param string $extensionName The plugin name.
170 * @return void
171 */
172 public function setPluginName($pluginName = NULL) {
173 if ($pluginName !== NULL) {
174 $this->pluginName = $pluginName;
175 }
176 }
177
178 /**
179 * Returns the plugin key.
180 *
181 * @return string The plugin key
182 * @api
183 */
184 public function getPluginName() {
185 return $this->pluginName;
186 }
187
188 /**
189 * Sets the extension name of the controller.
190 *
191 * @param string $controllerExtensionName The extension name.
192 * @return void
193 * @throws Tx_Extbase_MVC_Exception_InvalidExtensionName if the extension name is not valid
194 */
195 public function setControllerExtensionName($controllerExtensionName) {
196 if ($controllerExtensionName !== NULL) {
197 $this->controllerExtensionName = $controllerExtensionName;
198 }
199 }
200
201 /**
202 * Returns the extension name of the specified controller.
203 *
204 * @return string The extension name
205 * @api
206 */
207 public function getControllerExtensionName() {
208 return $this->controllerExtensionName;
209 }
210
211 /**
212 * Returns the extension name of the specified controller.
213 *
214 * @return string The extension key
215 * @api
216 */
217 public function getControllerExtensionKey() {
218 return Tx_Extbase_Utility_Extension::convertCamelCaseToLowerCaseUnderscored($this->controllerExtensionName);
219 }
220
221 /**
222 * Sets the subpackage key of the controller.
223 *
224 * @param string $subpackageKey The subpackage key.
225 * @return void
226 */
227 public function setControllerSubpackageKey($subpackageKey) {
228 $this->controllerSubpackageKey = $subpackageKey;
229 }
230
231 /**
232 * Returns the subpackage key of the specified controller.
233 * If there is no subpackage key set, the method returns NULL
234 *
235 * @return string The subpackage key
236 */
237 public function getControllerSubpackageKey() {
238 return $this->controllerSubpackageKey;
239 }
240
241 /**
242 * Sets the name of the controller which is supposed to handle the request.
243 * Note: This is not the object name of the controller!
244 *
245 * @param string $controllerName Name of the controller
246 * @return void
247 */
248 public function setControllerName($controllerName) {
249 if (!is_string($controllerName) && $controllerName !== NULL) throw new Tx_Extbase_MVC_Exception_InvalidControllerName('The controller name must be a valid string, ' . gettype($controllerName) . ' given.', 1187176358);
250 if (strpos($controllerName, '_') !== FALSE) throw new Tx_Extbase_MVC_Exception_InvalidControllerName('The controller name must not contain underscores.', 1217846412);
251 if ($controllerName !== NULL) {
252 $this->controllerName = $controllerName;
253 }
254 }
255
256 /**
257 * Returns the object name of the controller supposed to handle this request, if one
258 * was set already (if not, the name of the default controller is returned)
259 *
260 * @return string Object name of the controller
261 * @api
262 */
263 public function getControllerName() {
264 return $this->controllerName;
265 }
266
267 /**
268 * Sets the name of the action contained in this request.
269 *
270 * Note that the action name must start with a lower case letter and is case sensitive.
271 *
272 * @param string $actionName: Name of the action to execute by the controller
273 * @return void
274 * @throws Tx_Extbase_MVC_Exception_InvalidActionName if the action name is not valid
275 */
276 public function setControllerActionName($actionName) {
277 if (!is_string($actionName) && $actionName !== NULL) throw new Tx_Extbase_MVC_Exception_InvalidActionName('The action name must be a valid string, ' . gettype($actionName) . ' given (' . $actionName . ').', 1187176358);
278 if (($actionName{0} !== strtolower($actionName{0})) && $actionName !== NULL) throw new Tx_Extbase_MVC_Exception_InvalidActionName('The action name must start with a lower case letter, "' . $actionName . '" does not match this criteria.', 1218473352);
279 if ($actionName !== NULL) {
280 $this->controllerActionName = $actionName;
281 }
282 }
283
284 /**
285 * Returns the name of the action the controller is supposed to execute.
286 *
287 * @return string Action name
288 * @api
289 */
290 public function getControllerActionName() {
291 $controllerObjectName = $this->getControllerObjectName();
292 if ($controllerObjectName !== '' && ($this->controllerActionName === strtolower($this->controllerActionName))) {
293 $actionMethodName = $this->controllerActionName . 'Action';
294 foreach (get_class_methods($controllerObjectName) as $existingMethodName) {
295 if (strtolower($existingMethodName) === strtolower($actionMethodName)) {
296 $this->controllerActionName = substr($existingMethodName, 0, -6);
297 break;
298 }
299 }
300 }
301 return $this->controllerActionName;
302 }
303
304 /**
305 * Sets the value of the specified argument
306 *
307 * @param string $argumentName Name of the argument to set
308 * @param mixed $value The new value
309 * @return void
310 */
311 public function setArgument($argumentName, $value) {
312 if (!is_string($argumentName) || strlen($argumentName) == 0) throw new Tx_Extbase_MVC_Exception_InvalidArgumentName('Invalid argument name.', 1210858767);
313 $this->arguments[$argumentName] = $value;
314 }
315
316 /**
317 * Sets the whole arguments array and therefore replaces any arguments
318 * which existed before.
319 *
320 * @param array $arguments An array of argument names and their values
321 * @return void
322 */
323 public function setArguments(array $arguments) {
324 $this->arguments = $arguments;
325 }
326
327 /**
328 * Returns an array of arguments and their values
329 *
330 * @return array Associative array of arguments and their values (which may be arguments and values as well)
331 * @api
332 */
333 public function getArguments() {
334 return $this->arguments;
335 }
336
337 /**
338 * Returns the value of the specified argument
339 *
340 * @param string $argumentName Name of the argument
341 * @return string Value of the argument
342 * @throws Tx_Extbase_MVC_Exception_NoSuchArgument if such an argument does not exist
343 * @api
344 */
345 public function getArgument($argumentName) {
346 if (!isset($this->arguments[$argumentName])) throw new Tx_Extbase_MVC_Exception_NoSuchArgument('An argument "' . $argumentName . '" does not exist for this request.', 1176558158);
347 return $this->arguments[$argumentName];
348 }
349
350 /**
351 * Checks if an argument of the given name exists (is set)
352 *
353 * @param string $argumentName Name of the argument to check
354 * @return boolean TRUE if the argument is set, otherwise FALSE
355 * @api
356 */
357 public function hasArgument($argumentName) {
358 return isset($this->arguments[$argumentName]);
359 }
360
361 /**
362 * Sets the requested representation format
363 *
364 * @param string $format The desired format, something like "html", "xml", "png", "json" or the like. Can even be something like "rss.xml".
365 * @return void
366 * @author Robert Lemke <robert@typo3.org>
367 */
368 public function setFormat($format) {
369 $this->format = $format;
370 }
371
372 /**
373 * Returns the requested representation format
374 *
375 * @return string The desired format, something like "html", "xml", "png", "json" or the like.
376 * @author Robert Lemke <robert@typo3.org>
377 * @api
378 */
379 public function getFormat() {
380 return $this->format;
381 }
382
383 /**
384 * Set errors that occured during the request (e.g. argument mapping errors)
385 *
386 * @param array $errors An array of Tx_Extbase_Error_Error objects
387 * @return void
388 */
389 public function setErrors(array $errors) {
390 $this->errors = $errors;
391 }
392
393 /**
394 * Get errors that occured during the request (e.g. argument mapping errors)
395 *
396 * @return array The errors that occured during the request
397 */
398 public function getErrors() {
399 return $this->errors;
400 }
401
402 }