[CLEANUP] Adjust code to coding guidelines
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Mvc / Web / RequestBuilder.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Mvc\Web;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * This class is a backport of the corresponding class of TYPO3 Flow.
8 * All credits go to the TYPO3 Flow team.
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the textfile GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30 /**
31 * Builds a web request.
32 */
33 class RequestBuilder implements \TYPO3\CMS\Core\SingletonInterface {
34
35 /**
36 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
37 */
38 protected $objectManager;
39
40 /**
41 * This is the vendor name of the extension
42 *
43 * @var string
44 */
45 protected $vendorName;
46
47 /**
48 * This is a unique key for a plugin (not the extension key!)
49 *
50 * @var string
51 */
52 protected $pluginName = 'plugin';
53
54 /**
55 * The name of the extension (in UpperCamelCase)
56 *
57 * @var string
58 */
59 protected $extensionName;
60
61 /**
62 * The default controller name
63 *
64 * @var string
65 */
66 protected $defaultControllerName;
67
68 /**
69 * The default format of the response object
70 *
71 * @var string
72 */
73 protected $defaultFormat = 'html';
74
75 /**
76 * The allowed actions of the controller. This actions can be called via $_GET and $_POST.
77 *
78 * @var array
79 */
80 protected $allowedControllerActions = array();
81
82 /**
83 * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
84 */
85 protected $configurationManager;
86
87 /**
88 * @var \TYPO3\CMS\Extbase\Service\ExtensionService
89 */
90 protected $extensionService;
91
92 /**
93 * @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
94 */
95 public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager) {
96 $this->configurationManager = $configurationManager;
97 }
98
99 /**
100 * Injects the object manager
101 *
102 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
103 * @return void
104 */
105 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) {
106 $this->objectManager = $objectManager;
107 }
108
109 /**
110 * @param \TYPO3\CMS\Extbase\Service\ExtensionService $extensionService
111 * @return void
112 */
113 public function injectExtensionService(\TYPO3\CMS\Extbase\Service\ExtensionService $extensionService) {
114 $this->extensionService = $extensionService;
115 }
116
117 /**
118 * @throws \TYPO3\CMS\Extbase\Mvc\Exception
119 * @return void
120 */
121 protected function loadDefaultValues() {
122 $configuration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
123 if (empty($configuration['extensionName'])) {
124 throw new \TYPO3\CMS\Extbase\Mvc\Exception('"extensionName" is not properly configured. Request can\'t be dispatched!', 1289843275);
125 }
126 if (empty($configuration['pluginName'])) {
127 throw new \TYPO3\CMS\Extbase\Mvc\Exception('"pluginName" is not properly configured. Request can\'t be dispatched!', 1289843277);
128 }
129 if (!empty($configuration['vendorName'])) {
130 $this->vendorName = $configuration['vendorName'];
131 } else {
132 $this->vendorName = NULL;
133 }
134 $this->extensionName = $configuration['extensionName'];
135 $this->pluginName = $configuration['pluginName'];
136 $this->defaultControllerName = current(array_keys($configuration['controllerConfiguration']));
137 $this->allowedControllerActions = array();
138 foreach ($configuration['controllerConfiguration'] as $controllerName => $controllerActions) {
139 $this->allowedControllerActions[$controllerName] = $controllerActions['actions'];
140 }
141 if (!empty($configuration['format'])) {
142 $this->defaultFormat = $configuration['format'];
143 }
144 }
145
146 /**
147 * Builds a web request object from the raw HTTP information and the configuration
148 *
149 * @return \TYPO3\CMS\Extbase\Mvc\Web\Request The web request as an object
150 */
151 public function build() {
152 $this->loadDefaultValues();
153 $pluginNamespace = $this->extensionService->getPluginNamespace($this->extensionName, $this->pluginName);
154 $parameters = \TYPO3\CMS\Core\Utility\GeneralUtility::_GPmerged($pluginNamespace);
155 $files = $this->untangleFilesArray($_FILES);
156 if (isset($files[$pluginNamespace]) && is_array($files[$pluginNamespace])) {
157 $parameters = \TYPO3\CMS\Extbase\Utility\ArrayUtility::arrayMergeRecursiveOverrule($parameters, $files[$pluginNamespace]);
158 }
159 $controllerName = $this->resolveControllerName($parameters);
160 $actionName = $this->resolveActionName($controllerName, $parameters);
161 /** @var $request \TYPO3\CMS\Extbase\Mvc\Web\Request */
162 $request = $this->objectManager->create('TYPO3\\CMS\\Extbase\\Mvc\\Web\\Request');
163 if ($this->vendorName !== NULL) {
164 $request->setControllerVendorName($this->vendorName);
165 }
166 $request->setPluginName($this->pluginName);
167 $request->setControllerExtensionName($this->extensionName);
168 $request->setControllerName($controllerName);
169 $request->setControllerActionName($actionName);
170 $request->setRequestUri(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL'));
171 $request->setBaseUri(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL'));
172 $request->setMethod(isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : NULL);
173 if (is_string($parameters['format']) && strlen($parameters['format'])) {
174 $request->setFormat(filter_var($parameters['format'], FILTER_SANITIZE_STRING));
175 } else {
176 $request->setFormat($this->defaultFormat);
177 }
178 foreach ($parameters as $argumentName => $argumentValue) {
179 $request->setArgument($argumentName, $argumentValue);
180 }
181 return $request;
182 }
183
184 /**
185 * Returns the current ControllerName extracted from given $parameters.
186 * If no controller is specified, the defaultControllerName will be returned.
187 * If that's not available, an exception is thrown.
188 *
189 * @param array $parameters
190 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidControllerNameException
191 * @throws \TYPO3\CMS\Extbase\Mvc\Exception if the controller could not be resolved
192 * @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException
193 * @return string
194 */
195 protected function resolveControllerName(array $parameters) {
196 if (!isset($parameters['controller']) || strlen($parameters['controller']) === 0) {
197 if (strlen($this->defaultControllerName) === 0) {
198 throw new \TYPO3\CMS\Extbase\Mvc\Exception('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);
199 }
200 return $this->defaultControllerName;
201 }
202 $allowedControllerNames = array_keys($this->allowedControllerActions);
203 if (!in_array($parameters['controller'], $allowedControllerNames)) {
204 $configuration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
205 if (isset($configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) && (boolean) $configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) {
206 throw new \TYPO3\CMS\Core\Error\Http\PageNotFoundException('The requested resource was not found', 1313857897);
207 } elseif (isset($configuration['mvc']['callDefaultActionIfActionCantBeResolved']) && (boolean) $configuration['mvc']['callDefaultActionIfActionCantBeResolved']) {
208 return $this->defaultControllerName;
209 }
210 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidControllerNameException('The controller "' . $parameters['controller'] . '" is not allowed by this plugin. Please check for TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php.', 1313855173);
211 }
212 return filter_var($parameters['controller'], FILTER_SANITIZE_STRING);
213 }
214
215 /**
216 * Returns the current actionName extracted from given $parameters.
217 * If no action is specified, the defaultActionName will be returned.
218 * If that's not available or the specified action is not defined in the current plugin, an exception is thrown.
219 *
220 * @param $controllerName
221 * @param array $parameters
222 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidActionNameException
223 * @throws \TYPO3\CMS\Extbase\Mvc\Exception
224 * @throws \TYPO3\CMS\Core\Error\Http\PageNotFoundException
225 * @return string
226 */
227 protected function resolveActionName($controllerName, array $parameters) {
228 $defaultActionName = is_array($this->allowedControllerActions[$controllerName]) ? current($this->allowedControllerActions[$controllerName]) : '';
229 if (!isset($parameters['action']) || strlen($parameters['action']) === 0) {
230 if (strlen($defaultActionName) === 0) {
231 throw new \TYPO3\CMS\Extbase\Mvc\Exception('The default action can not be determined for controller "' . $controllerName . '". Please check TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php.', 1295479651);
232 }
233 return $defaultActionName;
234 }
235 $actionName = $parameters['action'];
236 $allowedActionNames = $this->allowedControllerActions[$controllerName];
237 if (!in_array($actionName, $allowedActionNames)) {
238 $configuration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
239 if (isset($configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) && (boolean) $configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) {
240 throw new \TYPO3\CMS\Core\Error\Http\PageNotFoundException('The requested resource was not found', 1313857897);
241 } elseif (isset($configuration['mvc']['callDefaultActionIfActionCantBeResolved']) && (boolean) $configuration['mvc']['callDefaultActionIfActionCantBeResolved']) {
242 return $defaultActionName;
243 }
244 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidActionNameException('The action "' . $actionName . '" (controller "' . $controllerName . '") is not allowed by this plugin. Please check TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility::configurePlugin() in your ext_localconf.php.', 1313855175);
245 }
246 return filter_var($actionName, FILTER_SANITIZE_STRING);
247 }
248
249 /**
250 * Transforms the convoluted _FILES superglobal into a manageable form.
251 *
252 * @param array $convolutedFiles The _FILES superglobal
253 * @return array Untangled files
254 * @see TYPO3\FLOW3\Utility\Environment
255 */
256 protected function untangleFilesArray(array $convolutedFiles) {
257 $untangledFiles = array();
258 $fieldPaths = array();
259 foreach ($convolutedFiles as $firstLevelFieldName => $fieldInformation) {
260 if (!is_array($fieldInformation['error'])) {
261 $fieldPaths[] = array($firstLevelFieldName);
262 } else {
263 $newFieldPaths = $this->calculateFieldPaths($fieldInformation['error'], $firstLevelFieldName);
264 array_walk($newFieldPaths, function (&$value, $key) {
265 $value = explode('/', $value);
266 });
267 $fieldPaths = array_merge($fieldPaths, $newFieldPaths);
268 }
269 }
270 foreach ($fieldPaths as $fieldPath) {
271 if (count($fieldPath) === 1) {
272 $fileInformation = $convolutedFiles[$fieldPath[0]];
273 } else {
274 $fileInformation = array();
275 foreach ($convolutedFiles[$fieldPath[0]] as $key => $subStructure) {
276 $fileInformation[$key] = \TYPO3\CMS\Extbase\Utility\ArrayUtility::getValueByPath($subStructure, array_slice($fieldPath, 1));
277 }
278 }
279 $untangledFiles = \TYPO3\CMS\Extbase\Utility\ArrayUtility::setValueByPath($untangledFiles, $fieldPath, $fileInformation);
280 }
281 return $untangledFiles;
282 }
283
284 /**
285 * Returns an array of all possibles "field paths" for the given array.
286 *
287 * @param array $structure The array to walk through
288 * @param string $firstLevelFieldName
289 * @return array An array of paths (as strings) in the format "key1/key2/key3" ...
290 */
291 protected function calculateFieldPaths(array $structure, $firstLevelFieldName = NULL) {
292 $fieldPaths = array();
293 if (is_array($structure)) {
294 foreach ($structure as $key => $subStructure) {
295 $fieldPath = ($firstLevelFieldName !== NULL ? $firstLevelFieldName . '/' : '') . $key;
296 if (is_array($subStructure)) {
297 foreach ($this->calculateFieldPaths($subStructure) as $subFieldPath) {
298 $fieldPaths[] = $fieldPath . '/' . $subFieldPath;
299 }
300 } else {
301 $fieldPaths[] = $fieldPath;
302 }
303 }
304 }
305 return $fieldPaths;
306 }
307 }
308
309 ?>