cache = $env === 'development' ? $factory->createForDevelopment() : $factory->createOptimized(); } else { $this->cache = $cache; } } // ClassReflector implementation public function getClass(ClassName $className): WrappedReflectionClass { return $this->cache->classCache->getClass($className); } public function getNativeClass(ClassName $className): ReflectionClass { return $this->cache->classCache->getNativeClass($className); } public function getProperties(ClassName $className): PropertyCollection { return $this->cache->classCache->getProperties($className); } public function getMethods(ClassName $className, ?int $filter = null): MethodCollection { return $this->cache->classCache->getMethods($className, $filter); } public function getAttributes(ClassName $className, ?string $attributeClass = null): AttributeCollection { return $this->cache->classCache->getAttributes($className, $attributeClass); } public function hasAttribute(ClassName $className, string $attributeClass): bool { return $this->cache->classCache->hasAttribute($className, $attributeClass); } public function isInstantiable(ClassName $className): bool { return $this->cache->classCache->isInstantiable($className); } public function implementsInterface(ClassName $className, string $interfaceName): bool { return $this->cache->classCache->implementsInterface($className, $interfaceName); } // MethodReflector implementation public function getMethod(ClassName $className, string $methodName): WrappedReflectionMethod { return $this->cache->methodCache->getMethod($className, $methodName); } public function getNativeMethod(ClassName $className, string $methodName): ReflectionMethod { return $this->cache->methodCache->getNativeMethod($className, $methodName); } public function getMethodParameters(ClassName $className, string $methodName): ParameterCollection { return $this->cache->parameterCache->getParameters($className, $methodName); } public function getMethodAttributes(ClassName $className, string $methodName, ?string $attributeClass = null): AttributeCollection { return $this->cache->methodCache->getMethodAttributes($className, $methodName, $attributeClass); } public function getParameterInfo(ClassName $className, string $methodName): array { return $this->cache->parameterCache->getParameterInfo($className, $methodName); } // PropertyReflector implementation public function getProperty(ClassName $className, string $propertyName): ReflectionProperty { return $this->getNativeClass($className)->getProperty($propertyName); } public function hasProperty(ClassName $className, string $propertyName): bool { return $this->getNativeClass($className)->hasProperty($propertyName); } public function getPropertiesWithAttribute(ClassName $className, string $attributeClass): PropertyCollection { $properties = $this->getProperties($className); $result = []; foreach ($properties as $property) { if (count($property->getAttributes($attributeClass)) > 0) { $result[] = $property; } } return new PropertyCollection(...$result); } public function getPropertyAttributes(ClassName $className, string $propertyName, ?string $attributeClass = null): array { $property = $this->getProperty($className, $propertyName); return $property->getAttributes($attributeClass); } public function getPropertyType(ClassName $className, string $propertyName): ?ReflectionType { $property = $this->getProperty($className, $propertyName); return $property->getType(); } public function getPropertyDefaultValue(ClassName $className, string $propertyName): mixed { $property = $this->getProperty($className, $propertyName); if (! $property->hasDefaultValue()) { return null; } return $property->getDefaultValue(); } // ParameterReflector implementation public function getMethodParameter(ClassName $className, string $methodName, string $parameterName): ReflectionParameter { $method = $this->getNativeMethod($className, $methodName); foreach ($method->getParameters() as $parameter) { if ($parameter->getName() === $parameterName) { return $parameter; } } throw new \ReflectionException("Parameter {$parameterName} does not exist in method {$methodName}"); } public function hasMethodParameter(ClassName $className, string $methodName, string $parameterName): bool { $method = $this->getNativeMethod($className, $methodName); foreach ($method->getParameters() as $parameter) { if ($parameter->getName() === $parameterName) { return true; } } return false; } public function getParameterType(ClassName $className, string $methodName, string $parameterName): ?ReflectionType { $parameter = $this->getMethodParameter($className, $methodName, $parameterName); return $parameter->getType(); } public function getParameterDefaultValue(ClassName $className, string $methodName, string $parameterName): mixed { $parameter = $this->getMethodParameter($className, $methodName, $parameterName); if (! $parameter->isDefaultValueAvailable()) { return null; } return $parameter->getDefaultValue(); } public function isParameterOptional(ClassName $className, string $methodName, string $parameterName): bool { $parameter = $this->getMethodParameter($className, $methodName, $parameterName); return $parameter->isOptional(); } public function isParameterVariadic(ClassName $className, string $methodName, string $parameterName): bool { $parameter = $this->getMethodParameter($className, $methodName, $parameterName); return $parameter->isVariadic(); } public function getParameterAttributes( ClassName $className, string $methodName, string $parameterName, ?string $attributeClass = null ): array { $parameter = $this->getMethodParameter($className, $methodName, $parameterName); return $parameter->getAttributes($attributeClass); } // AttributeReflector implementation public function hasMethodAttribute(ClassName $className, string $methodName, string $attributeClass): bool { $attributes = $this->getMethodAttributes($className, $methodName, $attributeClass); return ! $attributes->isEmpty(); } public function getAttributeInstances(ClassName $className, ?string $attributeClass = null): array { $attributes = $this->getAttributes($className, $attributeClass); $instances = []; foreach ($attributes as $attribute) { try { $instances[] = $attribute->newInstance(); } catch (\Throwable) { // Skip attributes that can't be instantiated } } return $instances; } public function getMethodAttributeInstances(ClassName $className, string $methodName, ?string $attributeClass = null): array { $attributes = $this->getMethodAttributes($className, $methodName, $attributeClass); $instances = []; foreach ($attributes as $attribute) { try { $instances[] = $attribute->newInstance(); } catch (\Throwable) { // Skip attributes that can't be instantiated } } return $instances; } // EnumReflector implementation public function isEnum(ClassName $className): bool { return $this->getNativeClass($className)->isEnum(); } public function getEnumCases(ClassName $className): array { if (! $this->isEnum($className)) { throw new \ReflectionException("Class {$className->getFullyQualified()} is not an enum"); } // Use ReflectionEnum instead of ReflectionClass for enum-specific methods /** @var class-string $classNameString */ $classNameString = $className->getFullyQualified(); $reflectionEnum = new \ReflectionEnum($classNameString); $reflectionCases = $reflectionEnum->getCases(); $cases = []; foreach ($reflectionCases as $case) { $caseName = $case->getName(); // Use constant() function to dynamically access enum case $cases[$caseName] = constant("$classNameString::$caseName"); } return $cases; } public function getEnumCase(ClassName $className, string $caseName): object { if (! $this->isEnum($className)) { throw new \ReflectionException("Class {$className->getFullyQualified()} is not an enum"); } if (! $this->hasEnumCase($className, $caseName)) { throw new \ReflectionException("Enum case {$caseName} does not exist in enum {$className->getFullyQualified()}"); } /** @var class-string $classNameString */ $classNameString = $className->getFullyQualified(); // Use constant() function to dynamically access enum case return constant("$classNameString::$caseName"); } public function hasEnumCase(ClassName $className, string $caseName): bool { if (! $this->isEnum($className)) { return false; } // Use ReflectionEnum instead of ReflectionClass for enum-specific methods /** @var class-string $classNameString */ $classNameString = $className->getFullyQualified(); $reflectionEnum = new \ReflectionEnum($classNameString); // ReflectionEnum has a hasCase method we can use directly return $reflectionEnum->hasCase($caseName); } public function getEnumCaseAttributes( ClassName $className, string $caseName, ?string $attributeClass = null ): array { if (! $this->isEnum($className)) { throw new \ReflectionException("Class {$className->getFullyQualified()} is not an enum"); } // Use ReflectionEnum instead of ReflectionClass for enum-specific methods /** @var class-string $classNameString */ $classNameString = $className->getFullyQualified(); $reflectionEnum = new \ReflectionEnum($classNameString); // Check if the case exists if (! $reflectionEnum->hasCase($caseName)) { throw new \ReflectionException("Enum case {$caseName} does not exist in enum {$className->getFullyQualified()}"); } // Get the case directly using getCase method $case = $reflectionEnum->getCase($caseName); return $case->getAttributes($attributeClass); } public function isBackedEnum(ClassName $className): bool { if (! $this->isEnum($className)) { return false; } // Use ReflectionEnum instead of ReflectionClass for enum-specific methods /** @var class-string $classNameString */ $classNameString = $className->getFullyQualified(); $reflectionEnum = new \ReflectionEnum($classNameString); return $reflectionEnum->isBacked(); } public function getEnumBackingType(ClassName $className): ?string { if (! $this->isBackedEnum($className)) { return null; } // Use ReflectionEnum instead of ReflectionClass for enum-specific methods /** @var class-string $classNameString */ $classNameString = $className->getFullyQualified(); $reflectionEnum = new \ReflectionEnum($classNameString); $backingType = $reflectionEnum->getBackingType(); return $backingType ? $backingType->getName() : null; } public function getEnumCaseBackingValue(ClassName $className, string $caseName): int|string|null { if (! $this->isBackedEnum($className)) { return null; } $case = $this->getEnumCase($className, $caseName); // For backed enums, the value property contains the backing value return $case->value; } // InstantiationReflector implementation public function createInstance(ClassName $className, array $args = []): object { if (! $this->isInstantiable($className)) { throw new \ReflectionException("Class {$className->getFullyQualified()} is not instantiable"); } $class = $this->getNativeClass($className); return $class->newInstance(...$args); } public function createInstanceWithoutConstructor(ClassName $className): object { $class = $this->getNativeClass($className); return $class->newInstanceWithoutConstructor(); } public function createLazyGhost(ClassName $className, callable $initializer, int $options = 0): object { $class = $this->getNativeClass($className); return $class->newLazyGhost($initializer, $options); } public function createLazyProxy(ClassName $className, callable $factory, int $options = 0): object { $class = $this->getNativeClass($className); return $class->newLazyProxy($factory, $options); } public function hasConstructor(ClassName $className): bool { $class = $this->getNativeClass($className); return $class->getConstructor() !== null; } public function getConstructorParameters(ClassName $className): array { $class = $this->getNativeClass($className); $constructor = $class->getConstructor(); if ($constructor === null) { return []; } return $constructor->getParameters(); } public function isAbstract(ClassName $className): bool { return $this->getNativeClass($className)->isAbstract(); } public function isFinal(ClassName $className): bool { return $this->getNativeClass($className)->isFinal(); } public function isInternal(ClassName $className): bool { return $this->getNativeClass($className)->isInternal(); } public function isUserDefined(ClassName $className): bool { return $this->getNativeClass($className)->isUserDefined(); } // CacheManager implementation public function forget(ClassName $className): void { $this->cache->forget($className); } public function flush(): void { $this->cache->flush(); } public function getStats(): Statistics { return $this->cache->getStats(); } /** * Get the underlying cache instance */ public function getCache(): ReflectionCache { return $this->cache; } }