| Current Path : /var/www/clients/client3/web2/web/vendor/laminas/laminas-di/src/ |
| Current File : /var/www/clients/client3/web2/web/vendor/laminas/laminas-di/src/Injector.php |
<?php
declare(strict_types=1);
namespace Laminas\Di;
use Laminas\Di\Definition\DefinitionInterface;
use Laminas\Di\Exception\ClassNotFoundException;
use Laminas\Di\Exception\InvalidCallbackException;
use Laminas\Di\Exception\RuntimeException;
use Laminas\Di\Resolver\DependencyResolverInterface;
use Laminas\Di\Resolver\InjectionInterface;
use Laminas\Di\Resolver\TypeInjection;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use function array_pop;
use function class_exists;
use function implode;
use function in_array;
use function sprintf;
/**
* Dependency injector that can generate instances using class definitions and configured instance parameters
*/
class Injector implements InjectorInterface
{
/** @var DefinitionInterface */
protected $definition;
/** @var ContainerInterface */
protected $container;
/** @var DependencyResolverInterface */
protected $resolver;
/** @var ConfigInterface */
protected $config;
/** @var string[] */
protected $instantiationStack = [];
/**
* Constructor
*
* @param ConfigInterface|null $config A custom configuration to utilize. An empty configuration is used
* when null is passed or the parameter is omitted.
* @param ContainerInterface|null $container The IoC container to retrieve dependency instances.
* `Laminas\Di\DefaultContainer` is used when null is passed or the parameter is omitted.
* @param null|DefinitionInterface $definition A custom definition instance for creating requested
* instances. The runtime definition is used when null is passed or the parameter is omitted.
* @param DependencyResolverInterface|null $resolver A custom resolver instance to resolve dependencies.
* The default resolver is used when null is passed or the parameter is omitted
*/
public function __construct(
?ConfigInterface $config = null,
?ContainerInterface $container = null,
?DefinitionInterface $definition = null,
?DependencyResolverInterface $resolver = null
) {
$this->definition = $definition ?: new Definition\RuntimeDefinition();
$this->config = $config ?: new Config();
$this->resolver = $resolver ?: new Resolver\DependencyResolver($this->definition, $this->config);
$this->setContainer($container ?: new DefaultContainer($this));
}
/**
* Set the ioc container
*
* Sets the ioc container to utilize for fetching instances of dependencies
*
* @return $this
*/
public function setContainer(ContainerInterface $container)
{
$this->resolver->setContainer($container);
$this->container = $container;
return $this;
}
public function getContainer(): ContainerInterface
{
return $this->container;
}
/**
* Returns the class name for the requested type
*/
private function getClassName(string $type): string
{
if ($this->config->isAlias($type)) {
return $this->config->getClassForAlias($type) ?? $type;
}
return $type;
}
/**
* Check if the given type name can be instantiated
*
* This will be the case if the name points to a class.
*/
public function canCreate(string $name): bool
{
$class = $this->getClassName($name);
return class_exists($class);
}
/**
* Create the instance with auto wiring
*
* @param string $name Class name or service alias
* @param array<string, mixed> $parameters Constructor parameters, keyed by the parameter name.
* @return object
* @throws ClassNotFoundException
* @throws RuntimeException
*/
public function create(string $name, array $parameters = [])
{
if (in_array($name, $this->instantiationStack)) {
throw new Exception\CircularDependencyException(sprintf(
'Circular dependency: %s -> %s',
implode(' -> ', $this->instantiationStack),
$name
));
}
$this->instantiationStack[] = $name;
try {
$instance = $this->createInstance($name, $parameters);
} finally {
array_pop($this->instantiationStack);
}
return $instance;
}
/**
* Retrieve a class instance based on the type name
*
* Any parameters provided will be used as constructor arguments only.
*
* @param string $name The type name to instantiate.
* @param array<string, mixed> $params Constructor arguments, keyed by the parameter name.
* @return object
* @throws InvalidCallbackException
* @throws ClassNotFoundException
*/
protected function createInstance(string $name, array $params)
{
$class = $this->getClassName($name);
if (! $this->definition->hasClass($class)) {
$aliasMsg = $name !== $class ? ' (specified by alias ' . $name . ')' : '';
throw new ClassNotFoundException(sprintf(
'Class %s%s could not be located in provided definitions.',
$class,
$aliasMsg
));
}
if (! class_exists($class)) {
throw new ClassNotFoundException(sprintf(
'Class by name %s does not exist',
$class
));
}
$callParameters = $this->resolveParameters($name, $params);
return new $class(...$callParameters);
}
/**
* @return mixed The value to inject into the instance
*/
private function getInjectionValue(InjectionInterface $injection)
{
$container = $this->container;
$containerTypes = [
ContainerInterface::class,
// Be backwards compatible with interop/container:
'Interop\Container\ContainerInterface', // phpcs:ignore
];
if (
$injection instanceof TypeInjection
&& ! $container->has((string) $injection)
&& in_array((string) $injection, $containerTypes, true)
) {
return $container;
}
return $injection->toValue($container);
}
/**
* Resolve parameters
*
* At first this method utilizes the resolver to obtain the types to inject.
* If this was successful (the resolver returned a non-null value), it will use
* the ioc container to fetch the instances
*
* @param string $type The class or alias name to resolve for
* @param array<string, mixed> $params Provided call time parameters
* @return list<mixed> The resulting arguments in call order
* @throws Exception\UndefinedReferenceException When a type cannot be
* obtained via the ioc container and the method is required for
* injection.
* @throws Exception\CircularDependencyException When a circular dependency is detected.
*/
private function resolveParameters(string $type, array $params = []): array
{
$resolved = $this->resolver->resolveParameters($type, $params);
$params = [];
foreach ($resolved as $injection) {
try {
$params[] = $this->getInjectionValue($injection);
} catch (NotFoundExceptionInterface $containerException) {
throw new Exception\UndefinedReferenceException(
$containerException->getMessage(),
$containerException->getCode(),
$containerException
);
}
}
return $params;
}
}