1eebca400271b9f526e25399599598d6c1c7c841
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Mvc / Request.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Mvc;
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 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 use TYPO3\CMS\Core\Utility\ClassNamingUtility;
32
33 /**
34 * Represents a generic request.
35 *
36 * @api
37 */
38 class Request implements \TYPO3\CMS\Extbase\Mvc\RequestInterface {
39
40 const PATTERN_MATCH_FORMAT = '/^[a-z0-9]{1,5}$/';
41
42 /**
43 * Pattern after which the controller object name is built
44 *
45 * @var string
46 */
47 protected $controllerObjectNamePattern = 'Tx_@extension_@subpackage_Controller_@controllerController';
48
49 /**
50 * Pattern after which the namespaced controller object name is built
51 *
52 * @var string
53 */
54 protected $namespacedControllerObjectNamePattern = '@vendor\@extension\@subpackage\Controller\@controllerController';
55
56 /**
57 * @var string Key of the plugin which identifies the plugin. It must be a string containing [a-z0-9]
58 */
59 protected $pluginName = '';
60
61 /**
62 * @var string Name of the extension which is supposed to handle this request. This is the extension name converted to UpperCamelCase
63 */
64 protected $controllerExtensionName = NULL;
65
66 /**
67 * @var string vendor prefix
68 */
69 protected $controllerVendorName = NULL;
70
71 /**
72 * Subpackage key of the controller which is supposed to handle this request.
73 *
74 * @var string
75 */
76 protected $controllerSubpackageKey = NULL;
77
78 /**
79 * @var string Object name of the controller which is supposed to handle this request.
80 */
81 protected $controllerName = 'Standard';
82
83 /**
84 * @var string Name of the action the controller is supposed to take.
85 */
86 protected $controllerActionName = 'index';
87
88 /**
89 * @var array The arguments for this request
90 */
91 protected $arguments = array();
92
93 /**
94 * Framework-internal arguments for this request, such as __referrer.
95 * All framework-internal arguments start with double underscore (__),
96 * and are only used from within the framework. Not for user consumption.
97 * Internal Arguments can be objects, in contrast to public arguments
98 *
99 * @var array
100 */
101 protected $internalArguments = array();
102
103 /**
104 * @var string The requested representation format
105 */
106 protected $format = 'txt';
107
108 /**
109 * @var boolean If this request has been changed and needs to be dispatched again
110 */
111 protected $dispatched = FALSE;
112
113 /**
114 * If this request is a forward because of an error, the original request gets filled.
115 *
116 * @var \TYPO3\CMS\Extbase\Mvc\Request
117 */
118 protected $originalRequest = NULL;
119
120 /**
121 * If the request is a forward because of an error, these mapping results get filled here.
122 *
123 * @var \TYPO3\CMS\Extbase\Error\Result
124 */
125 protected $originalRequestMappingResults = NULL;
126
127 /**
128 * @var array Errors that occured during this request
129 * @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
130 */
131 protected $errors = array();
132
133 /**
134 * Sets the dispatched flag
135 *
136 * @param boolean $flag If this request has been dispatched
137 *
138 * @return void
139 * @api
140 */
141 public function setDispatched($flag) {
142 $this->dispatched = $flag ? TRUE : FALSE;
143 }
144
145 /**
146 * If this request has been dispatched and addressed by the responsible
147 * controller and the response is ready to be sent.
148 *
149 * The dispatcher will try to dispatch the request again if it has not been
150 * addressed yet.
151 *
152 * @return boolean TRUE if this request has been disptached sucessfully
153 * @api
154 */
155 public function isDispatched() {
156 return $this->dispatched;
157 }
158
159 /**
160 * Returns the object name of the controller defined by the extension name and
161 * controller name
162 *
163 * @return string The controller's Object Name
164 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchControllerException if the controller does not exist
165 * @api
166 */
167 public function getControllerObjectName() {
168 if (NULL !== $this->controllerVendorName) {
169 // It's safe to assume a namespaced name as namespaced names have to follow PSR-0
170 $lowercaseObjectName = str_replace('@extension', $this->controllerExtensionName, $this->namespacedControllerObjectNamePattern);
171 $lowercaseObjectName = str_replace('@subpackage', $this->controllerSubpackageKey, $lowercaseObjectName);
172 $lowercaseObjectName = str_replace('@controller', $this->controllerName, $lowercaseObjectName);
173 $lowercaseObjectName = str_replace('@vendor', $this->controllerVendorName, $lowercaseObjectName);
174 $lowercaseObjectName = str_replace('\\\\', '\\', $lowercaseObjectName);
175 } else {
176 $lowercaseObjectName = str_replace('@extension', $this->controllerExtensionName, $this->controllerObjectNamePattern);
177 $lowercaseObjectName = str_replace('@subpackage', $this->controllerSubpackageKey, $lowercaseObjectName);
178 $lowercaseObjectName = str_replace('@controller', $this->controllerName, $lowercaseObjectName);
179 $lowercaseObjectName = str_replace('__', '_', $lowercaseObjectName);
180 }
181 // TODO implement getCaseSensitiveObjectName()
182 $objectName = $lowercaseObjectName;
183 if ($objectName === FALSE) {
184 throw new \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchControllerException('The controller object "' . $lowercaseObjectName . '" does not exist.', 1220884009);
185 }
186 return $objectName;
187 }
188
189 /**
190 * Explicitly sets the object name of the controller
191 *
192 * @param string $controllerObjectName The fully qualified controller object name
193 *
194 * @return void
195 */
196 public function setControllerObjectName($controllerObjectName) {
197 $nameParts = ClassNamingUtility::explodeObjectControllerName($controllerObjectName);
198 $this->controllerVendorName = isset($nameParts['vendorName']) ? $nameParts['vendorName'] : NULL;
199 $this->controllerExtensionName = $nameParts['extensionName'];
200 $this->controllerSubpackageKey = isset($nameParts['subpackageKey']) ? $nameParts['subpackageKey'] : NULL;
201 $this->controllerName = $nameParts['controllerName'];
202 }
203
204 /**
205 * Sets the plugin name.
206 *
207 * @param string|NULL $pluginName
208 *
209 * @return void
210 */
211 public function setPluginName($pluginName = NULL) {
212 if ($pluginName !== NULL) {
213 $this->pluginName = $pluginName;
214 }
215 }
216
217 /**
218 * Returns the plugin key.
219 *
220 * @return string The plugin key
221 * @api
222 */
223 public function getPluginName() {
224 return $this->pluginName;
225 }
226
227 /**
228 * Sets the extension name of the controller.
229 *
230 * @param string $controllerExtensionName The extension name.
231 *
232 * @return void
233 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidExtensionNameException if the extension name is not valid
234 */
235 public function setControllerExtensionName($controllerExtensionName) {
236 if ($controllerExtensionName !== NULL) {
237 $this->controllerExtensionName = $controllerExtensionName;
238 }
239 }
240
241 /**
242 * Returns the extension name of the specified controller.
243 *
244 * @return string The extension name
245 * @api
246 */
247 public function getControllerExtensionName() {
248 return $this->controllerExtensionName;
249 }
250
251 /**
252 * Returns the extension name of the specified controller.
253 *
254 * @return string The extension key
255 * @api
256 */
257 public function getControllerExtensionKey() {
258 return \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($this->controllerExtensionName);
259 }
260
261 /**
262 * Sets the subpackage key of the controller.
263 *
264 * @param string $subpackageKey The subpackage key.
265 *
266 * @return void
267 */
268 public function setControllerSubpackageKey($subpackageKey) {
269 $this->controllerSubpackageKey = $subpackageKey;
270 }
271
272 /**
273 * Returns the subpackage key of the specified controller.
274 * If there is no subpackage key set, the method returns NULL
275 *
276 * @return string The subpackage key
277 */
278 public function getControllerSubpackageKey() {
279 return $this->controllerSubpackageKey;
280 }
281
282 /**
283 * Sets the name of the controller which is supposed to handle the request.
284 * Note: This is not the object name of the controller!
285 *
286 * @param string $controllerName Name of the controller
287 *
288 * @throws Exception\InvalidControllerNameException
289 * @return void
290 */
291 public function setControllerName($controllerName) {
292 if (!is_string($controllerName) && $controllerName !== NULL) {
293 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidControllerNameException('The controller name must be a valid string, ' . gettype($controllerName) . ' given.', 1187176358);
294 }
295 if (strpos($controllerName, '_') !== FALSE) {
296 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidControllerNameException('The controller name must not contain underscores.', 1217846412);
297 }
298 if ($controllerName !== NULL) {
299 $this->controllerName = $controllerName;
300 }
301 }
302
303 /**
304 * Returns the object name of the controller supposed to handle this request, if one
305 * was set already (if not, the name of the default controller is returned)
306 *
307 * @return string Object name of the controller
308 * @api
309 */
310 public function getControllerName() {
311 return $this->controllerName;
312 }
313
314 /**
315 * Sets the name of the action contained in this request.
316 *
317 * Note that the action name must start with a lower case letter and is case sensitive.
318 *
319 * @param string $actionName Name of the action to execute by the controller
320 *
321 * @return void
322 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidActionNameException if the action name is not valid
323 */
324 public function setControllerActionName($actionName) {
325 if (!is_string($actionName) && $actionName !== NULL) {
326 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidActionNameException('The action name must be a valid string, ' . gettype($actionName) . ' given (' . $actionName . ').', 1187176358);
327 }
328 if ($actionName[0] !== strtolower($actionName[0]) && $actionName !== NULL) {
329 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidActionNameException('The action name must start with a lower case letter, "' . $actionName . '" does not match this criteria.', 1218473352);
330 }
331 if ($actionName !== NULL) {
332 $this->controllerActionName = $actionName;
333 }
334 }
335
336 /**
337 * Returns the name of the action the controller is supposed to execute.
338 *
339 * @return string Action name
340 * @api
341 */
342 public function getControllerActionName() {
343 $controllerObjectName = $this->getControllerObjectName();
344 if ($controllerObjectName !== '' && $this->controllerActionName === strtolower($this->controllerActionName)) {
345 $actionMethodName = $this->controllerActionName . 'Action';
346 $classMethods = get_class_methods($controllerObjectName);
347 if (is_array($classMethods)) {
348 foreach ($classMethods as $existingMethodName) {
349 if (strtolower($existingMethodName) === strtolower($actionMethodName)) {
350 $this->controllerActionName = substr($existingMethodName, 0, -6);
351 break;
352 }
353 }
354 }
355 }
356 return $this->controllerActionName;
357 }
358
359 /**
360 * Sets the value of the specified argument
361 *
362 * @param string $argumentName Name of the argument to set
363 * @param mixed $value The new value
364 *
365 * @throws Exception\InvalidArgumentNameException
366 * @return void
367 */
368 public function setArgument($argumentName, $value) {
369 if (!is_string($argumentName) || strlen($argumentName) == 0) {
370 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentNameException('Invalid argument name.', 1210858767);
371 }
372 if ($argumentName[0] === '_' && $argumentName[1] === '_') {
373 $this->internalArguments[$argumentName] = $value;
374 return;
375 }
376 switch ($argumentName) {
377 case '@extension':
378 $this->setControllerExtensionName($value);
379 break;
380 case '@subpackage':
381 $this->setControllerSubpackageKey($value);
382 break;
383 case '@controller':
384 $this->setControllerName($value);
385 break;
386 case '@action':
387 $this->setControllerActionName($value);
388 break;
389 case '@format':
390 $this->setFormat($value);
391 break;
392 case '@vendor':
393 $this->setControllerVendorName($value);
394 break;
395 default:
396 $this->arguments[$argumentName] = $value;
397 }
398 }
399
400 /**
401 * sets the VendorName
402 *
403 * @param string $vendorName
404 *
405 * @return void
406 */
407 public function setControllerVendorName($vendorName) {
408 $this->controllerVendorName = $vendorName;
409 }
410
411 /**
412 * get the VendorName
413 *
414 * @return string
415 */
416 public function getControllerVendorName() {
417 return $this->controllerVendorName;
418 }
419
420 /**
421 * Sets the whole arguments array and therefore replaces any arguments
422 * which existed before.
423 *
424 * @param array $arguments An array of argument names and their values
425 *
426 * @return void
427 */
428 public function setArguments(array $arguments) {
429 $this->arguments = array();
430 foreach ($arguments as $argumentName => $argumentValue) {
431 $this->setArgument($argumentName, $argumentValue);
432 }
433 }
434
435 /**
436 * Returns an array of arguments and their values
437 *
438 * @return array Associative array of arguments and their values (which may be arguments and values as well)
439 * @api
440 */
441 public function getArguments() {
442 return $this->arguments;
443 }
444
445 /**
446 * Returns the value of the specified argument
447 *
448 * @param string $argumentName Name of the argument
449 *
450 * @return string Value of the argument
451 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException if such an argument does not exist
452 * @api
453 */
454 public function getArgument($argumentName) {
455 if (!isset($this->arguments[$argumentName])) {
456 throw new \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException('An argument "' . $argumentName . '" does not exist for this request.', 1176558158);
457 }
458 return $this->arguments[$argumentName];
459 }
460
461 /**
462 * Checks if an argument of the given name exists (is set)
463 *
464 * @param string $argumentName Name of the argument to check
465 *
466 * @return boolean TRUE if the argument is set, otherwise FALSE
467 * @api
468 */
469 public function hasArgument($argumentName) {
470 return isset($this->arguments[$argumentName]);
471 }
472
473 /**
474 * Sets the requested representation format
475 *
476 * @param string $format The desired format, something like "html", "xml", "png", "json" or the like. Can even be something like "rss.xml".
477 *
478 * @return void
479 */
480 public function setFormat($format) {
481 $this->format = $format;
482 }
483
484 /**
485 * Returns the requested representation format
486 *
487 * @return string The desired format, something like "html", "xml", "png", "json" or the like.
488 * @api
489 */
490 public function getFormat() {
491 return $this->format;
492 }
493
494 /**
495 * Set errors that occured during the request (e.g. argument mapping errors)
496 *
497 * @param array $errors An array of \TYPO3\CMS\Extbase\Error\Error objects
498 *
499 * @return void
500 * @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
501 */
502 public function setErrors(array $errors) {
503 $this->errors = $errors;
504 }
505
506 /**
507 * Get errors that occured during the request (e.g. argument mapping errors)
508 *
509 * @return array The errors that occured during the request
510 * @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
511 */
512 public function getErrors() {
513 return $this->errors;
514 }
515
516 /**
517 * Returns the original request. Filled only if a property mapping error occured.
518 *
519 * @return \TYPO3\CMS\Extbase\Mvc\Request the original request.
520 */
521 public function getOriginalRequest() {
522 return $this->originalRequest;
523 }
524
525 /**
526 * @param \TYPO3\CMS\Extbase\Mvc\Request $originalRequest
527 *
528 * @return void
529 */
530 public function setOriginalRequest(\TYPO3\CMS\Extbase\Mvc\Request $originalRequest) {
531 $this->originalRequest = $originalRequest;
532 }
533
534 /**
535 * Get the request mapping results for the original request.
536 *
537 * @return \TYPO3\CMS\Extbase\Error\Result
538 */
539 public function getOriginalRequestMappingResults() {
540 if ($this->originalRequestMappingResults === NULL) {
541 return new \TYPO3\CMS\Extbase\Error\Result();
542 }
543 return $this->originalRequestMappingResults;
544 }
545
546 /**
547 * @param \TYPO3\CMS\Extbase\Error\Result $originalRequestMappingResults
548 */
549 public function setOriginalRequestMappingResults(\TYPO3\CMS\Extbase\Error\Result $originalRequestMappingResults) {
550 $this->originalRequestMappingResults = $originalRequestMappingResults;
551 }
552
553 /**
554 * Get the internal arguments of the request, i.e. every argument starting
555 * with two underscores.
556 *
557 * @return array
558 */
559 public function getInternalArguments() {
560 return $this->internalArguments;
561 }
562
563 /**
564 * Returns the value of the specified argument
565 *
566 * @param string $argumentName Name of the argument
567 *
568 * @return string Value of the argument, or NULL if not set.
569 */
570 public function getInternalArgument($argumentName) {
571 if (!isset($this->internalArguments[$argumentName])) {
572 return NULL;
573 }
574 return $this->internalArguments[$argumentName];
575 }
576 }