/** * Adds the needed valiators to the Arguments: * - Validators checking the data type from the @param annotation * - Custom validators specified with @validate. * * In case @dontvalidate is NOT set for an argument, the following two * validators are also added: * - Model-based validators (@validate annotations in the model) * - Custom model validator classes * * @return void * @author Sebastian Kurfürst <*****@*****.**> */ protected function initializeActionMethodValidators() { $parameterValidators = $this->validatorResolver->buildMethodArgumentsValidatorConjunctions(get_class($this), $this->actionMethodName); $dontValidateAnnotations = array(); $methodTagsValues = $this->reflectionService->getMethodTagsValues(get_class($this), $this->actionMethodName); if (isset($methodTagsValues['dontvalidate'])) { $dontValidateAnnotations = $methodTagsValues['dontvalidate']; } foreach ($this->arguments as $argument) { $validator = $parameterValidators[$argument->getName()]; if (array_search('$' . $argument->getName(), $dontValidateAnnotations) === FALSE) { $baseValidatorConjunction = $this->validatorResolver->getBaseValidatorConjunction($argument->getDataType()); if ($baseValidatorConjunction !== NULL) { $validator->addValidator($baseValidatorConjunction); } } $argument->setValidator($validator); } }
/** * 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; }
/** * Creates and returns an aspect from the annotations found in a class which * is tagged as an aspect. The object acting as an advice will already be * fetched (and therefore instantiated if neccessary). * * @param string $aspectClassName Name of the class which forms the aspect, contains advices etc. * @return mixed The aspect container containing one or more advisors or FALSE if no container could be built * @author Robert Lemke <*****@*****.**> */ protected function buildAspectContainer($aspectClassName) { if (!$this->reflectionService->isClassReflected($aspectClassName)) { return FALSE; } if (!$this->reflectionService->isClassTaggedWith($aspectClassName, 'aspect')) { return FALSE; } $aspectContainer = new \F3\FLOW3\AOP\AspectContainer($aspectClassName); foreach ($this->reflectionService->getClassMethodNames($aspectClassName) as $methodName) { foreach ($this->reflectionService->getMethodTagsValues($aspectClassName, $methodName) as $tagName => $tagValues) { foreach ($tagValues as $tagValue) { switch ($tagName) { case 'around': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue); $advice = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advice\\AroundAdvice', $aspectClassName, $methodName); $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName); $advisor = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advisor', $advice, $pointcut); $aspectContainer->addAdvisor($advisor); break; case 'before': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue); $advice = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advice\\BeforeAdvice', $aspectClassName, $methodName); $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName); $advisor = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advisor', $advice, $pointcut); $aspectContainer->addAdvisor($advisor); break; case 'afterreturning': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue); $advice = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advice\\AfterReturningAdvice', $aspectClassName, $methodName); $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName); $advisor = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advisor', $advice, $pointcut); $aspectContainer->addAdvisor($advisor); break; case 'afterthrowing': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue); $advice = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advice\\AfterThrowingAdvice', $aspectClassName, $methodName); $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName); $advisor = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advisor', $advice, $pointcut); $aspectContainer->addAdvisor($advisor); break; case 'after': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue); $advice = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advice\\AfterAdvice', $aspectClassName, $methodName); $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName); $advisor = $this->objectFactory->create('F3\\FLOW3\\AOP\\Advisor', $advice, $pointcut); $aspectContainer->addAdvisor($advisor); break; case 'pointcut': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($tagValue); $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $tagValue, $pointcutFilterComposite, $aspectClassName, $methodName); $aspectContainer->addPointcut($pointcut); break; } } } } foreach ($this->reflectionService->getClassPropertyNames($aspectClassName) as $propertyName) { foreach ($this->reflectionService->getPropertyTagsValues($aspectClassName, $propertyName) as $tagName => $tagValues) { foreach ($tagValues as $tagValue) { switch ($tagName) { case 'introduce': $splittedTagValue = explode(',', $tagValue); if (!is_array($splittedTagValue) || count($splittedTagValue) != 2) { throw new \F3\FLOW3\AOP\Exception('The introduction in class "' . $aspectClassName . '" does not contain the two required parameters.', 1172694761); } $pointcutExpression = trim($splittedTagValue[1]); $pointcutFilterComposite = $this->pointcutExpressionParser->parse($pointcutExpression); $pointcut = $this->objectFactory->create('F3\\FLOW3\\AOP\\Pointcut\\Pointcut', $pointcutExpression, $pointcutFilterComposite, $aspectClassName); $interfaceName = trim($splittedTagValue[0]); $introduction = $this->objectFactory->create('F3\\FLOW3\\AOP\\Introduction', $aspectClassName, $interfaceName, $pointcut); $aspectContainer->addIntroduction($introduction); break; } } } } if (count($aspectContainer->getAdvisors()) < 1 && count($aspectContainer->getPointcuts()) < 1 && count($aspectContainer->getIntroductions()) < 1) { throw new \F3\FLOW3\AOP\Exception('The class "' . $aspectClassName . '" is tagged to be an aspect but doesn\'t contain advices nor pointcut or introduction declarations.', 1169124534); } return $aspectContainer; }