mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-29 08:00:28 +01:00
155 lines
4.0 KiB
PHP
155 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace Xentral\Core\DependencyInjection;
|
|
|
|
use Xentral\Components\Logger\LoggerAwareTrait;
|
|
use Xentral\Core\DependencyInjection\Definition\FactoryMethodDefinition;
|
|
use Xentral\Core\DependencyInjection\Exception\InvalidArgumentException;
|
|
use Xentral\Core\DependencyInjection\Exception\ServiceNotFoundException;
|
|
|
|
final class ServiceRegistry extends AbstractBaseContainer
|
|
{
|
|
/** @var array $services Storage for service instances */
|
|
private $services = [];
|
|
|
|
/** @var FactoryMethodDefinition[] $factories Storage for factory methods */
|
|
private $factories = [];
|
|
|
|
/**
|
|
* @param array $factoryMethods
|
|
*/
|
|
public function __construct(array $factoryMethods = [])
|
|
{
|
|
$this->addFactories($factoryMethods);
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function has($name)
|
|
{
|
|
return $this->hasService($name) || $this->hasFactory($name);
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
*
|
|
* @throws ServiceNotFoundException
|
|
*
|
|
* @return object|mixed
|
|
*/
|
|
public function get($name)
|
|
{
|
|
if ($this->hasService($name)) {
|
|
return $this->services[$name];
|
|
}
|
|
|
|
if ($this->hasFactory($name)) {
|
|
$definition = $this->factories[$name];
|
|
$factoryMethod = $definition->getCallable();
|
|
$serviceInstance = $factoryMethod($this->get('ServiceContainer'));
|
|
//inject Logger if required
|
|
if (
|
|
$this->has('Logger')
|
|
&& in_array(LoggerAwareTrait::class, class_uses($serviceInstance), true)
|
|
) {
|
|
/** @var LoggerAwareTrait $serviceInstance */
|
|
$serviceInstance->setLogger($this->get('Logger'));
|
|
}
|
|
|
|
// Don't save non-shared services
|
|
if (!$definition->isShared()) {
|
|
return $serviceInstance;
|
|
}
|
|
|
|
// Save shared services
|
|
$this->add($name, $serviceInstance);
|
|
|
|
return $this->services[$name];
|
|
}
|
|
|
|
throw new ServiceNotFoundException(sprintf(
|
|
'Service "%s" was not found.', $name
|
|
));
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @param object $instance
|
|
*
|
|
* @throws InvalidArgumentException
|
|
*/
|
|
public function add($name, $instance)
|
|
{
|
|
if (!is_object($instance)) {
|
|
throw new InvalidArgumentException(sprintf(
|
|
'%s could not be added. Only objects can be added to container.', $name
|
|
));
|
|
}
|
|
|
|
$this->services[$name] = $instance;
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function hasFactory($name)
|
|
{
|
|
return isset($this->factories[$name]);
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @param callable $callable
|
|
* @param bool $shared
|
|
*
|
|
* @throws InvalidArgumentException
|
|
*/
|
|
public function addFactory($name, $callable, $shared = true)
|
|
{
|
|
if (!is_callable($callable, true)) {
|
|
throw new InvalidArgumentException(sprintf(
|
|
'Factory "%s" can not be added. Second argument must be a callable.', $name
|
|
));
|
|
}
|
|
|
|
if (!is_string($name)) {
|
|
throw new InvalidArgumentException(sprintf(
|
|
'Factory "%s" can not be added. Factory name must be a string.', $name
|
|
));
|
|
}
|
|
|
|
if ($this->hasFactory($name)) {
|
|
throw new InvalidArgumentException(sprintf(
|
|
'Factory "%s" can not be added. Factory is already present.', $name
|
|
));
|
|
}
|
|
|
|
$this->factories[$name] = new FactoryMethodDefinition($callable, $shared);
|
|
}
|
|
|
|
/**
|
|
* @param array|\Iterator $factories
|
|
*/
|
|
public function addFactories($factories)
|
|
{
|
|
foreach ($factories as $name => $callable) {
|
|
$this->addFactory($name, $callable, true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
*
|
|
* @return bool
|
|
*/
|
|
private function hasService($name)
|
|
{
|
|
return isset($this->services[$name]);
|
|
}
|
|
}
|