public function secureActionArguments($arguments, $request, $controllerClassName) { // look for @modificationAllowed and @creationAllowed annotations on action methods $actionMethodName = $request->getControllerActionName() . 'Action'; $tags = $this->reflectionService->getMethodTagsValues($controllerClassName, $actionMethodName); if (array_key_exists('modificationAllowed', $tags)) { $modificationAllowed = $tags['modificationAllowed']; } else { $modificationAllowed = array(); } if (array_key_exists('creationAllowed', $tags)) { $creationAllowed = $tags['creationAllowed']; } else { $creationAllowed = array(); } // modification and creation are disabled by default on all arguments foreach ($arguments->getArgumentNames() as $argumentName) { $conf = $arguments[$argumentName]->getPropertyMappingConfiguration(); $options = array(); $key = \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED; if (!in_array($argumentName, $modificationAllowed)) { $options[$key] = false; } else { $options[$key] = true; } $key = \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED; if (!in_array($argumentName, $creationAllowed)) { $options[$key] = false; } else { $options[$key] = true; } // set sane defaults #$conf->setTypeConverterOptions('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', $options); } }
/** * Checks the request hash (HMAC), if arguments have been touched by the property mapper. * * In case the @dontverifyrequesthash-Annotation has been set, this suppresses the exception. * * @return void * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidOrNoRequestHashException In case request hash checking failed * @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1 */ protected function checkRequestHash() { if ($this->configurationManager->isFeatureEnabled('rewrittenPropertyMapper')) { // If the new property mapper is enabled, the request hash is not needed anymore. return; } if (!$this->request instanceof \TYPO3\CMS\Extbase\Mvc\Web\Request) { return; } // We only want to check it for now for web requests. if ($this->request->isHmacVerified()) { return; } // all good $verificationNeeded = FALSE; foreach ($this->arguments as $argument) { if ($argument->getOrigin() == \TYPO3\CMS\Extbase\Mvc\Controller\Argument::ORIGIN_NEWLY_CREATED || $argument->getOrigin() == \TYPO3\CMS\Extbase\Mvc\Controller\Argument::ORIGIN_PERSISTENCE_AND_MODIFIED) { $verificationNeeded = TRUE; } } if ($verificationNeeded) { $methodTagsValues = $this->reflectionService->getMethodTagsValues(get_class($this), $this->actionMethodName); if (!isset($methodTagsValues['dontverifyrequesthash'])) { 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); } } }
/** * Register method arguments for "render" by analysing the doc comment above. * * @return void * @throws \TYPO3Fluid\Fluid\Core\Parser\Exception */ protected function registerRenderMethodArguments() { $methodParameters = $this->reflectionService->getMethodParameters(get_class($this), 'render'); if (count($methodParameters) === 0) { return; } $methodTags = $this->reflectionService->getMethodTagsValues(get_class($this), 'render'); $paramAnnotations = array(); if (isset($methodTags['param'])) { $paramAnnotations = $methodTags['param']; } $i = 0; foreach ($methodParameters as $parameterName => $parameterInfo) { $dataType = null; if (isset($parameterInfo['type'])) { $dataType = isset($parameterInfo['array']) && (bool) $parameterInfo['array'] ? 'array' : $parameterInfo['type']; } else { throw new \TYPO3\CMS\Fluid\Core\Exception('Could not determine type of argument "' . $parameterName . '" of the render-method in ViewHelper "' . get_class($this) . '". Either the methods docComment is invalid or some PHP optimizer strips off comments.', 1242292003); } $description = ''; if (isset($paramAnnotations[$i])) { $explodedAnnotation = explode(' ', $paramAnnotations[$i]); array_shift($explodedAnnotation); array_shift($explodedAnnotation); $description = implode(' ', $explodedAnnotation); } $defaultValue = null; if (isset($parameterInfo['defaultValue'])) { $defaultValue = $parameterInfo['defaultValue']; } $this->argumentDefinitions[$parameterName] = new ArgumentDefinition($parameterName, $dataType, $description, $parameterInfo['optional'] === false, $defaultValue, true); $i++; } }
/** * @param $model * @return \stdClass */ public function transform($model) { if ($model instanceof \Traversable) { $out = array(); foreach ($model as $subModel) { $out[] = $this->transform($subModel); } return $out; } else { if ($model instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) { $transformedObject = new \stdClass(); $properties = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getGettablePropertyNames($model); $class = get_class($model); foreach ($properties as $property) { $getMethodName = 'get' . ucfirst($property); $methodTags = $this->reflectionService->getMethodTagsValues($class, $getMethodName); // The Goal here is to be able to expose properties and methods with the JSONExpose annotation. if ($property == 'uid' || array_key_exists('JSONExpose', $methodTags) || $this->reflectionService->isPropertyTaggedWith($class, $property, 'JSONExpose')) { $value = $model->{$getMethodName}(); // TODO, not sure about this check for lazy loading. Would be good to write a test for it. if ($value instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy) { $transformedObject->{$property} = 'lazy'; } elseif ($this->typeHandlingService->isSimpleType(gettype($value))) { $transformedObject->{$property} = $value; } elseif (is_object($value)) { if ($value instanceof \TYPO3\CMS\Extbase\Persistence\ObjectStorage) { $transformedObject->{$property} = $this->transform($value); } else { $transformedObject->{$property} = get_class($value); } } } } return $transformedObject; } else { return NULL; } } }
/** * Temporary replacement for $this->reflectionService->getMethodAnnotations() * * @param string $className * @param string $methodName * * @return array */ public function getMethodValidateAnnotations($className, $methodName) { $validateAnnotations = array(); $methodTagsValues = $this->reflectionService->getMethodTagsValues($className, $methodName); if (isset($methodTagsValues['validate']) && is_array($methodTagsValues['validate'])) { foreach ($methodTagsValues['validate'] as $validateValue) { $parsedAnnotations = $this->parseValidatorAnnotation($validateValue); foreach ($parsedAnnotations['validators'] as $validator) { array_push($validateAnnotations, array('argumentName' => $parsedAnnotations['argumentName'], 'validatorName' => $validator['validatorName'], 'validatorOptions' => $validator['validatorOptions'])); } } } return $validateAnnotations; }
/** * Gets the data type required for the argument value * * @param \TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition $argument */ protected function getArgumentType(\TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition $argument) { $command = $this->commandManager->getCommandByIdentifier($this->task->getCommandIdentifier()); $controllerClassName = $command->getControllerClassName(); $methodName = $command->getControllerCommandName() . 'Command'; $tags = $this->reflectionService->getMethodTagsValues($controllerClassName, $methodName); foreach ($tags['param'] as $tag) { list($argumentType, $argumentVariableName) = explode(' ', $tag); if (substr($argumentVariableName, 1) == $argument->getName()) { return $argumentType; } } return NULL; }
/** * Calls the specified action method and passes the arguments. * * If the action returns a string, it is appended to the content in the * response object. If the action doesn't return anything and a valid * view exists, the view is rendered automatically. * * @return void * @api */ protected function callActionMethod() { $preparedArguments = array(); /** @var \TYPO3\CMS\Extbase\Mvc\Controller\Argument $argument */ foreach ($this->arguments as $argument) { $preparedArguments[] = $argument->getValue(); } $validationResult = $this->arguments->getValidationResults(); if (!$validationResult->hasErrors()) { $this->emitBeforeCallActionMethodSignal($preparedArguments); $actionResult = call_user_func_array(array($this, $this->actionMethodName), $preparedArguments); } else { $methodTagsValues = $this->reflectionService->getMethodTagsValues(get_class($this), $this->actionMethodName); $ignoreValidationAnnotations = array(); if (isset($methodTagsValues['ignorevalidation'])) { $ignoreValidationAnnotations = $methodTagsValues['ignorevalidation']; } // if there exist errors which are not ignored with @ignorevalidation => call error method // else => call action method $shouldCallActionMethod = true; foreach ($validationResult->getSubResults() as $argumentName => $subValidationResult) { if (!$subValidationResult->hasErrors()) { continue; } if (array_search('$' . $argumentName, $ignoreValidationAnnotations) !== false) { continue; } $shouldCallActionMethod = false; break; } if ($shouldCallActionMethod) { $this->emitBeforeCallActionMethodSignal($preparedArguments); $actionResult = call_user_func_array(array($this, $this->actionMethodName), $preparedArguments); } else { $actionResult = call_user_func(array($this, $this->errorMethodName)); } } if ($actionResult === null && $this->view instanceof ViewInterface) { $this->response->appendContent($this->view->render()); } elseif (is_string($actionResult) && $actionResult !== '') { $this->response->appendContent($actionResult); } elseif (is_object($actionResult) && method_exists($actionResult, '__toString')) { $this->response->appendContent((string) $actionResult); } }
/** * @test */ public function getMethodTagsValues() { $service = new ReflectionService(); $tagsValues = $service->getMethodTagsValues(get_class($this), 'fixtureMethodForMethodTagsValues'); $this->assertEquals(array('param' => array('array $foo The foo parameter'), 'return' => array('void')), $tagsValues); }
/** * Register method arguments for "render" by analysing the doc comment above. * * @return void * @throws \TYPO3\CMS\Fluid\Core\Parser\Exception */ private function registerRenderMethodArguments() { $methodParameters = $this->reflectionService->getMethodParameters(get_class($this), 'render'); if (count($methodParameters) === 0) { return; } if (\TYPO3\CMS\Fluid\Fluid::$debugMode) { $methodTags = $this->reflectionService->getMethodTagsValues(get_class($this), 'render'); $paramAnnotations = array(); if (isset($methodTags['param'])) { $paramAnnotations = $methodTags['param']; } } $i = 0; foreach ($methodParameters as $parameterName => $parameterInfo) { $dataType = NULL; if (isset($parameterInfo['type'])) { $dataType = $parameterInfo['type']; } elseif ($parameterInfo['array']) { $dataType = 'array'; } if ($dataType === NULL) { throw new \TYPO3\CMS\Fluid\Core\Parser\Exception('could not determine type of argument "' . $parameterName . '" of the render-method in ViewHelper "' . get_class($this) . '". Either the methods docComment is invalid or some PHP optimizer strips off comments.', 1242292003); } $description = ''; if (\TYPO3\CMS\Fluid\Fluid::$debugMode && isset($paramAnnotations[$i])) { $explodedAnnotation = explode(' ', $paramAnnotations[$i]); array_shift($explodedAnnotation); array_shift($explodedAnnotation); $description = implode(' ', $explodedAnnotation); } $defaultValue = NULL; if (isset($parameterInfo['defaultValue'])) { $defaultValue = $parameterInfo['defaultValue']; } $this->argumentDefinitions[$parameterName] = new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition($parameterName, $dataType, $description, $parameterInfo['optional'] === FALSE, $defaultValue, TRUE); $i++; } }