/** * Builds a base validator conjunction for the given data type. * * The base validation rules are those which were declared directly in a class (typically * a model) through some @validate annotations on properties. * * Additionally, if a custom validator was defined for the class in question, it will be added * to the end of the conjunction. A custom validator is found if it follows the naming convention * "Replace '\Model\' by '\Validator\' and append "Validator". * * Example: $dataType is F3\Foo\Domain\Model\Quux, then the Validator will be found if it has the * name F3\Foo\Domain\Validator\QuuxValidator * * @param string $dataType The data type to build the validation conjunction for. Needs to be the fully qualified object name. * @return F3\FLOW3\Validation\Validator\ConjunctionValidator The validator conjunction or NULL * @author Robert Lemke <*****@*****.**> * @author Sebastian Kurfürst <*****@*****.**> */ protected function buildBaseValidatorConjunction($dataType) { $validatorConjunction = $this->objectManager->getObject('F3\\FLOW3\\Validation\\Validator\\ConjunctionValidator'); // Model based validator if (class_exists($dataType)) { $validatorCount = 0; $objectValidator = $this->createValidator('F3\\FLOW3\\Validation\\Validator\\GenericObjectValidator'); foreach ($this->reflectionService->getClassPropertyNames($dataType) as $classPropertyName) { $classPropertyTagsValues = $this->reflectionService->getPropertyTagsValues($dataType, $classPropertyName); if (!isset($classPropertyTagsValues['validate'])) { continue; } foreach ($classPropertyTagsValues['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 ' . $dataType . '::' . $classPropertyName . ': Could not resolve class name for validator "' . $validatorConfiguration['validatorName'] . '".', 1241098027); } $objectValidator->addPropertyValidator($classPropertyName, $newValidator); $validatorCount++; } } } if ($validatorCount > 0) { $validatorConjunction->addValidator($objectValidator); } } // Custom validator for the class $possibleValidatorClassName = str_replace('\\Model\\', '\\Validator\\', $dataType) . 'Validator'; $customValidator = $this->createValidator($possibleValidatorClassName); if ($customValidator !== NULL) { $validatorConjunction->addValidator($customValidator); } return $validatorConjunction; }
/** * 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; }