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