[BUGFIX] No double htmlspecialchars for filemount select
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Mvc / Controller / ActionController.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Mvc\Controller;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2013 Extbase Team (http://forge.typo3.org/projects/typo3v4-mvc)
8 * Extbase is a backport of TYPO3 Flow. 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 use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
31 use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
32
33 /**
34 * A multi action controller. This is by far the most common base class for Controllers.
35 *
36 * @api
37 */
38 class ActionController extends \TYPO3\CMS\Extbase\Mvc\Controller\AbstractController {
39
40 /**
41 * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
42 * @inject
43 */
44 protected $reflectionService;
45
46 /**
47 * @var \TYPO3\CMS\Extbase\Service\CacheService
48 * @inject
49 */
50 protected $cacheService;
51
52 /**
53 * The current view, as resolved by resolveView()
54 *
55 * @var ViewInterface
56 * @api
57 */
58 protected $view = NULL;
59
60 /**
61 * Pattern after which the view object name is built if no Fluid template
62 * is found.
63 *
64 * @var string
65 * @api
66 * @deprecated since Extbase 6.2, will be removed two versions later
67 */
68 protected $viewObjectNamePattern = 'Tx_@extension_View_@controller_@action@format';
69
70 /**
71 * @var string
72 * @api
73 */
74 protected $namespacesViewObjectNamePattern = '@vendor\@extension\View\@controller\@action@format';
75
76 /**
77 * A list of formats and object names of the views which should render them.
78 *
79 * Example:
80 *
81 * array('html' => 'Tx_MyExtension_View_MyHtmlView', 'json' => 'F3...
82 *
83 * @var array
84 */
85 protected $viewFormatToObjectNameMap = array();
86
87 /**
88 * The default view object to use if none of the resolved views can render
89 * a response for the current request.
90 *
91 * @var string
92 * @api
93 */
94 protected $defaultViewObjectName = 'TYPO3\\CMS\\Fluid\\View\\TemplateView';
95
96 /**
97 * Name of the action method
98 *
99 * @var string
100 * @api
101 */
102 protected $actionMethodName = 'indexAction';
103
104 /**
105 * Name of the special error action method which is called in case of errors
106 *
107 * @var string
108 * @api
109 */
110 protected $errorMethodName = 'errorAction';
111
112 /**
113 * @var \TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService
114 * @inject
115 * @api
116 */
117 protected $mvcPropertyMappingConfigurationService;
118
119 /**
120 * Checks if the current request type is supported by the controller.
121 *
122 * If your controller only supports certain request types, either
123 * replace / modify the supporteRequestTypes property or override this
124 * method.
125 *
126 * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request The current request
127 * @return boolean TRUE if this request type is supported, otherwise FALSE
128 */
129 public function canProcessRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request) {
130 return parent::canProcessRequest($request);
131 }
132
133 /**
134 * Handles a request. The result output is returned by altering the given response.
135 *
136 * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request The request object
137 * @param \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response The response, modified by this handler
138 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
139 * @return void
140 */
141 public function processRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request, \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response) {
142 if (!$this->canProcessRequest($request)) {
143 throw new \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException(get_class($this) . ' does not support requests of type "' . get_class($request) . '". Supported types are: ' . implode(' ', $this->supportedRequestTypes), 1187701131);
144 }
145 if ($response instanceof \TYPO3\CMS\Extbase\Mvc\Web\Response) {
146 $response->setRequest($request);
147 }
148 $this->request = $request;
149 $this->request->setDispatched(TRUE);
150 $this->response = $response;
151 $this->uriBuilder = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Mvc\\Web\\Routing\\UriBuilder');
152 $this->uriBuilder->setRequest($request);
153 $this->actionMethodName = $this->resolveActionMethodName();
154 $this->initializeActionMethodArguments();
155 $this->initializeActionMethodValidators();
156 $this->mvcPropertyMappingConfigurationService->initializePropertyMappingConfigurationFromRequest($request, $this->arguments);
157 $this->initializeAction();
158 $actionInitializationMethodName = 'initialize' . ucfirst($this->actionMethodName);
159 if (method_exists($this, $actionInitializationMethodName)) {
160 call_user_func(array($this, $actionInitializationMethodName));
161 }
162 $this->mapRequestArgumentsToControllerArguments();
163 $this->checkRequestHash();
164 $this->controllerContext = $this->buildControllerContext();
165 $this->view = $this->resolveView();
166 if ($this->view !== NULL) {
167 $this->initializeView($this->view);
168 }
169 $this->callActionMethod();
170 }
171
172 /**
173 * Implementation of the arguments initilization in the action controller:
174 * Automatically registers arguments of the current action
175 *
176 * Don't override this method - use initializeAction() instead.
177 *
178 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentTypeException
179 * @return void
180 * @see initializeArguments()
181 */
182 protected function initializeActionMethodArguments() {
183 $methodParameters = $this->reflectionService->getMethodParameters(get_class($this), $this->actionMethodName);
184 foreach ($methodParameters as $parameterName => $parameterInfo) {
185 $dataType = NULL;
186 if (isset($parameterInfo['type'])) {
187 $dataType = $parameterInfo['type'];
188 } elseif ($parameterInfo['array']) {
189 $dataType = 'array';
190 }
191 if ($dataType === NULL) {
192 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentTypeException('The argument type for parameter $' . $parameterName . ' of method ' . get_class($this) . '->' . $this->actionMethodName . '() could not be detected.', 1253175643);
193 }
194 $defaultValue = isset($parameterInfo['defaultValue']) ? $parameterInfo['defaultValue'] : NULL;
195 $this->arguments->addNewArgument($parameterName, $dataType, $parameterInfo['optional'] === FALSE, $defaultValue);
196 }
197 }
198
199 /**
200 * Adds the needed validators to the Arguments:
201 *
202 * - Validators checking the data type from the @param annotation
203 * - Custom validators specified with validate annotations.
204 * - Model-based validators (validate annotations in the model)
205 * - Custom model validator classes
206 *
207 * @return void
208 */
209 protected function initializeActionMethodValidators() {
210
211 if (!$this->configurationManager->isFeatureEnabled('rewrittenPropertyMapper')) {
212 // @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
213
214 $parameterValidators = $this->validatorResolver->buildMethodArgumentsValidatorConjunctions(get_class($this), $this->actionMethodName);
215 $dontValidateAnnotations = array();
216
217 $methodTagsValues = $this->reflectionService->getMethodTagsValues(get_class($this), $this->actionMethodName);
218 if (isset($methodTagsValues['dontvalidate'])) {
219 $dontValidateAnnotations = $methodTagsValues['dontvalidate'];
220 }
221
222 foreach ($this->arguments as $argument) {
223 $validator = $parameterValidators[$argument->getName()];
224 if (array_search('$' . $argument->getName(), $dontValidateAnnotations) === FALSE) {
225 $baseValidatorConjunction = $this->validatorResolver->getBaseValidatorConjunction($argument->getDataType());
226 if ($baseValidatorConjunction !== NULL) {
227 $validator->addValidator($baseValidatorConjunction);
228 }
229 }
230 $argument->setValidator($validator);
231 }
232 } else {
233 /**
234 * @todo: add validation group support
235 * (https://review.typo3.org/#/c/13556/4)
236 */
237
238 $actionMethodParameters = static::getActionMethodParameters($this->objectManager);
239 if (isset($actionMethodParameters[$this->actionMethodName])) {
240 $methodParameters = $actionMethodParameters[$this->actionMethodName];
241 } else {
242 $methodParameters = array();
243 }
244
245 /**
246 * @todo: add resolving of $actionValidateAnnotations and pass them to
247 * buildMethodArgumentsValidatorConjunctions as in TYPO3.Flow
248 */
249
250 $parameterValidators = $this->validatorResolver->buildMethodArgumentsValidatorConjunctions(get_class($this), $this->actionMethodName, $methodParameters);
251
252 foreach ($this->arguments as $argument) {
253 $validator = $parameterValidators[$argument->getName()];
254
255 $baseValidatorConjunction = $this->validatorResolver->getBaseValidatorConjunction($argument->getDataType());
256 if (count($baseValidatorConjunction) > 0) {
257 $validator->addValidator($baseValidatorConjunction);
258 }
259 $argument->setValidator($validator);
260 }
261 }
262 }
263
264 /**
265 * Resolves and checks the current action method name
266 *
267 * @return string Method name of the current action
268 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchActionException if the action specified in the request object does not exist (and if there's no default action either).
269 */
270 protected function resolveActionMethodName() {
271 $actionMethodName = $this->request->getControllerActionName() . 'Action';
272 if (!method_exists($this, $actionMethodName)) {
273 throw new \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchActionException('An action "' . $actionMethodName . '" does not exist in controller "' . get_class($this) . '".', 1186669086);
274 }
275 return $actionMethodName;
276 }
277
278 /**
279 * Calls the specified action method and passes the arguments.
280 *
281 * If the action returns a string, it is appended to the content in the
282 * response object. If the action doesn't return anything and a valid
283 * view exists, the view is rendered automatically.
284 *
285 * @return void
286 * @api
287 */
288 protected function callActionMethod() {
289 if ($this->configurationManager->isFeatureEnabled('rewrittenPropertyMapper')) {
290 // enabled since Extbase 1.4.0.
291 $preparedArguments = array();
292 foreach ($this->arguments as $argument) {
293 $preparedArguments[] = $argument->getValue();
294 }
295 $validationResult = $this->arguments->getValidationResults();
296 if (!$validationResult->hasErrors()) {
297 $this->signalSlotDispatcher->dispatch(__CLASS__, 'beforeCallActionMethod', array('controllerName' => get_class($this), 'actionMethodName' => $this->actionMethodName, 'preparedArguments' => $preparedArguments));
298 $actionResult = call_user_func_array(array($this, $this->actionMethodName), $preparedArguments);
299 } else {
300 $methodTagsValues = $this->reflectionService->getMethodTagsValues(get_class($this), $this->actionMethodName);
301 $ignoreValidationAnnotations = array();
302 if (isset($methodTagsValues['ignorevalidation'])) {
303 $ignoreValidationAnnotations = $methodTagsValues['ignorevalidation'];
304 }
305 // if there exists more errors than in ignoreValidationAnnotations_=> call error method
306 // else => call action method
307 $shouldCallActionMethod = TRUE;
308 foreach ($validationResult->getSubResults() as $argumentName => $subValidationResult) {
309 if (!$subValidationResult->hasErrors()) {
310 continue;
311 }
312 if (array_search('$' . $argumentName, $ignoreValidationAnnotations) !== FALSE) {
313 continue;
314 }
315 $shouldCallActionMethod = FALSE;
316 }
317 if ($shouldCallActionMethod) {
318 $this->signalSlotDispatcher->dispatch(__CLASS__, 'beforeCallActionMethod', array('controllerName' => get_class($this), 'actionMethodName' => $this->actionMethodName, 'preparedArguments' => $preparedArguments));
319 $actionResult = call_user_func_array(array($this, $this->actionMethodName), $preparedArguments);
320 } else {
321 $actionResult = call_user_func(array($this, $this->errorMethodName));
322 }
323 }
324 } else {
325 // @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
326 $preparedArguments = array();
327 foreach ($this->arguments as $argument) {
328 $preparedArguments[] = $argument->getValue();
329 }
330 if ($this->argumentsMappingResults->hasErrors()) {
331 $actionResult = call_user_func(array($this, $this->errorMethodName));
332 } else {
333 $this->signalSlotDispatcher->dispatch(__CLASS__, 'beforeCallActionMethod', array('controllerName' => get_class($this), 'actionMethodName' => $this->actionMethodName, 'preparedArguments' => $preparedArguments));
334 $actionResult = call_user_func_array(array($this, $this->actionMethodName), $preparedArguments);
335 }
336 }
337 if ($actionResult === NULL && $this->view instanceof ViewInterface) {
338 $this->response->appendContent($this->view->render());
339 } elseif (is_string($actionResult) && strlen($actionResult) > 0) {
340 $this->response->appendContent($actionResult);
341 } elseif (is_object($actionResult) && method_exists($actionResult, '__toString')) {
342 $this->response->appendContent((string) $actionResult);
343 }
344 }
345
346 /**
347 * Prepares a view for the current action and stores it in $this->view.
348 * By default, this method tries to locate a view with a name matching
349 * the current action.
350 *
351 * @return string
352 * @api
353 */
354 protected function resolveView() {
355 $viewObjectName = $this->resolveViewObjectName();
356 if ($viewObjectName !== FALSE) {
357 /** @var $view ViewInterface */
358 $view = $this->objectManager->get($viewObjectName);
359 $this->setViewConfiguration($view);
360 if ($view->canRender($this->controllerContext) === FALSE) {
361 unset($view);
362 }
363 }
364 if (!isset($view) && $this->defaultViewObjectName != '') {
365 /** @var $view ViewInterface */
366 $view = $this->objectManager->get($this->defaultViewObjectName);
367 $this->setViewConfiguration($view);
368 if ($view->canRender($this->controllerContext) === FALSE) {
369 unset($view);
370 }
371 }
372 if (!isset($view)) {
373 $view = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Mvc\\View\\NotFoundView');
374 $view->assign('errorMessage', 'No template was found. View could not be resolved for action "'
375 . $this->request->getControllerActionName() . '" in class "' . $this->request->getControllerObjectName() . '"');
376 }
377 $view->setControllerContext($this->controllerContext);
378 if (method_exists($view, 'injectSettings')) {
379 $view->injectSettings($this->settings);
380 }
381 $view->initializeView();
382 // In FLOW3, solved through Object Lifecycle methods, we need to call it explicitely
383 $view->assign('settings', $this->settings);
384 // same with settings injection.
385 return $view;
386 }
387
388 /**
389 * @param ViewInterface $view
390 *
391 * @return void
392 */
393 protected function setViewConfiguration(ViewInterface $view) {
394 // Template Path Override
395 $extbaseFrameworkConfiguration = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
396 if (isset($extbaseFrameworkConfiguration['view']['templateRootPath'])
397 && strlen($extbaseFrameworkConfiguration['view']['templateRootPath']) > 0
398 && method_exists($view, 'setTemplateRootPath')
399 ) {
400 $view->setTemplateRootPath($extbaseFrameworkConfiguration['view']['templateRootPath']);
401 } elseif (!empty($extbaseFrameworkConfiguration['view']['templateRootPaths'])
402 && is_array($extbaseFrameworkConfiguration['view']['templateRootPaths'])
403 && method_exists($view, 'setTemplateRootPaths')
404 ) {
405 $paths = $extbaseFrameworkConfiguration['view']['templateRootPaths'];
406 krsort($paths);
407 $view->setTemplateRootPaths($paths);
408 }
409 if (isset($extbaseFrameworkConfiguration['view']['layoutRootPath'])
410 && strlen($extbaseFrameworkConfiguration['view']['layoutRootPath']) > 0
411 && method_exists($view, 'setLayoutRootPath')
412 ) {
413 $view->setLayoutRootPath($extbaseFrameworkConfiguration['view']['layoutRootPath']);
414 } elseif (!empty($extbaseFrameworkConfiguration['view']['layoutRootPaths'])
415 && is_array($extbaseFrameworkConfiguration['view']['layoutRootPaths'])
416 && method_exists($view, 'layoutRootPaths')
417 ) {
418 $paths = $extbaseFrameworkConfiguration['view']['layoutRootPaths'];
419 krsort($paths);
420 $view->setLayoutRootPaths($paths);
421 }
422 if (isset($extbaseFrameworkConfiguration['view']['partialRootPath'])
423 && strlen($extbaseFrameworkConfiguration['view']['partialRootPath']) > 0
424 && method_exists($view, 'setPartialRootPath')
425 ) {
426 $view->setPartialRootPath($extbaseFrameworkConfiguration['view']['partialRootPath']);
427 } elseif (!empty($extbaseFrameworkConfiguration['view']['partialRootPaths'])
428 && is_array($extbaseFrameworkConfiguration['view']['partialRootPaths'])
429 && method_exists($view, 'setPartialRootPaths')
430 ) {
431 $paths = $extbaseFrameworkConfiguration['view']['partialRootPaths'];
432 krsort($paths);
433 $view->setPartialRootPaths($paths);
434 }
435 }
436
437 /**
438 * Determines the fully qualified view object name.
439 *
440 * @return mixed The fully qualified view object name or FALSE if no matching view could be found.
441 * @api
442 */
443 protected function resolveViewObjectName() {
444 $vendorName = $this->request->getControllerVendorName();
445
446 if ($vendorName !== NULL) {
447 $possibleViewName = str_replace('@vendor', $vendorName, $this->namespacesViewObjectNamePattern);
448 } else {
449 $possibleViewName = $this->viewObjectNamePattern;
450 }
451
452 $extensionName = $this->request->getControllerExtensionName();
453 $possibleViewName = str_replace('@extension', $extensionName, $possibleViewName);
454 $possibleViewName = str_replace('@controller', $this->request->getControllerName(), $possibleViewName);
455 $possibleViewName = str_replace('@action', ucfirst($this->request->getControllerActionName()), $possibleViewName);
456 $format = $this->request->getFormat();
457 $viewObjectName = str_replace('@format', ucfirst($this->request->getFormat()), $possibleViewName);
458 if (class_exists($viewObjectName) === FALSE) {
459 $viewObjectName = str_replace('@format', '', $possibleViewName);
460 }
461 if (isset($this->viewFormatToObjectNameMap[$format]) && class_exists($viewObjectName) === FALSE) {
462 $viewObjectName = $this->viewFormatToObjectNameMap[$format];
463 }
464 return class_exists($viewObjectName) ? $viewObjectName : FALSE;
465 }
466
467 /**
468 * Initializes the view before invoking an action method.
469 *
470 * Override this method to solve assign variables common for all actions
471 * or prepare the view in another way before the action is called.
472 *
473 * @param ViewInterface $view The view to be initialized
474 * @return void
475 * @api
476 */
477 protected function initializeView(ViewInterface $view) {
478 }
479
480 /**
481 * Initializes the controller before invoking an action method.
482 *
483 * Override this method to solve tasks which all actions have in
484 * common.
485 *
486 * @return void
487 * @api
488 */
489 protected function initializeAction() {
490 }
491
492 /**
493 * A special action which is called if the originally intended action could
494 * not be called, for example if the arguments were not valid.
495 *
496 * The default implementation sets a flash message, request errors and forwards back
497 * to the originating action. This is suitable for most actions dealing with form input.
498 *
499 * We clear the page cache by default on an error as well, as we need to make sure the
500 * data is re-evaluated when the user changes something.
501 *
502 * @return string
503 * @api
504 */
505 protected function errorAction() {
506 $this->clearCacheOnError();
507 if ($this->configurationManager->isFeatureEnabled('rewrittenPropertyMapper')) {
508 $errorFlashMessage = $this->getErrorFlashMessage();
509 if ($errorFlashMessage !== FALSE) {
510 $errorFlashMessageObject = new \TYPO3\CMS\Core\Messaging\FlashMessage(
511 $errorFlashMessage,
512 '',
513 \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
514 );
515 $this->controllerContext->getFlashMessageQueue()->enqueue($errorFlashMessageObject);
516 }
517 $referringRequest = $this->request->getReferringRequest();
518 if ($referringRequest !== NULL) {
519 $originalRequest = clone $this->request;
520 $this->request->setOriginalRequest($originalRequest);
521 $this->request->setOriginalRequestMappingResults($this->arguments->getValidationResults());
522 $this->forward($referringRequest->getControllerActionName(), $referringRequest->getControllerName(), $referringRequest->getControllerExtensionName(), $referringRequest->getArguments());
523 }
524 $message = 'An error occurred while trying to call ' . get_class($this) . '->' . $this->actionMethodName . '().' . PHP_EOL;
525 return $message;
526 } else {
527 // @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
528 $this->request->setErrors($this->argumentsMappingResults->getErrors());
529 $errorFlashMessage = $this->getErrorFlashMessage();
530 if ($errorFlashMessage !== FALSE) {
531 $errorFlashMessageObject = new \TYPO3\CMS\Core\Messaging\FlashMessage(
532 $errorFlashMessage,
533 '',
534 \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
535 );
536 $this->controllerContext->getFlashMessageQueue()->enqueue($errorFlashMessageObject);
537 }
538 $referrer = $this->request->getInternalArgument('__referrer');
539 if ($referrer !== NULL) {
540 $this->forward($referrer['actionName'], $referrer['controllerName'], $referrer['extensionName'], $this->request->getArguments());
541 }
542 $message = 'An error occurred while trying to call ' . get_class($this) . '->' . $this->actionMethodName . '().' . PHP_EOL;
543 return $message;
544 }
545 }
546
547 /**
548 * A template method for displaying custom error flash messages, or to
549 * display no flash message at all on errors. Override this to customize
550 * the flash message in your action controller.
551 *
552 * @return string The flash message or FALSE if no flash message should be set
553 * @api
554 */
555 protected function getErrorFlashMessage() {
556 return 'An error occurred while trying to call ' . get_class($this) . '->' . $this->actionMethodName . '()';
557 }
558
559 /**
560 * Checks the request hash (HMAC), if arguments have been touched by the property mapper.
561 *
562 * In case the @dontverifyrequesthash-Annotation has been set, this suppresses the exception.
563 *
564 * @return void
565 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidOrNoRequestHashException In case request hash checking failed
566 * @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
567 */
568 protected function checkRequestHash() {
569 if ($this->configurationManager->isFeatureEnabled('rewrittenPropertyMapper')) {
570 // If the new property mapper is enabled, the request hash is not needed anymore.
571 return;
572 }
573 if (!$this->request instanceof \TYPO3\CMS\Extbase\Mvc\Web\Request) {
574 return;
575 }
576 // We only want to check it for now for web requests.
577 if ($this->request->isHmacVerified()) {
578 return;
579 }
580 // all good
581 $verificationNeeded = FALSE;
582 foreach ($this->arguments as $argument) {
583 if ($argument->getOrigin() == \TYPO3\CMS\Extbase\Mvc\Controller\Argument::ORIGIN_NEWLY_CREATED || $argument->getOrigin() == \TYPO3\CMS\Extbase\Mvc\Controller\Argument::ORIGIN_PERSISTENCE_AND_MODIFIED) {
584 $verificationNeeded = TRUE;
585 }
586 }
587 if ($verificationNeeded) {
588 $methodTagsValues = $this->reflectionService->getMethodTagsValues(get_class($this), $this->actionMethodName);
589 if (!isset($methodTagsValues['dontverifyrequesthash'])) {
590 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidOrNoRequestHashException('Request hash (HMAC) checking failed. The parameter __hmac was invalid or not set, and objects were modified.', 1255082824);
591 }
592 }
593 }
594
595 /**
596 * Clear cache of current page on error. Needed because we want a re-evaluation of the data.
597 * Better would be just do delete the cache for the error action, but that is not possible right now.
598 *
599 * @return void
600 */
601 protected function clearCacheOnError() {
602 $extbaseSettings = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
603 if (isset($extbaseSettings['persistence']['enableAutomaticCacheClearing']) && $extbaseSettings['persistence']['enableAutomaticCacheClearing'] === '1') {
604 if (isset($GLOBALS['TSFE'])) {
605 $pageUid = $GLOBALS['TSFE']->id;
606 $this->cacheService->clearPageCache(array($pageUid));
607 }
608 }
609 }
610
611 /**
612 * Returns a map of action method names and their parameters.
613 *
614 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
615 * @return array Array of method parameters by action name
616 */
617 static public function getActionMethodParameters($objectManager) {
618 $reflectionService = $objectManager->get('TYPO3\CMS\Extbase\Reflection\ReflectionService');
619
620 $result = array();
621
622 $className = get_called_class();
623 $methodNames = get_class_methods($className);
624 foreach ($methodNames as $methodName) {
625 if (strlen($methodName) > 6 && strpos($methodName, 'Action', strlen($methodName) - 6) !== FALSE) {
626 $result[$methodName] = $reflectionService->getMethodParameters($className, $methodName);
627 }
628 }
629
630 return $result;
631 }
632 }