/** * Checks if the specified method matches against the method name * expression. * * Returns TRUE if method name, visibility and arguments constraints match and the target * method is not final. * * @param string $className Ignored in this pointcut filter * @param string $methodName Name of the method to match against * @param string $methodDeclaringClassName Name of the class the method was originally declared in * @param mixed $pointcutQueryIdentifier Some identifier for this query - must at least differ from a previous identifier. Used for circular reference detection. * @return boolean TRUE if the class matches, otherwise FALSE * @throws \TYPO3\FLOW3\Aop\Exception */ public function matches($className, $methodName, $methodDeclaringClassName, $pointcutQueryIdentifier) { $matchResult = preg_match('/^' . $this->methodNameFilterExpression . '$/', $methodName); if ($matchResult === FALSE) { throw new \TYPO3\FLOW3\Aop\Exception('Error in regular expression', 1168876915); } elseif ($matchResult !== 1) { return FALSE; } switch ($this->methodVisibility) { case 'public': if (!($methodDeclaringClassName !== NULL && $this->reflectionService->isMethodPublic($methodDeclaringClassName, $methodName))) { return FALSE; } break; case 'protected': if (!($methodDeclaringClassName !== NULL && $this->reflectionService->isMethodProtected($methodDeclaringClassName, $methodName))) { return FALSE; } break; } if ($methodDeclaringClassName !== NULL && $this->reflectionService->isMethodFinal($methodDeclaringClassName, $methodName)) { return FALSE; } $methodArguments = $methodDeclaringClassName === NULL ? array() : $this->reflectionService->getMethodParameters($methodDeclaringClassName, $methodName); foreach (array_keys($this->methodArgumentConstraints) as $argumentName) { $objectAccess = explode('.', $argumentName, 2); $argumentName = $objectAccess[0]; if (!array_key_exists($argumentName, $methodArguments)) { $this->systemLogger->log('The argument "' . $argumentName . '" declared in pointcut does not exist in method ' . $methodDeclaringClassName . '->' . $methodName, LOG_NOTICE); return FALSE; } } return TRUE; }
/** * Traverses all aspect containers, their aspects and their advisors and adds the * methods and their advices to the (usually empty) array of intercepted methods. * * @param array &$interceptedMethods An array (empty or not) which contains the names of the intercepted methods and additional information * @param array $methods An array of class and method names which are matched against the pointcut (class name = name of the class or interface the method was declared) * @param string $targetClassName Name of the class the pointcut should match with * @param array &$aspectContainers All aspects to take into consideration * @return void */ protected function addAdvicedMethodsToInterceptedMethods(array &$interceptedMethods, array $methods, $targetClassName, array &$aspectContainers) { $pointcutQueryIdentifier = 0; foreach ($aspectContainers as $aspectContainer) { if (!$aspectContainer->getCachedTargetClassNameCandidates()->hasClassName($targetClassName)) { continue; } foreach ($aspectContainer->getAdvisors() as $advisor) { $pointcut = $advisor->getPointcut(); foreach ($methods as $method) { list($methodDeclaringClassName, $methodName) = $method; if ($this->reflectionService->isMethodFinal($targetClassName, $methodName)) { continue; } if ($pointcut->matches($targetClassName, $methodName, $methodDeclaringClassName, $pointcutQueryIdentifier)) { $advice = $advisor->getAdvice(); $interceptedMethods[$methodName]['groupedAdvices'][get_class($advice)][] = array('advice' => $advice, 'runtimeEvaluationsClosureCode' => $pointcut->getRuntimeEvaluationsClosureCode()); $interceptedMethods[$methodName]['declaringClassName'] = $methodDeclaringClassName; } $pointcutQueryIdentifier++; } } } }