|
|
|
@ -12,6 +12,7 @@ use Closure; |
|
|
|
|
use OCP\AppFramework\QueryException; |
|
|
|
|
use OCP\IContainer; |
|
|
|
|
use Pimple\Container; |
|
|
|
|
use Psr\Container\ContainerExceptionInterface; |
|
|
|
|
use Psr\Container\ContainerInterface; |
|
|
|
|
use ReflectionClass; |
|
|
|
|
use ReflectionException; |
|
|
|
@ -23,8 +24,9 @@ use function class_exists; |
|
|
|
|
* SimpleContainer is a simple implementation of a container on basis of Pimple |
|
|
|
|
*/ |
|
|
|
|
class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { |
|
|
|
|
/** @var Container */ |
|
|
|
|
private $container; |
|
|
|
|
public static bool $useLazyObjects = false; |
|
|
|
|
|
|
|
|
|
private Container $container; |
|
|
|
|
|
|
|
|
|
public function __construct() { |
|
|
|
|
$this->container = new Container(); |
|
|
|
@ -49,16 +51,29 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @param ReflectionClass $class the class to instantiate |
|
|
|
|
* @return \stdClass the created class |
|
|
|
|
* @return object the created class |
|
|
|
|
* @suppress PhanUndeclaredClassInstanceof |
|
|
|
|
*/ |
|
|
|
|
private function buildClass(ReflectionClass $class) { |
|
|
|
|
private function buildClass(ReflectionClass $class): object { |
|
|
|
|
$constructor = $class->getConstructor(); |
|
|
|
|
if ($constructor === null) { |
|
|
|
|
/* No constructor, return a instance directly */ |
|
|
|
|
return $class->newInstance(); |
|
|
|
|
} |
|
|
|
|
if (PHP_VERSION_ID >= 80400 && self::$useLazyObjects) { |
|
|
|
|
/* For PHP>=8.4, use a lazy ghost to delay constructor and dependency resolving */ |
|
|
|
|
/** @psalm-suppress UndefinedMethod */ |
|
|
|
|
return $class->newLazyGhost(function (object $object) use ($constructor): void { |
|
|
|
|
/** @psalm-suppress DirectConstructorCall For lazy ghosts we have to call the constructor directly */ |
|
|
|
|
$object->__construct(...$this->buildClassConstructorParameters($constructor)); |
|
|
|
|
}); |
|
|
|
|
} else { |
|
|
|
|
return $class->newInstanceArgs($this->buildClassConstructorParameters($constructor)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return $class->newInstanceArgs(array_map(function (ReflectionParameter $parameter) { |
|
|
|
|
private function buildClassConstructorParameters(\ReflectionMethod $constructor): array { |
|
|
|
|
return array_map(function (ReflectionParameter $parameter) { |
|
|
|
|
$parameterType = $parameter->getType(); |
|
|
|
|
|
|
|
|
|
$resolveName = $parameter->getName(); |
|
|
|
@ -69,10 +84,10 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
$builtIn = $parameter->hasType() && ($parameter->getType() instanceof ReflectionNamedType) |
|
|
|
|
&& $parameter->getType()->isBuiltin(); |
|
|
|
|
$builtIn = $parameterType !== null && ($parameterType instanceof ReflectionNamedType) |
|
|
|
|
&& $parameterType->isBuiltin(); |
|
|
|
|
return $this->query($resolveName, !$builtIn); |
|
|
|
|
} catch (QueryException $e) { |
|
|
|
|
} catch (ContainerExceptionInterface $e) { |
|
|
|
|
// Service not found, use the default value when available |
|
|
|
|
if ($parameter->isDefaultValueAvailable()) { |
|
|
|
|
return $parameter->getDefaultValue(); |
|
|
|
@ -82,7 +97,7 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { |
|
|
|
|
$resolveName = $parameter->getName(); |
|
|
|
|
try { |
|
|
|
|
return $this->query($resolveName); |
|
|
|
|
} catch (QueryException $e2) { |
|
|
|
|
} catch (ContainerExceptionInterface $e2) { |
|
|
|
|
// Pass null if typed and nullable |
|
|
|
|
if ($parameter->allowsNull() && ($parameterType instanceof ReflectionNamedType)) { |
|
|
|
|
return null; |
|
|
|
@ -95,7 +110,7 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { |
|
|
|
|
|
|
|
|
|
throw $e; |
|
|
|
|
} |
|
|
|
|
}, $constructor->getParameters())); |
|
|
|
|
}, $constructor->getParameters()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function resolve($name) { |
|
|
|
|