/** * Ext Direct does not provide named arguments by now, so we have * to map them by reflecting on the action parameters. * * @param RequestInterface $dispatchRequest * @param Transaction $transaction * @return array The mapped arguments */ protected function getArgumentsFromTransaction(\F3\FLOW3\MVC\RequestInterface $dispatchRequest, \F3\ExtJS\ExtDirect\Transaction $transaction) { if (!$transaction->getDirectRequest()->isFormPost()) { $controllerClass = $dispatchRequest->getControllerObjectName(); $parameters = $this->reflectionService->getMethodParameters($controllerClass, $dispatchRequest->getControllerActionName() . 'Action'); return $transaction->mapDataToParameters($parameters); } else { // TODO Reuse setArgumentsFromRawRequestData from Web/RequestBuilder } }
/** * Implementation of the arguments initilization in the action controller: * Automatically registers arguments of the current action * * Don't override this method - use initializeAction() instead. * * @return void * @author Robert Lemke <*****@*****.**> * @see initializeArguments() */ protected function initializeActionMethodArguments() { $methodParameters = $this->reflectionService->getMethodParameters(get_class($this), $this->actionMethodName); foreach ($methodParameters as $parameterName => $parameterInfo) { $dataType = NULL; if (isset($parameterInfo['type'])) { $dataType = $parameterInfo['type']; } elseif ($parameterInfo['array']) { $dataType = 'array'; } if ($dataType === NULL) { throw new \F3\FLOW3\MVC\Exception\InvalidArgumentTypeException('The argument type for parameter $' . $parameterName . ' of method ' . get_class($this) . '->' . $this->actionMethodName . '() could not be detected.', 1253175643); } $defaultValue = isset($parameterInfo['defaultValue']) ? $parameterInfo['defaultValue'] : NULL; $this->arguments->addNewArgument($parameterName, $dataType, $parameterInfo['optional'] === FALSE, $defaultValue); } }
/** * Detects and registers any validators for arguments: * - by the data type specified in the @param annotations * - additional validators specified in the @validate annotations of a method * * @param string $className * @param string $methodName * @return array An Array of ValidatorConjunctions for each method parameters. * @author Robert Lemke <*****@*****.**> * @author Sebastian Kurfürst <*****@*****.**> */ public function buildMethodArgumentsValidatorConjunctions($className, $methodName) { $validatorConjunctions = array(); $methodParameters = $this->reflectionService->getMethodParameters($className, $methodName); if (!count($methodParameters)) { // early return in case no parameters were found. return $validatorConjunctions; } foreach ($methodParameters as $parameterName => $methodParameter) { $validatorConjunction = $this->createValidator('F3\\FLOW3\\Validation\\Validator\\ConjunctionValidator'); if (strpos($methodParameter['type'], '\\') === FALSE) { $typeValidator = $this->createValidator($methodParameter['type']); } elseif (strpos($methodParameter['type'], '\\Model\\') !== FALSE) { $possibleValidatorClassName = str_replace('\\Model\\', '\\Validator\\', $methodParameter['type']) . 'Validator'; $typeValidator = $this->createValidator($possibleValidatorClassName); } else { $typeValidator = NULL; } if ($typeValidator !== NULL) { $validatorConjunction->addValidator($typeValidator); } $validatorConjunctions[$parameterName] = $validatorConjunction; } $methodTagsValues = $this->reflectionService->getMethodTagsValues($className, $methodName); if (isset($methodTagsValues['validate'])) { foreach ($methodTagsValues['validate'] as $validateValue) { $parsedAnnotation = $this->parseValidatorAnnotation($validateValue); foreach ($parsedAnnotation['validators'] as $validatorConfiguration) { $newValidator = $this->createValidator($validatorConfiguration['validatorName'], $validatorConfiguration['validatorOptions']); if ($newValidator === NULL) { throw new \F3\FLOW3\Validation\Exception\NoSuchValidatorException('Invalid validate annotation in ' . $className . '->' . $methodName . '(): Could not resolve class name for validator "' . $validatorConfiguration['validatorName'] . '".', 1239853109); } if (isset($validatorConjunctions[$parsedAnnotation['argumentName']])) { $validatorConjunctions[$parsedAnnotation['argumentName']]->addValidator($newValidator); } else { throw new \F3\FLOW3\Validation\Exception\InvalidValidationConfigurationException('Invalid validate annotation in ' . $className . '->' . $methodName . '(): Validator specified for argument name "' . $parsedAnnotation['argumentName'] . '", but this argument does not exist.', 1253172726); } } } } return $validatorConjunctions; }
/** * Maps the given properties to the target object WITHOUT VALIDATING THE RESULT. * If the properties could be set, this method returns TRUE, otherwise FALSE. * Returning TRUE does not mean that the target object is valid and secure! * * Only use this method if you're sure that you don't need validation! * * @param array $propertyNames Names of the properties to map. * @param mixed $source Source containing the properties to map to the target object. Must either be an array, ArrayObject or any other object. * @param object $target The target object * @param array $optionalPropertyNames Names of optional properties. If a property is specified here and it doesn't exist in the source, no error is issued. * @return boolean TRUE if the properties could be mapped, otherwise FALSE * @see mapAndValidate() * @author Robert Lemke <*****@*****.**> * @api */ public function map(array $propertyNames, $source, &$target, $optionalPropertyNames = array()) { if (!is_object($source) && !is_array($source)) { throw new \F3\FLOW3\Property\Exception\InvalidSourceException('The source object must be a valid object or array, ' . gettype($target) . ' given.', 1187807099); } if (is_string($target) && strpos($target, '\\') !== FALSE) { return $this->transformToObject($source, $target, '--none--'); } $this->mappingResults = $this->objectManager->getObject('F3\\FLOW3\\Property\\MappingResults'); if (!is_object($target) && !is_array($target)) { throw new \F3\FLOW3\Property\Exception\InvalidTargetException('The target must be a valid object, class name or array, ' . gettype($target) . ' given.', 1187807099); } if (is_object($target)) { $targetClassSchema = $this->reflectionService->getClassSchema($target); } else { $targetClassSchema = NULL; } foreach ($propertyNames as $propertyName) { $propertyValue = NULL; if (is_array($source) || $source instanceof \ArrayAccess) { if (isset($source[$propertyName])) { $propertyValue = $source[$propertyName]; } } elseif (\F3\FLOW3\Reflection\ObjectAccess::isPropertyGettable($source, $propertyName)) { $propertyValue = \F3\FLOW3\Reflection\ObjectAccess::getProperty($source, $propertyName); } if ($propertyValue === NULL && !in_array($propertyName, $optionalPropertyNames)) { $this->mappingResults->addError($this->objectManager->getObject('F3\\FLOW3\\Error\\Error', "Required property '{$propertyName}' does not exist in source.", 1236785359), $propertyName); } else { if (method_exists($target, \F3\FLOW3\Reflection\ObjectAccess::buildSetterMethodName($propertyName)) && is_callable(array($target, \F3\FLOW3\Reflection\ObjectAccess::buildSetterMethodName($propertyName)))) { $targetClassName = $target instanceof \F3\FLOW3\AOP\ProxyInterface ? $target->FLOW3_AOP_Proxy_getProxyTargetClassName() : get_class($target); $methodParameters = $this->reflectionService->getMethodParameters($targetClassName, \F3\FLOW3\Reflection\ObjectAccess::buildSetterMethodName($propertyName)); $methodParameter = current($methodParameters); $targetPropertyType = \F3\FLOW3\Utility\TypeHandling::parseType($methodParameter['type']); } elseif ($targetClassSchema !== NULL && $targetClassSchema->hasProperty($propertyName)) { $targetPropertyType = $targetClassSchema->getProperty($propertyName); } elseif ($targetClassSchema !== NULL) { $this->mappingResults->addError($this->objectManager->getObject('F3\\FLOW3\\Error\\Error', "Property '{$propertyName}' does not exist in target class schema.", 1251813614), $propertyName); continue; } if (isset($targetPropertyType)) { if (in_array($targetPropertyType['type'], array('array', 'ArrayObject', 'SplObjectStorage')) && strpos($targetPropertyType['elementType'], '\\') !== FALSE) { $objects = array(); foreach ($propertyValue as $value) { $objects[] = $this->transformToObject($value, $targetPropertyType['elementType'], $propertyName); } if ($targetPropertyType['type'] === 'ArrayObject') { $propertyValue = new \ArrayObject($objects); } elseif ($targetPropertyType['type'] === 'SplObjectStorage') { $propertyValue = new \SplObjectStorage(); foreach ($objects as $object) { $propertyValue->attach($object); } } else { $propertyValue = $objects; } } elseif (strpos($targetPropertyType['type'], '\\') !== FALSE) { $propertyValue = $this->transformToObject($propertyValue, $targetPropertyType['type'], $propertyName); } } if (is_array($target)) { $target[$propertyName] = $propertyValue; } elseif (\F3\FLOW3\Reflection\ObjectAccess::setProperty($target, $propertyName, $propertyValue) === FALSE) { $this->mappingResults->addError($this->objectManager->getObject('F3\\FLOW3\\Error\\Error', "Property '{$propertyName}' could not be set.", 1236783102), $propertyName); } } } return !$this->mappingResults->hasErrors(); }