/** * Builds a single AOP proxy class for the specified class. * * @param string $targetClassName Name of the class to create a proxy class file for * @param array $aspectContainers The array of aspect containers from the AOP Framework * @param string $context The current application context * @return mixed An array containing the proxy class name and its source code if a proxy class has been built, otherwise FALSE * @author Robert Lemke <*****@*****.**> * @author Karsten Dambekalns <*****@*****.**> */ public function buildProxyClass($targetClassName, array $aspectContainers, $context) { if ($this->reflectionService->isClassImplementationOf($targetClassName, 'F3\\FLOW3\\AOP\\ProxyInterface')) { throw new \F3\FLOW3\AOP\Exception\InvalidTargetClassException('Cannot proxy class "' . $targetClassName . '" because it is already an AOP proxy class.', 1238858632); } $introductions = $this->getMatchingIntroductions($aspectContainers, $targetClassName); $introducedInterfaces = $this->getInterfaceNamesFromIntroductions($introductions); $methodsFromTargetClass = $this->getMethodsFromTargetClass($targetClassName); $methodsFromIntroducedInterfaces = $this->getIntroducedMethodsFromIntroductions($introductions, $targetClassName); $interceptedMethods = array(); $this->addAdvicedMethodsToInterceptedMethods($interceptedMethods, array_merge($methodsFromTargetClass, $methodsFromIntroducedInterfaces), $targetClassName, $aspectContainers); $this->addIntroducedMethodsToInterceptedMethods($interceptedMethods, $methodsFromIntroducedInterfaces); if (count($interceptedMethods) < 1 && count($introducedInterfaces) < 1) { return FALSE; } $this->addConstructorToInterceptedMethods($interceptedMethods, $targetClassName); $proxyClassName = $this->renderProxyClassName($targetClassName, $context); $proxyNamespace = $this->getProxyNamespace($targetClassName); $advicedMethodsInformation = $this->getAdvicedMethodsInformation($interceptedMethods); $proxyClassTokens = array('CLASS_ANNOTATIONS' => $this->buildClassAnnotationsCode($targetClassName), 'PROXY_NAMESPACE' => $proxyNamespace, 'PROXY_CLASS_NAME' => $proxyClassName, 'TARGET_CLASS_NAME' => $targetClassName, 'INTRODUCED_INTERFACES' => $this->buildIntroducedInterfacesCode($introducedInterfaces), 'METHODS_AND_ADVICES_ARRAY_CODE' => $this->buildMethodsAndAdvicesArrayCode($interceptedMethods), 'METHODS_INTERCEPTOR_CODE' => $this->buildMethodsInterceptorCode($interceptedMethods, $targetClassName)); $proxyCode = $this->proxyClassTemplate; foreach ($proxyClassTokens as $token => $value) { $proxyCode = str_replace('###' . $token . '###', $value, $proxyCode); } return array('proxyClassName' => $proxyNamespace . '\\' . $proxyClassName, 'proxyClassCode' => $proxyCode, 'advicedMethodsInformation' => $advicedMethodsInformation); }
/** * @test * @author Karsten Dambekalns <*****@*****.**> */ public function isClassImplementationOfReturnsTrueIfClassImplementsSpecifiedInterface() { $availableClassNames = array('F3\\FLOW3\\Tests\\Reflection\\Fixture\\ImplementationOfDummyInterface1'); $reflectionService = new \F3\FLOW3\Reflection\ReflectionService(); $reflectionService->setStatusCache($this->getMock('F3\\FLOW3\\Cache\\Frontend\\StringFrontend', array(), array(), '', FALSE)); $reflectionService->setDataCache($this->getMock('F3\\FLOW3\\Cache\\Frontend\\VariableFrontend', array(), array(), '', FALSE)); $reflectionService->injectSystemLogger($this->getMock('F3\\FLOW3\\Log\\SystemLoggerInterface')); $reflectionService->initialize($availableClassNames); $this->assertTrue($reflectionService->isClassImplementationOf('F3\\FLOW3\\Tests\\Reflection\\Fixture\\ImplementationOfDummyInterface1', 'F3\\FLOW3\\Tests\\Reflection\\Fixture\\DummyInterface1')); $this->assertFalse($reflectionService->isClassImplementationOf('F3\\FLOW3\\Tests\\Reflection\\Fixture\\ImplementationOfDummyInterface1', 'F3\\FLOW3\\Tests\\Reflection\\Fixture\\DummyInterface2')); }