[TASK] Use FQCN's when registering plugins/modules
[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 * @var string Key of the plugin which identifies the plugin. It must be a string containing [a-z0-9]
28 */
29 protected $pluginName = '';
30
31 /**
32 * @var string Name of the extension which is supposed to handle this request. This is the extension name converted to UpperCamelCase
33 */
34 protected $controllerExtensionName;
35
36 /**
37 * @var string vendor prefix
38 */
39 protected $controllerVendorName;
40
41 /**
42 * Subpackage key of the controller which is supposed to handle this request.
43 *
44 * @var string
45 */
46 protected $controllerSubpackageKey;
47
48 /**
49 * @var string
50 */
51 protected $controllerObjectName;
52
53 /**
54 * @var string Object name of the controller which is supposed to handle this request.
55 */
56 protected $controllerName = 'Standard';
57
58 /**
59 * @var string Name of the action the controller is supposed to take.
60 */
61 protected $controllerActionName = 'index';
62
63 /**
64 * @var array The arguments for this request
65 */
66 protected $arguments = [];
67
68 /**
69 * Framework-internal arguments for this request, such as __referrer.
70 * All framework-internal arguments start with double underscore (__),
71 * and are only used from within the framework. Not for user consumption.
72 * Internal Arguments can be objects, in contrast to public arguments
73 *
74 * @var array
75 */
76 protected $internalArguments = [];
77
78 /**
79 * @var string The requested representation format
80 */
81 protected $format = 'txt';
82
83 /**
84 * @var bool If this request has been changed and needs to be dispatched again
85 */
86 protected $dispatched = false;
87
88 /**
89 * If this request is a forward because of an error, the original request gets filled.
90 *
91 * @var \TYPO3\CMS\Extbase\Mvc\Request
92 */
93 protected $originalRequest;
94
95 /**
96 * If the request is a forward because of an error, these mapping results get filled here.
97 *
98 * @var \TYPO3\CMS\Extbase\Error\Result
99 */
100 protected $originalRequestMappingResults;
101
102 /**
103 * Sets the dispatched flag
104 *
105 * @param bool $flag If this request has been dispatched
106 */
107 public function setDispatched($flag)
108 {
109 $this->dispatched = (bool)$flag;
110 }
111
112 /**
113 * If this request has been dispatched and addressed by the responsible
114 * controller and the response is ready to be sent.
115 *
116 * The dispatcher will try to dispatch the request again if it has not been
117 * addressed yet.
118 *
119 * @return bool TRUE if this request has been disptached successfully
120 */
121 public function isDispatched()
122 {
123 return $this->dispatched;
124 }
125
126 /**
127 * @param string $controllerClassName
128 */
129 public function __construct(string $controllerClassName = '')
130 {
131 $this->controllerObjectName = $controllerClassName;
132 }
133
134 /**
135 * @return string
136 */
137 public function getControllerObjectName(): string
138 {
139 return $this->controllerObjectName;
140 }
141
142 /**
143 * Explicitly sets the object name of the controller
144 *
145 * @param string $controllerObjectName The fully qualified controller object name
146 * @internal only to be used within Extbase, not part of TYPO3 Core API.
147 */
148 public function setControllerObjectName($controllerObjectName)
149 {
150 $nameParts = ClassNamingUtility::explodeObjectControllerName($controllerObjectName);
151 $this->controllerVendorName = $nameParts['vendorName'] ?? null;
152 $this->controllerExtensionName = $nameParts['extensionName'];
153 $this->controllerSubpackageKey = $nameParts['subpackageKey'] ?? null;
154 $this->controllerName = $nameParts['controllerName'];
155 }
156
157 /**
158 * Sets the plugin name.
159 *
160 * @param string|null $pluginName
161 * @internal only to be used within Extbase, not part of TYPO3 Core API.
162 */
163 public function setPluginName($pluginName = null)
164 {
165 if ($pluginName !== null) {
166 $this->pluginName = $pluginName;
167 }
168 }
169
170 /**
171 * Returns the plugin key.
172 *
173 * @return string The plugin key
174 */
175 public function getPluginName()
176 {
177 return $this->pluginName;
178 }
179
180 /**
181 * Sets the extension name of the controller.
182 *
183 * @param string $controllerExtensionName The extension name.
184 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidExtensionNameException if the extension name is not valid
185 * @internal only to be used within Extbase, not part of TYPO3 Core API.
186 */
187 public function setControllerExtensionName($controllerExtensionName)
188 {
189 if ($controllerExtensionName !== null) {
190 $this->controllerExtensionName = $controllerExtensionName;
191 }
192 }
193
194 /**
195 * Returns the extension name of the specified controller.
196 *
197 * @return string The extension name
198 */
199 public function getControllerExtensionName()
200 {
201 return $this->controllerExtensionName;
202 }
203
204 /**
205 * Returns the extension name of the specified controller.
206 *
207 * @return string The extension key
208 */
209 public function getControllerExtensionKey()
210 {
211 return \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($this->controllerExtensionName);
212 }
213
214 /**
215 * Sets the subpackage key of the controller.
216 *
217 * @param string $subpackageKey The subpackage key.
218 * @internal only to be used within Extbase, not part of TYPO3 Core API.
219 */
220 public function setControllerSubpackageKey($subpackageKey)
221 {
222 $this->controllerSubpackageKey = $subpackageKey;
223 }
224
225 /**
226 * Returns the subpackage key of the specified controller.
227 * If there is no subpackage key set, the method returns NULL
228 *
229 * @return string The subpackage key
230 * @internal only to be used within Extbase, not part of TYPO3 Core API.
231 */
232 public function getControllerSubpackageKey()
233 {
234 return $this->controllerSubpackageKey;
235 }
236
237 /**
238 * @var array
239 */
240 protected $controllerAliasToClassNameMapping = [];
241
242 /**
243 * @param array $controllerAliasToClassNameMapping
244 */
245 public function setControllerAliasToClassNameMapping(array $controllerAliasToClassNameMapping)
246 {
247 // this is only needed as long as forwarded requests are altered and unless there
248 // is no new request object created by the request builder.
249 $this->controllerAliasToClassNameMapping = $controllerAliasToClassNameMapping;
250 }
251
252 /**
253 * Sets the name of the controller which is supposed to handle the request.
254 * Note: This is not the object name of the controller!
255 *
256 * @param string $controllerName Name of the controller
257 * @throws Exception\InvalidControllerNameException
258 * @internal only to be used within Extbase, not part of TYPO3 Core API.
259 */
260 public function setControllerName($controllerName)
261 {
262 if (!is_string($controllerName) && $controllerName !== null) {
263 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidControllerNameException('The controller name must be a valid string, ' . gettype($controllerName) . ' given.', 1187176358);
264 }
265 if ($controllerName !== null) {
266 $this->controllerName = $controllerName;
267 $this->controllerObjectName = $this->controllerAliasToClassNameMapping[$controllerName] ?? '';
268 // There might be no Controller Class, for example for Fluid Templates.
269 }
270 }
271
272 /**
273 * Returns the object name of the controller supposed to handle this request, if one
274 * was set already (if not, the name of the default controller is returned)
275 *
276 * @return string Object name of the controller
277 */
278 public function getControllerName()
279 {
280 return $this->controllerName;
281 }
282
283 /**
284 * Sets the name of the action contained in this request.
285 *
286 * Note that the action name must start with a lower case letter and is case sensitive.
287 *
288 * @param string $actionName Name of the action to execute by the controller
289 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidActionNameException if the action name is not valid
290 * @internal only to be used within Extbase, not part of TYPO3 Core API.
291 */
292 public function setControllerActionName($actionName)
293 {
294 if (!is_string($actionName) && $actionName !== null) {
295 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidActionNameException('The action name must be a valid string, ' . gettype($actionName) . ' given (' . $actionName . ').', 1187176359);
296 }
297 if ($actionName[0] !== strtolower($actionName[0]) && $actionName !== null) {
298 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);
299 }
300 if ($actionName !== null) {
301 $this->controllerActionName = $actionName;
302 }
303 }
304
305 /**
306 * Returns the name of the action the controller is supposed to execute.
307 *
308 * @return string Action name
309 */
310 public function getControllerActionName()
311 {
312 $controllerObjectName = $this->getControllerObjectName();
313 if ($controllerObjectName !== '' && $this->controllerActionName === strtolower($this->controllerActionName)) {
314 // todo: this is nonsense! We can detect a non existing method in
315 // todo: \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin, if necessary.
316 // todo: At this point, we want to have a getter for a fixed value.
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 }