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