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