chore: complete update
This commit is contained in:
174
src/Framework/Reflection/CachedReflectionProvider.php
Normal file
174
src/Framework/Reflection/CachedReflectionProvider.php
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Reflection;
|
||||
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
use ReflectionParameter;
|
||||
use ReflectionProperty;
|
||||
use ReflectionException;
|
||||
|
||||
final class CachedReflectionProvider implements ReflectionProvider
|
||||
{
|
||||
private array $classCache = [];
|
||||
private array $methodCache = [];
|
||||
private array $parameterCache = [];
|
||||
private array $propertyCache = [];
|
||||
private array $attributeCache = [];
|
||||
private array $parameterInfoCache = [];
|
||||
private array $instantiableCache = [];
|
||||
private array $interfaceCache = [];
|
||||
private array $wrappedClassCache = [];
|
||||
private array $wrappedMethodCache = [];
|
||||
|
||||
public function getWrappedClass(string $className): WrappedReflectionClass
|
||||
{
|
||||
return $this->wrappedClassCache[$className] ??= new WrappedReflectionClass(
|
||||
$this->getClass($className)
|
||||
);
|
||||
}
|
||||
|
||||
public function getWrappedMethod(string $className, string $methodName): WrappedReflectionMethod
|
||||
{
|
||||
$key = "{$className}::{$methodName}";
|
||||
return $this->wrappedMethodCache[$key] ??= new WrappedReflectionMethod(
|
||||
$this->getMethod($className, $methodName)
|
||||
);
|
||||
}
|
||||
|
||||
public function getClass(string $className): ReflectionClass
|
||||
{
|
||||
return $this->classCache[$className] ??= new ReflectionClass($className);
|
||||
}
|
||||
|
||||
public function getMethod(string $className, string $methodName): ReflectionMethod
|
||||
{
|
||||
$key = "{$className}::{$methodName}";
|
||||
return $this->methodCache[$key] ??= $this->getClass($className)->getMethod($methodName);
|
||||
}
|
||||
|
||||
public function getMethodParameters(string $className, string $methodName): array
|
||||
{
|
||||
$key = "{$className}::{$methodName}::params";
|
||||
return $this->parameterCache[$key] ??= $this->getMethod($className, $methodName)->getParameters();
|
||||
}
|
||||
|
||||
public function getProperties(string $className): array
|
||||
{
|
||||
$key = "{$className}::properties";
|
||||
return $this->propertyCache[$key] ??= $this->getClass($className)->getProperties();
|
||||
}
|
||||
|
||||
public function getAttributes(string $className, ?string $attributeClass = null): array
|
||||
{
|
||||
$key = "{$className}::attributes::" . ($attributeClass ?? 'all');
|
||||
|
||||
return $this->attributeCache[$key] ??= $attributeClass
|
||||
? $this->getClass($className)->getAttributes($attributeClass)
|
||||
: $this->getClass($className)->getAttributes();
|
||||
}
|
||||
|
||||
public function getMethodAttributes(string $className, string $methodName, ?string $attributeClass = null): array
|
||||
{
|
||||
$key = "{$className}::{$methodName}::attributes::" . ($attributeClass ?? 'all');
|
||||
|
||||
return $this->attributeCache[$key] ??= $attributeClass
|
||||
? $this->getMethod($className, $methodName)->getAttributes($attributeClass)
|
||||
: $this->getMethod($className, $methodName)->getAttributes();
|
||||
}
|
||||
|
||||
public function hasAttribute(string $className, string $attributeClass): bool
|
||||
{
|
||||
return !empty($this->getAttributes($className, $attributeClass));
|
||||
}
|
||||
|
||||
public function getParameterInfo(string $className, string $methodName): array
|
||||
{
|
||||
$key = "{$className}::{$methodName}::paramInfo";
|
||||
|
||||
return $this->parameterInfoCache[$key] ??= $this->buildParameterInfo($className, $methodName);
|
||||
}
|
||||
|
||||
public function isInstantiable(string $className): bool
|
||||
{
|
||||
return $this->instantiableCache[$className] ??= $this->getClass($className)->isInstantiable();
|
||||
}
|
||||
|
||||
public function implementsInterface(string $className, string $interfaceName): bool
|
||||
{
|
||||
$key = "{$className}::implements::{$interfaceName}";
|
||||
|
||||
return $this->interfaceCache[$key] ??= $this->getClass($className)->implementsInterface($interfaceName);
|
||||
}
|
||||
|
||||
private function buildParameterInfo(string $className, string $methodName): array
|
||||
{
|
||||
$parameters = $this->getMethodParameters($className, $methodName);
|
||||
$paramInfo = [];
|
||||
|
||||
foreach ($parameters as $param) {
|
||||
$type = $param->getType();
|
||||
$paramInfo[] = [
|
||||
'name' => $param->getName(),
|
||||
'type' => $type ? $type->getName() : null,
|
||||
'isBuiltin' => $type ? $type->isBuiltin() : true,
|
||||
'allowsNull' => $param->allowsNull(),
|
||||
'isOptional' => $param->isOptional(),
|
||||
'hasDefaultValue' => $param->isDefaultValueAvailable(),
|
||||
'default' => $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null,
|
||||
'position' => $param->getPosition(),
|
||||
];
|
||||
}
|
||||
|
||||
return $paramInfo;
|
||||
}
|
||||
|
||||
public function forget(string $className): void
|
||||
{
|
||||
unset($this->classCache[$className]);
|
||||
unset($this->instantiableCache[$className]);
|
||||
unset($this->wrappedClassCache[$className]);
|
||||
|
||||
// Alle zugehörigen Caches leeren
|
||||
$this->clearRelatedCaches($className);
|
||||
}
|
||||
|
||||
public function flush(): void
|
||||
{
|
||||
$this->classCache = [];
|
||||
$this->methodCache = [];
|
||||
$this->parameterCache = [];
|
||||
$this->propertyCache = [];
|
||||
$this->attributeCache = [];
|
||||
$this->parameterInfoCache = [];
|
||||
$this->instantiableCache = [];
|
||||
$this->interfaceCache = [];
|
||||
$this->wrappedClassCache = [];
|
||||
$this->wrappedMethodCache = [];
|
||||
}
|
||||
|
||||
private function clearRelatedCaches(string $className): void
|
||||
{
|
||||
$prefix = $className . '::';
|
||||
|
||||
$caches = [
|
||||
&$this->methodCache,
|
||||
&$this->parameterCache,
|
||||
&$this->propertyCache,
|
||||
&$this->attributeCache,
|
||||
&$this->parameterInfoCache,
|
||||
&$this->interfaceCache,
|
||||
&$this->wrappedMethodCache
|
||||
];
|
||||
|
||||
foreach ($caches as &$cache) {
|
||||
$cache = array_filter(
|
||||
$cache,
|
||||
fn($key) => !str_starts_with($key, $prefix),
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
43
src/Framework/Reflection/ReflectionProvider.php
Normal file
43
src/Framework/Reflection/ReflectionProvider.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Reflection;
|
||||
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
use ReflectionParameter;
|
||||
use ReflectionProperty;
|
||||
|
||||
interface ReflectionProvider
|
||||
{
|
||||
// Wrapped Objekte für erweiterte API
|
||||
public function getWrappedClass(string $className): WrappedReflectionClass;
|
||||
|
||||
public function getWrappedMethod(string $className, string $methodName): WrappedReflectionMethod;
|
||||
|
||||
// Original Reflection Objekte
|
||||
public function getClass(string $className): ReflectionClass;
|
||||
|
||||
public function getMethod(string $className, string $methodName): ReflectionMethod;
|
||||
|
||||
public function getMethodParameters(string $className, string $methodName): array;
|
||||
|
||||
public function getProperties(string $className): array;
|
||||
|
||||
public function getAttributes(string $className, ?string $attributeClass = null): array;
|
||||
|
||||
public function getMethodAttributes(string $className, string $methodName, ?string $attributeClass = null): array;
|
||||
|
||||
public function hasAttribute(string $className, string $attributeClass): bool;
|
||||
|
||||
public function getParameterInfo(string $className, string $methodName): array;
|
||||
|
||||
public function isInstantiable(string $className): bool;
|
||||
|
||||
public function implementsInterface(string $className, string $interfaceName): bool;
|
||||
|
||||
public function forget(string $className): void;
|
||||
|
||||
public function flush(): void;
|
||||
}
|
||||
77
src/Framework/Reflection/WrappedReflectionClass.php
Normal file
77
src/Framework/Reflection/WrappedReflectionClass.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Reflection;
|
||||
|
||||
use ReflectionClass;
|
||||
use ReflectionAttribute;
|
||||
|
||||
final readonly class WrappedReflectionClass
|
||||
{
|
||||
public function __construct(
|
||||
public ReflectionClass $reflection
|
||||
) {}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->reflection->getName();
|
||||
}
|
||||
|
||||
public function getShortName(): string
|
||||
{
|
||||
return $this->reflection->getShortName();
|
||||
}
|
||||
|
||||
public function isInstantiable(): bool
|
||||
{
|
||||
return $this->reflection->isInstantiable();
|
||||
}
|
||||
|
||||
public function implementsInterface(string $interface): bool
|
||||
{
|
||||
return $this->reflection->implementsInterface($interface);
|
||||
}
|
||||
|
||||
// Erweiterte Convenience-Methoden
|
||||
public function getAttributeInstances(?string $attributeClass = null): array
|
||||
{
|
||||
$attributes = $this->reflection->getAttributes($attributeClass);
|
||||
return array_map(fn(ReflectionAttribute $attr) => $attr->newInstance(), $attributes);
|
||||
}
|
||||
|
||||
public function hasAttribute(string $attributeClass): bool
|
||||
{
|
||||
return !empty($this->reflection->getAttributes($attributeClass));
|
||||
}
|
||||
|
||||
public function getFirstAttribute(string $attributeClass): ?object
|
||||
{
|
||||
$instances = $this->getAttributeInstances($attributeClass);
|
||||
return $instances[0] ?? null;
|
||||
}
|
||||
|
||||
public function getMethodsWithAttribute(string $attributeClass): array
|
||||
{
|
||||
$methods = [];
|
||||
foreach ($this->reflection->getMethods() as $method) {
|
||||
if (!empty($method->getAttributes($attributeClass))) {
|
||||
$methods[] = new WrappedReflectionMethod($method);
|
||||
}
|
||||
}
|
||||
return $methods;
|
||||
}
|
||||
|
||||
public function getWrappedMethod(string $name): WrappedReflectionMethod
|
||||
{
|
||||
return new WrappedReflectionMethod($this->reflection->getMethod($name));
|
||||
}
|
||||
|
||||
public function getWrappedMethods(?int $filter = null): array
|
||||
{
|
||||
return array_map(
|
||||
fn($method) => new WrappedReflectionMethod($method),
|
||||
$this->reflection->getMethods($filter)
|
||||
);
|
||||
}
|
||||
}
|
||||
65
src/Framework/Reflection/WrappedReflectionMethod.php
Normal file
65
src/Framework/Reflection/WrappedReflectionMethod.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Reflection;
|
||||
|
||||
use ReflectionMethod;
|
||||
use ReflectionAttribute;
|
||||
|
||||
final readonly class WrappedReflectionMethod
|
||||
{
|
||||
public function __construct(
|
||||
public ReflectionMethod $reflection
|
||||
) {}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->reflection->getName();
|
||||
}
|
||||
|
||||
public function getWrappedParameters(): array
|
||||
{
|
||||
return array_map(
|
||||
fn($param) => new WrappedReflectionParameter($param),
|
||||
$this->reflection->getParameters()
|
||||
);
|
||||
}
|
||||
|
||||
// Erweiterte Parameter-Info als Array (für DI)
|
||||
public function getParameterInfo(): array
|
||||
{
|
||||
$params = [];
|
||||
foreach ($this->reflection->getParameters() as $param) {
|
||||
$type = $param->getType();
|
||||
$params[] = [
|
||||
'name' => $param->getName(),
|
||||
'type' => $type ? $type->getName() : null,
|
||||
'isBuiltin' => $type ? $type->isBuiltin() : true,
|
||||
'allowsNull' => $param->allowsNull(),
|
||||
'isOptional' => $param->isOptional(),
|
||||
'hasDefaultValue' => $param->isDefaultValueAvailable(),
|
||||
'default' => $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null,
|
||||
'position' => $param->getPosition(),
|
||||
];
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
public function getAttributeInstances(?string $attributeClass = null): array
|
||||
{
|
||||
$attributes = $this->reflection->getAttributes($attributeClass);
|
||||
return array_map(fn(ReflectionAttribute $attr) => $attr->newInstance(), $attributes);
|
||||
}
|
||||
|
||||
public function hasAttribute(string $attributeClass): bool
|
||||
{
|
||||
return !empty($this->reflection->getAttributes($attributeClass));
|
||||
}
|
||||
|
||||
public function getFirstAttribute(string $attributeClass): ?object
|
||||
{
|
||||
$instances = $this->getAttributeInstances($attributeClass);
|
||||
return $instances[0] ?? null;
|
||||
}
|
||||
}
|
||||
73
src/Framework/Reflection/WrappedReflectionParameter.php
Normal file
73
src/Framework/Reflection/WrappedReflectionParameter.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Reflection;
|
||||
|
||||
use ReflectionParameter;
|
||||
|
||||
final readonly class WrappedReflectionParameter
|
||||
{
|
||||
public function __construct(
|
||||
public ReflectionParameter $reflection
|
||||
) {}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->reflection->getName();
|
||||
}
|
||||
|
||||
public function getTypeName(): ?string
|
||||
{
|
||||
$type = $this->reflection->getType();
|
||||
return $type ? $type->getName() : null;
|
||||
}
|
||||
|
||||
public function isBuiltin(): bool
|
||||
{
|
||||
$type = $this->reflection->getType();
|
||||
return $type ? $type->isBuiltin() : true;
|
||||
}
|
||||
|
||||
public function isOptional(): bool
|
||||
{
|
||||
return $this->reflection->isOptional();
|
||||
}
|
||||
|
||||
public function hasDefaultValue(): bool
|
||||
{
|
||||
return $this->reflection->isDefaultValueAvailable();
|
||||
}
|
||||
|
||||
public function getDefaultValue(): mixed
|
||||
{
|
||||
return $this->reflection->isDefaultValueAvailable()
|
||||
? $this->reflection->getDefaultValue()
|
||||
: null;
|
||||
}
|
||||
|
||||
public function allowsNull(): bool
|
||||
{
|
||||
return $this->reflection->allowsNull();
|
||||
}
|
||||
|
||||
public function getPosition(): int
|
||||
{
|
||||
return $this->reflection->getPosition();
|
||||
}
|
||||
|
||||
// Convenience-Methode für DI
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->getName(),
|
||||
'type' => $this->getTypeName(),
|
||||
'isBuiltin' => $this->isBuiltin(),
|
||||
'allowsNull' => $this->allowsNull(),
|
||||
'isOptional' => $this->isOptional(),
|
||||
'hasDefaultValue' => $this->hasDefaultValue(),
|
||||
'default' => $this->getDefaultValue(),
|
||||
'position' => $this->getPosition(),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user