chore: complete update

This commit is contained in:
2025-07-17 16:24:20 +02:00
parent 899227b0a4
commit 64a7051137
1300 changed files with 85570 additions and 2756 deletions

View File

@@ -0,0 +1,177 @@
<?php
namespace App\Framework\DI;
use App\Framework\DI\Exceptions\CyclicDependencyException;
use App\Framework\DI\Exceptions\LazyLoadingException;
use App\Framework\Reflection\CachedReflectionProvider;
use App\Framework\Reflection\ReflectionProvider;
use Throwable;
final class DefaultContainer implements Container
{
private array $resolving = [];
private readonly DependencyResolver $dependencyResolver;
private readonly SingletonDetector $singletonDetector;
private readonly LazyInstantiator $lazyInstantiator;
public readonly MethodInvoker $invoker;
public function __construct(
private readonly InstanceRegistry $instances = new InstanceRegistry(),
private readonly BindingRegistry $bindings = new BindingRegistry(),
private readonly ReflectionProvider $reflectionProvider = new CachedReflectionProvider(),
){
$this->dependencyResolver = new DependencyResolver($this->reflectionProvider, $this);
$this->singletonDetector = new SingletonDetector($this->reflectionProvider, $this->instances);
$this->lazyInstantiator = new LazyInstantiator(
$this->reflectionProvider,
$this->createInstance(...)
);
$this->invoker = new MethodInvoker($this, $this->reflectionProvider);
$this->registerSelf();
}
public function bind(string $abstract, callable|string|object $concrete): void
{
$this->bindings->bind($abstract, $concrete);
$this->clearCaches($abstract);
}
public function singleton(string $abstract, callable|string|object $concrete): void
{
$this->bind($abstract, $concrete);
$this->instances->markAsSingleton($abstract);
}
public function instance(string $abstract, object $instance): void
{
$this->instances->setInstance($abstract, $instance);
}
/**
* @template T of object
* @param class-string<T> $class
* @return T
*/
public function get(string $class): object
{
// Bereits instanziierte Objekte zurückgeben
if ($this->instances->hasSingleton($class)) {
return $this->instances->getSingleton($class);
}
if ($this->instances->hasInstance($class)) {
return $this->instances->getInstance($class);
}
// Lazy Loading versuchen
if ($this->lazyInstantiator->canUseLazyLoading($class, $this->instances)) {
try {
return $this->lazyInstantiator->createLazyInstance($class);
} catch (Throwable $e) {
if (!$e instanceof LazyLoadingException) {
throw $e;
}
}
}
return $this->createInstance($class);
}
private function createInstance(string $class): object
{
if (in_array($class, $this->resolving, true)) {
throw new CyclicDependencyException(
dependencyChain: $this->resolving,
class: $class
);
}
$this->resolving[] = $class;
try {
$instance = $this->buildInstance($class);
if ($this->singletonDetector->isSingleton($class)) {
$this->instances->setSingleton($class, $instance);
} else {
$this->instances->setInstance($class, $instance);
}
return $instance;
} finally {
array_pop($this->resolving);
}
}
private function buildInstance(string $class): object
{
if ($this->bindings->hasBinding($class)) {
return $this->resolveBinding($class, $this->bindings->getBinding($class));
}
$reflection = $this->reflectionProvider->getClass($class);
$dependencies = $this->dependencyResolver->resolveDependencies($class);
return $reflection->newInstanceArgs($dependencies);
}
private function resolveBinding(string $class, callable|string|object $concrete): object
{
return match (true) {
is_callable($concrete) => $concrete($this),
is_string($concrete) => $this->get($concrete),
default => $concrete
};
}
public function has(string $class): bool
{
return $this->instances->hasSingleton($class)
|| $this->instances->hasInstance($class)
|| $this->bindings->hasBinding($class)
|| class_exists($class);
}
public function forget(string $class): void
{
$this->instances->forget($class);
$this->bindings->forget($class);
$this->clearCaches($class);
}
public function flush(): void
{
$this->instances->flush();
$this->reflectionProvider->flush();
$this->dependencyResolver->flushCache();
$this->lazyInstantiator->flushFactories();
// Container selbst wieder registrieren
$this->registerSelf();
}
public function getRegisteredServices(): array
{
return array_merge(
$this->instances->getAllRegistered(),
$this->bindings->getAllBindings()
);
}
private function clearCaches(string $class): void
{
$this->reflectionProvider->forget($class);
$this->dependencyResolver->clearCache($class);
$this->lazyInstantiator->forgetFactory($class);
}
private function registerSelf():void
{
$this->instances->setSingleton(self::class, $this);
$this->instances->setSingleton(DefaultContainer::class, $this);
$this->instances->setSingleton(Container::class, $this);
}
}