/** * Reflects the given class and stores the results in this service's properties. * * @param string $className Full qualified name of the class to reflect * @return void * @throws Exception\InvalidClassException */ protected function reflectClass($className) { $this->log(sprintf('Reflecting class %s', $className), LOG_DEBUG); $className = $this->cleanClassName($className); if (strpos($className, 'Neos\\Flow\\Persistence\\Doctrine\\Proxies') === 0 && in_array(\Doctrine\ORM\Proxy\Proxy::class, class_implements($className))) { // Somebody tried to reflect a doctrine proxy, which will have severe side effects. // see bug http://forge.typo3.org/issues/29449 for details. throw new Exception\InvalidClassException('The class with name "' . $className . '" is a Doctrine proxy. It is not supported to reflect doctrine proxy classes.', 1314944681); } $class = new ClassReflection($className); if (!isset($this->classReflectionData[$className])) { $this->classReflectionData[$className] = []; } if ($class->isAbstract() || $class->isInterface()) { $this->classReflectionData[$className][self::DATA_CLASS_ABSTRACT] = true; } if ($class->isFinal()) { $this->classReflectionData[$className][self::DATA_CLASS_FINAL] = true; } /** @var $parentClass ClassReflection */ foreach ($this->getParentClasses($class) as $parentClass) { $this->addParentClass($className, $parentClass); } /** @var $interface ClassReflection */ foreach ($class->getInterfaces() as $interface) { $this->addImplementedInterface($className, $interface); } foreach ($this->annotationReader->getClassAnnotations($class) as $annotation) { $annotationClassName = get_class($annotation); $this->annotatedClasses[$annotationClassName][$className] = true; $this->classReflectionData[$className][self::DATA_CLASS_ANNOTATIONS][] = $annotation; } /** @var $property PropertyReflection */ foreach ($class->getProperties() as $property) { $this->reflectClassProperty($className, $property); } foreach ($class->getMethods() as $method) { $this->reflectClassMethod($className, $method); } // Sort reflection data so that the cache data is deterministic. This is // important for comparisons when checking if classes have changed in a // Development context. ksort($this->classReflectionData); $this->updatedReflectionData[$className] = true; }
/** * @test */ public function proxiedFinalClassesAreStillFinal() { $reflectionClass = new ClassReflection(Fixtures\FinalClassWithDependencies::class); $this->assertTrue($reflectionClass->isFinal()); }