‪TYPO3CMS  10.4
RequestBuilder.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Psr\Http\Message\ServerRequestInterface;
32 
38 {
42  protected ‪$objectManager;
43 
49  protected ‪$pluginName = 'plugin';
50 
56  protected ‪$extensionName;
57 
64 
70  protected ‪$defaultControllerName = '';
71 
77  protected ‪$defaultFormat = 'html';
78 
84  protected ‪$allowedControllerActions = [];
85 
90 
94  protected ‪$extensionService;
95 
99  protected ‪$environmentService;
100 
105 
110 
115 
120  {
121  $this->objectManager = ‪$objectManager;
122  }
123 
128  {
129  $this->configurationManager = ‪$configurationManager;
130  }
131 
136  {
137  $this->extensionService = ‪$extensionService;
138  }
139 
144  {
145  $this->environmentService = ‪$environmentService;
146  }
147 
152  protected function ‪loadDefaultValues()
153  {
154  // todo: See comment in \TYPO3\CMS\Extbase\Core\Bootstrap::initializeConfiguration for further explanation
155  // todo: on why we shouldn't use the configuration manager here.
156  $configuration = $this->configurationManager->getConfiguration(‪ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
157  if (empty($configuration['extensionName'])) {
158  throw new ‪MvcException('"extensionName" is not properly configured. Request can\'t be dispatched!', 1289843275);
159  }
160  if (empty($configuration['pluginName'])) {
161  throw new ‪MvcException('"pluginName" is not properly configured. Request can\'t be dispatched!', 1289843277);
162  }
163  $this->extensionName = $configuration['extensionName'];
164  $this->pluginName = $configuration['pluginName'];
165  $defaultControllerConfiguration = reset($configuration['controllerConfiguration']) ?? [];
166  $this->defaultControllerClassName = $defaultControllerConfiguration['className'] ?? null;
167  $this->defaultControllerName = $defaultControllerConfiguration['alias'] ?? null;
168  $this->allowedControllerActions = [];
169  foreach ($configuration['controllerConfiguration'] as $controllerClassName => $controllerConfiguration) {
170  $this->allowedControllerActions[$controllerClassName] = $controllerConfiguration['actions'] ?? null;
171  $this->controllerAliasToClassMapping[$controllerConfiguration['alias']] = $controllerConfiguration['className'];
172  $this->controllerClassToAliasMapping[$controllerConfiguration['className']] = $controllerConfiguration['alias'];
173  $this->allowedControllerAliases[] = $controllerConfiguration['alias'];
174  }
175  if (!empty($configuration['format'])) {
176  $this->defaultFormat = $configuration['format'];
177  }
178  }
179 
185  public function ‪build()
186  {
187  $this->‪loadDefaultValues();
188  $pluginNamespace = $this->extensionService->getPluginNamespace($this->extensionName, $this->pluginName);
190  $typo3Request = ‪$GLOBALS['TYPO3_REQUEST'] ?? null;
191  if ($typo3Request instanceof ServerRequestInterface) {
192  $queryArguments = $typo3Request->getAttribute('routing');
193  if ($queryArguments instanceof PageArguments) {
194  $parameters = $queryArguments->get($pluginNamespace) ?? [];
195  } else {
196  $parameters = $typo3Request->getQueryParams()[$pluginNamespace] ?? [];
197  }
198  $bodyParameters = $typo3Request->getParsedBody()[$pluginNamespace] ?? [];
199  $parameters = is_array($parameters) ? $parameters : [];
200  $bodyParameters = is_array($bodyParameters) ? $bodyParameters : [];
201  ‪ArrayUtility::mergeRecursiveWithOverrule($parameters, $bodyParameters);
202  } else {
203  $parameters = GeneralUtility::_GPmerged($pluginNamespace);
204  }
205 
206  $files = $this->‪untangleFilesArray($_FILES);
207  if (is_array($files[$pluginNamespace] ?? null)) {
208  $parameters = array_replace_recursive($parameters, $files[$pluginNamespace]);
209  }
210 
211  $controllerClassName = $this->‪resolveControllerClassName($parameters);
212  $actionName = $this->‪resolveActionName($controllerClassName, $parameters);
213 
214  $baseUri = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
215  if ($this->environmentService->isEnvironmentInBackendMode()) {
216  $baseUri .= TYPO3_mainDir;
217  }
218 
220  $request = $this->objectManager->get(Request::class);
221  $request->setPluginName($this->pluginName);
222  $request->setControllerExtensionName($this->extensionName);
223  $request->setControllerAliasToClassNameMapping($this->controllerAliasToClassMapping);
224  $request->setControllerName($this->controllerClassToAliasMapping[$controllerClassName]);
225  $request->setControllerActionName($actionName);
226  // @todo Use Environment
227  $request->setRequestUri(GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL'));
228  $request->setBaseUri($baseUri);
229  $request->setMethod($this->‪getServerRequestMethod($typo3Request));
230  if (isset($parameters['format']) && is_string($parameters['format']) && $parameters['format'] !== '') {
231  $request->setFormat(filter_var($parameters['format'], FILTER_SANITIZE_STRING));
232  } else {
233  $request->setFormat($this->defaultFormat);
234  }
235  foreach ($parameters as $argumentName => $argumentValue) {
236  $request->setArgument($argumentName, $argumentValue);
237  }
238  return $request;
239  }
240 
252  protected function ‪resolveControllerClassName(array $parameters)
253  {
254  if (!isset($parameters['controller']) || $parameters['controller'] === '') {
255  if (empty($this->defaultControllerClassName)) {
256  throw new ‪MvcException('The default controller for extension "' . $this->extensionName . '" and plugin "' . $this->pluginName . '" can not be determined. Please check for TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php.', 1316104317);
257  }
259  }
260  $controllerClassName = $this->controllerAliasToClassMapping[$parameters['controller']] ?? '';
261  if (!in_array($controllerClassName, array_keys($this->allowedControllerActions))) {
262  $configuration = $this->configurationManager->getConfiguration(‪ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
263  if (isset($configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) && (bool)$configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) {
264  throw new PageNotFoundException('The requested resource was not found', 1313857897);
265  }
266  if (isset($configuration['mvc']['callDefaultActionIfActionCantBeResolved']) && (bool)$configuration['mvc']['callDefaultActionIfActionCantBeResolved']) {
268  }
269  throw new InvalidControllerNameException(
270  'The controller "' . $parameters['controller'] . '" is not allowed by plugin "' . $this->pluginName . '". Please check for TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php.',
271  1313855173
272  );
273  }
274  return filter_var($controllerClassName, FILTER_SANITIZE_STRING);
275  }
276 
289  protected function ‪resolveActionName($controllerClassName, array $parameters)
290  {
291  $defaultActionName = is_array($this->allowedControllerActions[$controllerClassName]) ? current($this->allowedControllerActions[$controllerClassName]) : '';
292  if (!isset($parameters['action']) || $parameters['action'] === '') {
293  if ($defaultActionName === '') {
294  throw new ‪MvcException('The default action can not be determined for controller "' . $controllerClassName . '". Please check TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php.', 1295479651);
295  }
296  return $defaultActionName;
297  }
298  $actionName = $parameters['action'];
299  $allowedActionNames = $this->allowedControllerActions[$controllerClassName];
300  if (!in_array($actionName, $allowedActionNames)) {
301  $configuration = $this->configurationManager->getConfiguration(‪ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
302  if (isset($configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) && (bool)$configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) {
303  throw new ‪PageNotFoundException('The requested resource was not found', 1313857898);
304  }
305  if (isset($configuration['mvc']['callDefaultActionIfActionCantBeResolved']) && (bool)$configuration['mvc']['callDefaultActionIfActionCantBeResolved']) {
306  return $defaultActionName;
307  }
308  throw new ‪InvalidActionNameException('The action "' . $actionName . '" (controller "' . $controllerClassName . '") is not allowed by this plugin / module. Please check TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php / TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configureModule() in your ext_tables.php.', 1313855175);
309  }
310  return filter_var($actionName, FILTER_SANITIZE_STRING);
311  }
312 
319  protected function ‪untangleFilesArray(array $convolutedFiles)
320  {
321  $untangledFiles = [];
322  $fieldPaths = [];
323  foreach ($convolutedFiles as $firstLevelFieldName => $fieldInformation) {
324  if (!is_array($fieldInformation['error'])) {
325  $fieldPaths[] = [$firstLevelFieldName];
326  } else {
327  $newFieldPaths = $this->‪calculateFieldPaths($fieldInformation['error'], $firstLevelFieldName);
328  array_walk($newFieldPaths, function (&$value, $key) {
329  $value = explode('/', $value);
330  });
331  $fieldPaths = array_merge($fieldPaths, $newFieldPaths);
332  }
333  }
334  foreach ($fieldPaths as $fieldPath) {
335  if (count($fieldPath) === 1) {
336  $fileInformation = $convolutedFiles[$fieldPath[0]];
337  } else {
338  $fileInformation = [];
339  foreach ($convolutedFiles[$fieldPath[0]] as $key => $subStructure) {
340  try {
341  $fileInformation[$key] = ‪ArrayUtility::getValueByPath($subStructure, array_slice($fieldPath, 1));
342  } catch (MissingArrayPathException $e) {
343  // do nothing if the path is invalid
344  }
345  }
346  }
347  $untangledFiles = ‪ArrayUtility::setValueByPath($untangledFiles, $fieldPath, $fileInformation);
348  }
349  return $untangledFiles;
350  }
351 
359  protected function ‪calculateFieldPaths(array $structure, $firstLevelFieldName = null)
360  {
361  $fieldPaths = [];
362  if (is_array($structure)) {
363  foreach ($structure as $key => $subStructure) {
364  $fieldPath = ($firstLevelFieldName !== null ? $firstLevelFieldName . '/' : '') . $key;
365  if (is_array($subStructure)) {
366  foreach ($this->‪calculateFieldPaths($subStructure) as $subFieldPath) {
367  $fieldPaths[] = $fieldPath . '/' . $subFieldPath;
368  }
369  } else {
370  $fieldPaths[] = $fieldPath;
371  }
372  }
373  }
374  return $fieldPaths;
375  }
376 
377  protected function ‪getServerRequestMethod(?ServerRequestInterface $typo3Request): string
378  {
379  if ($typo3Request instanceof ServerRequestInterface) {
380  return $typo3Request->getMethod();
381  }
382  return isset($_SERVER['REQUEST_METHOD']) && is_string($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
383  }
384 }
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$controllerClassToAliasMapping
‪array $controllerClassToAliasMapping
Definition: RequestBuilder.php:97
‪TYPO3\CMS\Core\Routing\PageArguments
Definition: PageArguments.php:26
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\resolveActionName
‪string resolveActionName($controllerClassName, array $parameters)
Definition: RequestBuilder.php:276
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$controllerAliasToClassMapping
‪array $controllerAliasToClassMapping
Definition: RequestBuilder.php:93
‪TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException
Definition: MissingArrayPathException.php:28
‪TYPO3\CMS\Extbase\Mvc\Exception\InvalidControllerNameException
Definition: InvalidControllerNameException.php:26
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$pluginName
‪string $pluginName
Definition: RequestBuilder.php:47
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$defaultFormat
‪string $defaultFormat
Definition: RequestBuilder.php:71
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$defaultControllerName
‪string $defaultControllerName
Definition: RequestBuilder.php:65
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
Definition: ConfigurationManagerInterface.php:28
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:654
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\injectExtensionService
‪injectExtensionService(ExtensionService $extensionService)
Definition: RequestBuilder.php:122
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\injectConfigurationManager
‪injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
Definition: RequestBuilder.php:114
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$objectManager
‪TYPO3 CMS Extbase Object ObjectManagerInterface $objectManager
Definition: RequestBuilder.php:41
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$allowedControllerActions
‪array $allowedControllerActions
Definition: RequestBuilder.php:77
‪TYPO3\CMS\Extbase\Object\ObjectManagerInterface
Definition: ObjectManagerInterface.php:26
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface\CONFIGURATION_TYPE_FRAMEWORK
‪const CONFIGURATION_TYPE_FRAMEWORK
Definition: ConfigurationManagerInterface.php:29
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static mixed getValueByPath(array $array, $path, $delimiter='/')
Definition: ArrayUtility.php:180
‪TYPO3\CMS\Core\Error\Http\PageNotFoundException
Definition: PageNotFoundException.php:24
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$extensionService
‪TYPO3 CMS Extbase Service ExtensionService $extensionService
Definition: RequestBuilder.php:85
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\injectEnvironmentService
‪injectEnvironmentService(EnvironmentService $environmentService)
Definition: RequestBuilder.php:130
‪TYPO3\CMS\Extbase\Mvc\Exception
Definition: InfiniteLoopException.php:18
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\build
‪TYPO3 CMS Extbase Mvc Web Request build()
Definition: RequestBuilder.php:172
‪TYPO3\CMS\Extbase\Service\EnvironmentService
Definition: EnvironmentService.php:27
‪TYPO3\CMS\Extbase\Mvc\Web
Definition: AbstractRequestHandler.php:16
‪TYPO3\CMS\Core\Utility\ArrayUtility\setValueByPath
‪static array setValueByPath(array $array, $path, $value, $delimiter='/')
Definition: ArrayUtility.php:272
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$configurationManager
‪TYPO3 CMS Extbase Configuration ConfigurationManagerInterface $configurationManager
Definition: RequestBuilder.php:81
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\calculateFieldPaths
‪array calculateFieldPaths(array $structure, $firstLevelFieldName=null)
Definition: RequestBuilder.php:346
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\loadDefaultValues
‪loadDefaultValues()
Definition: RequestBuilder.php:139
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:23
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$defaultControllerClassName
‪string $defaultControllerClassName
Definition: RequestBuilder.php:59
‪TYPO3\CMS\Extbase\Service\ExtensionService
Definition: ExtensionService.php:33
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\untangleFilesArray
‪array untangleFilesArray(array $convolutedFiles)
Definition: RequestBuilder.php:306
‪TYPO3\CMS\Extbase\Mvc\Exception\InvalidActionNameException
Definition: InvalidActionNameException.php:26
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$allowedControllerAliases
‪array string[] $allowedControllerAliases
Definition: RequestBuilder.php:101
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\resolveControllerClassName
‪string resolveControllerClassName(array $parameters)
Definition: RequestBuilder.php:239
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\getServerRequestMethod
‪getServerRequestMethod(?ServerRequestInterface $typo3Request)
Definition: RequestBuilder.php:364
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$environmentService
‪TYPO3 CMS Extbase Service EnvironmentService $environmentService
Definition: RequestBuilder.php:89
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\injectObjectManager
‪injectObjectManager(ObjectManagerInterface $objectManager)
Definition: RequestBuilder.php:106
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder
Definition: RequestBuilder.php:38
‪TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder\$extensionName
‪string $extensionName
Definition: RequestBuilder.php:53