/**
* 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 necessary).
*
* @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
* @throws Aop\Exception
*/
protected function buildAspectContainer($aspectClassName)
{
$aspectContainer = new AspectContainer($aspectClassName);
$methodNames = get_class_methods($aspectClassName);
foreach ($methodNames as $methodName) {
foreach ($this->reflectionService->getMethodAnnotations($aspectClassName, $methodName) as $annotation) {
$annotationClass = get_class($annotation);
switch ($annotationClass) {
case Flow\Around::class:
$pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass));
$advice = new Aop\Advice\AroundAdvice($aspectClassName, $methodName);
$pointcut = new Aop\Pointcut\Pointcut($annotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName);
$advisor = new Aop\Advisor($advice, $pointcut);
$aspectContainer->addAdvisor($advisor);
break;
case Flow\Before::class:
$pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass));
$advice = new Aop\Advice\BeforeAdvice($aspectClassName, $methodName);
$pointcut = new Aop\Pointcut\Pointcut($annotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName);
$advisor = new Aop\Advisor($advice, $pointcut);
$aspectContainer->addAdvisor($advisor);
break;
case Flow\AfterReturning::class:
$pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass));
$advice = new Aop\Advice\AfterReturningAdvice($aspectClassName, $methodName);
$pointcut = new Aop\Pointcut\Pointcut($annotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName);
$advisor = new Aop\Advisor($advice, $pointcut);
$aspectContainer->addAdvisor($advisor);
break;
case Flow\AfterThrowing::class:
$pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass));
$advice = new Aop\Advice\AfterThrowingAdvice($aspectClassName, $methodName);
$pointcut = new Aop\Pointcut\Pointcut($annotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName);
$advisor = new Aop\Advisor($advice, $pointcut);
$aspectContainer->addAdvisor($advisor);
break;
case Flow\After::class:
$pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass));
$advice = new Aop\Advice\AfterAdvice($aspectClassName, $methodName);
$pointcut = new Aop\Pointcut\Pointcut($annotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName);
$advisor = new Aop\Advisor($advice, $pointcut);
$aspectContainer->addAdvisor($advisor);
break;
case Flow\Pointcut::class:
$pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->expression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass));
$pointcut = new Aop\Pointcut\Pointcut($annotation->expression, $pointcutFilterComposite, $aspectClassName, $methodName);
$aspectContainer->addPointcut($pointcut);
break;
}
}
}
$introduceAnnotation = $this->reflectionService->getClassAnnotation($aspectClassName, Flow\Introduce::class);
if ($introduceAnnotation !== null) {
if ($introduceAnnotation->interfaceName === null && $introduceAnnotation->traitName === null) {
throw new Aop\Exception('The introduction in class "' . $aspectClassName . '" does neither contain an interface name nor a trait name, at least one is required.', 1172694761);
}
$pointcutFilterComposite = $this->pointcutExpressionParser->parse($introduceAnnotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $introduceAnnotation->interfaceName, Flow\Introduce::class));
$pointcut = new Aop\Pointcut\Pointcut($introduceAnnotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName);
if ($introduceAnnotation->interfaceName !== null) {
$introduction = new Aop\InterfaceIntroduction($aspectClassName, $introduceAnnotation->interfaceName, $pointcut);
$aspectContainer->addInterfaceIntroduction($introduction);
}
if ($introduceAnnotation->traitName !== null) {
$introduction = new TraitIntroduction($aspectClassName, $introduceAnnotation->traitName, $pointcut);
$aspectContainer->addTraitIntroduction($introduction);
}
}
foreach ($this->reflectionService->getClassPropertyNames($aspectClassName) as $propertyName) {
$introduceAnnotation = $this->reflectionService->getPropertyAnnotation($aspectClassName, $propertyName, Flow\Introduce::class);
if ($introduceAnnotation !== null) {
$pointcutFilterComposite = $this->pointcutExpressionParser->parse($introduceAnnotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $propertyName, Flow\Introduce::class));
$pointcut = new Aop\Pointcut\Pointcut($introduceAnnotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName);
$introduction = new PropertyIntroduction($aspectClassName, $propertyName, $pointcut);
$aspectContainer->addPropertyIntroduction($introduction);
}
}
if (count($aspectContainer->getAdvisors()) < 1 && count($aspectContainer->getPointcuts()) < 1 && count($aspectContainer->getInterfaceIntroductions()) < 1 && count($aspectContainer->getTraitIntroductions()) < 1 && count($aspectContainer->getPropertyIntroductions()) < 1) {
throw new Aop\Exception('The class "' . $aspectClassName . '" is tagged to be an aspect but doesn\'t contain advices nor pointcut or introduction declarations.', 1169124534);
}
return $aspectContainer;
}