/** * Will return one pointcut which does specifically only match the joinpoints of the structure * which this docblock belongs to * * @param string $docBlock The DocBlock to search in * @param string $targetType Type of the target any resulting joinpoints have, e.g. Joinpoint::TARGET_METHOD * @param string $targetName Name of the target any resulting joinpoints have * * @return \AppserverIo\Doppelgaenger\Entities\Lists\PointcutExpressionList */ public function getPointcutExpressions($docBlock, $targetType, $targetName) { $pointcutExpressions = new PointcutExpressionList(); // get our tokenizer and parse the doc Block $tokenizer = new Tokenizer(); $tokenizer->ignore(array('param', 'return', 'throws')); $tokens = new Tokens($tokenizer->parse($docBlock)); // convert to array and run it through our advice factory $toArray = new ToArray(); $annotations = $toArray->convert($tokens); // create the entities for the join-points and advices the pointcut describes foreach ($annotations as $annotation) { // filter out the annotations which are no proper join-points if (!class_exists('\\AppserverIo\\Psr\\MetaobjectProtocol\\Aop\\Annotations\\Advices\\' . $annotation->name)) { continue; } // build the join-point $joinpoint = new Joinpoint(); $joinpoint->setTarget($targetType); $joinpoint->setCodeHook($annotation->name); $joinpoint->setStructure($this->currentDefinition->getQualifiedName()); $joinpoint->setTargetName($targetName); // build the pointcut(s) foreach ($annotation->values as $rawAdvice) { // as it might be an array we have to sanitize it first if (!is_array($rawAdvice)) { $rawAdvice = array($rawAdvice); } foreach ($rawAdvice as $adviceString) { // create the pointcut $pointcutExpression = new PointcutExpression($adviceString); $pointcutExpression->setJoinpoint($joinpoint); $pointcutExpressions->add($pointcutExpression); } } } return $pointcutExpressions; }
/** * Will look at all advices known to the aspect register and filter out pointcut expressions matching the * function in question * Will return a list of pointcut expressions including distinctive pointcuts to weave in the associated advices * * @param FunctionDefinition $functionDefinition Definition of the function to match known advices against * * @return \AppserverIo\Doppelgaenger\Entities\Lists\PointcutExpressionList */ protected function findAdvicePointcutExpressions(FunctionDefinition $functionDefinition) { // we have to search for all advices, all of their pointcuts and all pointcut expressions those reference $pointcutExpressions = new PointcutExpressionList(); foreach ($this->aspectRegister as $aspect) { foreach ($aspect->getAdvices() as $advice) { foreach ($advice->getPointcuts() as $pointcut) { // there should be no other pointcuts than those referencing pointcut definitions if (!$pointcut instanceof PointcutPointcut) { continue; } foreach ($pointcut->getReferencedPointcuts() as $referencedPointcut) { if ($referencedPointcut->getPointcutExpression()->getPointcut()->matches($functionDefinition)) { // we found a pointcut of an advice that matches! // lets create a distinctive join-point and add the advice weaving to the pointcut. // Make a clone so that there are no weird reference shenanigans $pointcutExpression = clone $referencedPointcut->getPointcutExpression(); $joinpoint = new Joinpoint(); $joinpoint->setCodeHook($advice->getCodeHook()); $joinpoint->setStructure($functionDefinition->getStructureName()); $joinpoint->setTarget(Joinpoint::TARGET_METHOD); $joinpoint->setTargetName($functionDefinition->getName()); $pointcutExpression->setJoinpoint($joinpoint); // "straighten out" structure and function referenced by the pointcut to avoid regex within generated code. // Same here with the cloning: we do not want to influence the matching process with working on references $expressionPointcut = clone $pointcutExpression->getPointcut(); $expressionPointcut->straightenExpression($functionDefinition); // add the weaving pointcut into the expression $pointcutExpression->setPointcut(new AndPointcut(AdvisePointcut::TYPE . str_replace('\\\\', '\\', '(\\' . $advice->getQualifiedName() . ')'), $expressionPointcut->getType() . '(' . $expressionPointcut->getExpression() . ')')); $pointcutExpression->setString($expressionPointcut->getExpression()); // add it to our result list $pointcutExpressions->add($pointcutExpression); // break here as we only need one, they are implicitly "or" combined break; } } } } } return $pointcutExpressions; }