/** * This method is used to optimize the matching process. * * @param \Neos\Flow\Aop\Builder\ClassNameIndex $classNameIndex * @return \Neos\Flow\Aop\Builder\ClassNameIndex */ public function reduceTargetClassNames(\Neos\Flow\Aop\Builder\ClassNameIndex $classNameIndex) { $classNames = $this->reflectionService->getClassNamesByAnnotation(Flow\ValueObject::class); $annotatedIndex = new \Neos\Flow\Aop\Builder\ClassNameIndex(); $annotatedIndex->setClassNames($classNames); return $classNameIndex->intersect($annotatedIndex); }
/** * @test */ public function filterByPrefixWork() { $index1 = new Aop\Builder\ClassNameIndex(); $index1->setClassNames(['\\Foo\\Bar', '\\Foo\\Baz', '\\Bar\\Baz', '\\Foo\\Blubb']); // We need to call sort manually! $index1->sort(); $filteredIndex = $index1->filterByPrefix('\\Foo'); $this->assertEquals(['\\Foo\\Bar', '\\Foo\\Baz', '\\Foo\\Blubb'], $filteredIndex->getClassNames()); }
/** * @test */ public function reduceTargetClassNamesFiltersAllClassesNotMatchedByAClassNameFilterWithRegularExpressions() { $availableClassNames = ['TestPackage\\Subpackage\\Class1', 'TestPackage\\Class2', 'TestPackage\\Subpackage\\SubSubPackage\\Class3', 'TestPackage\\Subpackage2\\Class4']; sort($availableClassNames); $availableClassNamesIndex = new Aop\Builder\ClassNameIndex(); $availableClassNamesIndex->setClassNames($availableClassNames); $expectedClassNames = ['TestPackage\\Subpackage\\Class1', 'TestPackage\\Subpackage\\SubSubPackage\\Class3']; sort($expectedClassNames); $expectedClassNamesIndex = new Aop\Builder\ClassNameIndex(); $expectedClassNamesIndex->setClassNames($expectedClassNames); $classNameFilter = new Aop\Pointcut\PointcutClassNameFilter('TestPackage\\Subpackage\\.*'); $result = $classNameFilter->reduceTargetClassNames($availableClassNamesIndex); $this->assertEquals($expectedClassNamesIndex, $result, 'The wrong class names have been filtered'); }
/** * @test */ public function reduceTargetClassNamesFiltersAllClassesNotHavingAMethodWithTheGivenAnnotation() { $availableClassNames = ['TestPackage\\Subpackage\\Class1', 'TestPackage\\Class2', 'TestPackage\\Subpackage\\SubSubPackage\\Class3', 'TestPackage\\Subpackage2\\Class4']; sort($availableClassNames); $availableClassNamesIndex = new Aop\Builder\ClassNameIndex(); $availableClassNamesIndex->setClassNames($availableClassNames); $mockReflectionService = $this->getMockBuilder(ReflectionService::class)->disableOriginalConstructor()->getMock(); $mockReflectionService->expects($this->any())->method('getClassesContainingMethodsAnnotatedWith')->with('SomeAnnotationClass')->will($this->returnValue(['TestPackage\\Subpackage\\Class1', 'TestPackage\\Subpackage\\SubSubPackage\\Class3', 'SomeMoreClass'])); $methodAnnotatedWithFilter = new Aop\Pointcut\PointcutMethodAnnotatedWithFilter('SomeAnnotationClass'); $methodAnnotatedWithFilter->injectReflectionService($mockReflectionService); $expectedClassNames = ['TestPackage\\Subpackage\\Class1', 'TestPackage\\Subpackage\\SubSubPackage\\Class3']; sort($expectedClassNames); $expectedClassNamesIndex = new Aop\Builder\ClassNameIndex(); $expectedClassNamesIndex->setClassNames($expectedClassNames); $result = $methodAnnotatedWithFilter->reduceTargetClassNames($availableClassNamesIndex); $this->assertEquals($expectedClassNamesIndex, $result, 'The wrong class names have been filtered'); }
/** * @test */ public function reduceTargetClassNamesFiltersAllClassesNotBeeingConfiguredAsScopeSession() { $availableClassNames = ['TestPackage\\Subpackage\\Class1', 'TestPackage\\Class2', 'TestPackage\\Subpackage\\SubSubPackage\\Class3', 'TestPackage\\Subpackage2\\Class4']; sort($availableClassNames); $availableClassNamesIndex = new ClassNameIndex(); $availableClassNamesIndex->setClassNames($availableClassNames); $mockCompileTimeObjectManager = $this->getMockBuilder(CompileTimeObjectManager::class)->disableOriginalConstructor()->getMock(); $mockCompileTimeObjectManager->expects($this->any())->method('getClassNamesByScope')->with(Configuration::SCOPE_SESSION)->will($this->returnValue(['TestPackage\\Subpackage\\Class1', 'TestPackage\\Subpackage\\SubSubPackage\\Class3', 'SomeMoreClass'])); $sessionObjectMethodsPointcutFilter = new SessionObjectMethodsPointcutFilter(); $sessionObjectMethodsPointcutFilter->injectObjectManager($mockCompileTimeObjectManager); $expectedClassNames = ['TestPackage\\Subpackage\\Class1', 'TestPackage\\Subpackage\\SubSubPackage\\Class3']; sort($expectedClassNames); $expectedClassNamesIndex = new ClassNameIndex(); $expectedClassNamesIndex->setClassNames($expectedClassNames); $result = $sessionObjectMethodsPointcutFilter->reduceTargetClassNames($availableClassNamesIndex); $this->assertEquals($expectedClassNamesIndex, $result, 'The wrong class names have been filtered'); }
/** * @test */ public function reduceTargetClassNamesFiltersAllClassesExceptTheClassItselfAndAllItsSubclasses() { $testClassName = uniqid('someTestInterface'); eval('class ' . $testClassName . ' {}'); $availableClassNames = [$testClassName, 'TestPackage\\Subpackage\\Class1', 'TestPackage\\Class2', 'TestPackage\\Subpackage\\SubSubPackage\\Class3', 'TestPackage\\Subpackage2\\Class4']; sort($availableClassNames); $availableClassNamesIndex = new Aop\Builder\ClassNameIndex(); $availableClassNamesIndex->setClassNames($availableClassNames); $mockReflectionService = $this->getMockBuilder(ReflectionService::class)->disableOriginalConstructor()->getMock(); $mockReflectionService->expects($this->any())->method('getAllSubClassNamesForClass')->with($testClassName)->will($this->returnValue(['TestPackage\\Subpackage\\Class1', 'TestPackage\\Subpackage\\SubSubPackage\\Class3', 'SomeMoreClass'])); $classTypeFilter = new Aop\Pointcut\PointcutClassTypeFilter($testClassName); $classTypeFilter->injectReflectionService($mockReflectionService); $expectedClassNames = [$testClassName, 'TestPackage\\Subpackage\\Class1', 'TestPackage\\Subpackage\\SubSubPackage\\Class3']; sort($expectedClassNames); $expectedClassNamesIndex = new Aop\Builder\ClassNameIndex(); $expectedClassNamesIndex->setClassNames($expectedClassNames); $result = $classTypeFilter->reduceTargetClassNames($availableClassNamesIndex); $this->assertEquals($expectedClassNamesIndex, $result, 'The wrong class names have been filtered'); }
/** * This method is used to optimize the matching process. * * @param ClassNameIndex $classNameIndex * @return ClassNameIndex */ public function reduceTargetClassNames(ClassNameIndex $classNameIndex) { if (!preg_match('/^([^\\.\\(\\)\\{\\}\\[\\]\\?\\+\\$\\!\\|]+)/', $this->originalExpressionString, $matches)) { return $classNameIndex; } $prefixFilter = $matches[1]; // We sort here to make sure the index is okay $classNameIndex->sort(); return $classNameIndex->filterByPrefix($prefixFilter); }
/** * This method is used to optimize the matching process. * * @param ClassNameIndex $classNameIndex * @return ClassNameIndex */ public function reduceTargetClassNames(ClassNameIndex $classNameIndex) { $classNames = $this->reflectionService->getClassesContainingMethodsAnnotatedWith($this->annotation); $annotatedIndex = new ClassNameIndex(); $annotatedIndex->setClassNames($classNames); return $classNameIndex->intersect($annotatedIndex); }
/** * @test */ public function reduceTargetClassNamesFiltersAllClassesNotMatchedAByClassNameFilter() { $availableClassNames = ['TestPackage\\Subpackage\\Class1', 'TestPackage\\Class2', 'TestPackage\\Subpackage\\SubSubPackage\\Class3', 'TestPackage\\Subpackage2\\Class4']; sort($availableClassNames); $availableClassNamesIndex = new Aop\Builder\ClassNameIndex(); $availableClassNamesIndex->setClassNames($availableClassNames); $classNameFilter1 = new Pointcut\PointcutClassNameFilter('TestPackage\\Subpackage\\SubSubPackage\\Class3'); $classNameFilter2 = new Pointcut\PointcutClassNameFilter('TestPackage\\Subpackage\\Class1'); $methodNameFilter1 = new Pointcut\PointcutMethodNameFilter('method2'); $expectedClassNames = ['TestPackage\\Subpackage\\Class1', 'TestPackage\\Subpackage\\SubSubPackage\\Class3']; sort($expectedClassNames); $expectedClassNamesIndex = new Aop\Builder\ClassNameIndex(); $expectedClassNamesIndex->setClassNames($expectedClassNames); $pointcutFilterComposite = new Pointcut\PointcutFilterComposite(); $pointcutFilterComposite->addFilter('&&', $classNameFilter1); $pointcutFilterComposite->addFilter('||', $classNameFilter2); $pointcutFilterComposite->addFilter('&&', $methodNameFilter1); $result = $pointcutFilterComposite->reduceTargetClassNames($availableClassNamesIndex); $this->assertEquals($expectedClassNamesIndex, $result, 'The wrong class names have been filtered'); }
/** * This method is used to optimize the matching process. * * @param ClassNameIndex $classNameIndex * @return ClassNameIndex */ public function reduceTargetClassNames(ClassNameIndex $classNameIndex) { if (interface_exists($this->interfaceOrClassName)) { $classNames = $this->reflectionService->getAllImplementationClassNamesForInterface($this->interfaceOrClassName); } elseif (class_exists($this->interfaceOrClassName)) { $classNames = $this->reflectionService->getAllSubClassNamesForClass($this->interfaceOrClassName); $classNames[] = $this->interfaceOrClassName; } else { $classNames = []; } $filteredIndex = new ClassNameIndex(); $filteredIndex->setClassNames($classNames); return $classNameIndex->intersect($filteredIndex); }
/** * This method is used to optimize the matching process. * * @param ClassNameIndex $classNameIndex * @return ClassNameIndex */ public function reduceTargetClassNames(ClassNameIndex $classNameIndex) { $sessionClasses = new ClassNameIndex(); $sessionClasses->setClassNames($this->objectManager->getClassNamesByScope(ObjectConfiguration::SCOPE_SESSION)); return $classNameIndex->intersect($sessionClasses); }
/** * This method is used to optimize the matching process. * * @param \Neos\Flow\Aop\Builder\ClassNameIndex $classNameIndex * @return \Neos\Flow\Aop\Builder\ClassNameIndex */ public function reduceTargetClassNames(Builder\ClassNameIndex $classNameIndex) { $result = new Builder\ClassNameIndex(); foreach ($this->advisors as $advisor) { $result->applyUnion($advisor->getPointcut()->reduceTargetClassNames($classNameIndex)); } foreach ($this->interfaceIntroductions as $interfaceIntroduction) { $result->applyUnion($interfaceIntroduction->getPointcut()->reduceTargetClassNames($classNameIndex)); } foreach ($this->propertyIntroductions as $propertyIntroduction) { $result->applyUnion($propertyIntroduction->getPointcut()->reduceTargetClassNames($classNameIndex)); } foreach ($this->traitIntroductions as $traitIntroduction) { $result->applyUnion($traitIntroduction->getPointcut()->reduceTargetClassNames($classNameIndex)); } $this->cachedTargetClassNameCandidates = $result; return $result; }
/** * Adds code to build the methods and advices array in case the parent class has some. * * @param string $className * @param ClassNameIndex $treatedSubClasses * @return ClassNameIndex */ protected function addBuildMethodsAndAdvicesCodeToClass($className, ClassNameIndex $treatedSubClasses) { if ($treatedSubClasses->hasClassName($className)) { return $treatedSubClasses; } $treatedSubClasses = $treatedSubClasses->union(new ClassNameIndex([$className])); if ($this->reflectionService->isClassReflected($className) === false) { return $treatedSubClasses; } $proxyClass = $this->compiler->getProxyClass($className); if ($proxyClass === false) { return $treatedSubClasses; } $callBuildMethodsAndAdvicesArrayCode = " if (method_exists(get_parent_class(), 'Flow_Aop_Proxy_buildMethodsAndAdvicesArray') && is_callable('parent::Flow_Aop_Proxy_buildMethodsAndAdvicesArray')) parent::Flow_Aop_Proxy_buildMethodsAndAdvicesArray();\n"; $proxyClass->getConstructor()->addPreParentCallCode($callBuildMethodsAndAdvicesArrayCode); $proxyClass->getMethod('__wakeup')->addPreParentCallCode($callBuildMethodsAndAdvicesArrayCode); return $treatedSubClasses; }
/** * Returns a new index object which contains all class names of this index * starting with the given prefix * * @param string $prefixFilter A prefix string to filter the class names of this index * @return \Neos\Flow\Aop\Builder\ClassNameIndex A new index object */ public function filterByPrefix($prefixFilter) { $pointcuts = array_keys($this->classNames); $result = new ClassNameIndex(); $right = count($pointcuts) - 1; $left = 0; $found = false; $currentPosition = -1; while ($found === false) { if ($left > $right) { break; } $currentPosition = $left + floor(($right - $left) / 2); if (strpos($pointcuts[$currentPosition], $prefixFilter) === 0) { $found = true; break; } else { $comparisonResult = strcmp($prefixFilter, $pointcuts[$currentPosition]); if ($comparisonResult > 0) { $left = $currentPosition + 1; } else { $right = $currentPosition - 1; } } } if ($found === true) { $startIndex = $currentPosition; while ($startIndex >= 0 && strpos($pointcuts[$startIndex], $prefixFilter) === 0) { $startIndex--; } $startIndex++; $endIndex = $currentPosition; while ($endIndex < count($pointcuts) && strpos($pointcuts[$endIndex], $prefixFilter) === 0) { $endIndex++; } $result->setClassNames(array_slice($pointcuts, $startIndex, $endIndex - $startIndex)); } return $result; }
/** * This method is used to optimize the matching process. * * @param ClassNameIndex $classNameIndex * @return ClassNameIndex */ public function reduceTargetClassNames(ClassNameIndex $classNameIndex) { if ($this->filters === null) { $this->buildPointcutFilters(); } $result = new ClassNameIndex(); foreach ($this->filters as $filter) { $result->applyUnion($filter->reduceTargetClassNames($classNameIndex)); } return $result; }