*/ private $instances; /** * An array of service factories (the result of the call to 'getFactories'), * indexed by service provider. * * @var array An array> */ private $serviceFactories = []; /** * An array of service extensions (the result of the call to 'getExtensions'), * indexed by service provider. * * @var array An array> */ private $serviceExtensions = []; /** * Initializes the registry from a list of service providers. * This list of service providers can be passed as ServiceProvider instances, class name string, * or an array of ['class name', [constructor params...]]. */ public function __construct(PackageManager $packageManager, bool $failsafe = false) { $this->packageManager = $packageManager; $this->failsafe = $failsafe; } /** * Whether an id exists. * * @param string $packageKey Key of the service provider in the registry * @return bool true on success or false on failure. */ public function has(string $packageKey): bool { if (isset($this->instances[$packageKey])) { return true; } if ($this->packageManager->isPackageActive($packageKey)) { if ($this->failsafe && $this->packageManager->getPackage($packageKey)->isPartOfMinimalUsableSystem() === false) { return false; } return true; } return false; } /** * Returns service provider by id. * * @param string $packageKey Key of the service provider in the registry */ public function get(string $packageKey): ServiceProviderInterface { return $this->instances[$packageKey] ?? $this->create($packageKey); } /** * Returns service provider by id. * * @param string $packageKey Key of the service provider in the registry * @param Package|null $package */ private function create(string $packageKey, ?Package $package = null): ServiceProviderInterface { if ($package === null) { if (!$this->packageManager->isPackageActive($packageKey)) { throw new \InvalidArgumentException('Package ' . $packageKey . ' is not active', 1550351445); } $package = $this->packageManager->getPackage($packageKey); } $serviceProviderClassName = $package->getServiceProvider(); $instance = new $serviceProviderClassName($package); if (!$instance instanceof ServiceProviderInterface) { throw new \InvalidArgumentException('Service providers need to implement ' . ServiceProviderInterface::class, 1550302554); } return $this->instances[$packageKey] = $instance; } /** * Returns the result of the getFactories call on service provider whose key in the registry is $packageKey. * The result is cached in the registry so two successive calls will trigger `getFactories` only once. * * @param string $packageKey Key of the service provider in the registry */ public function getFactories(string $packageKey): array { return $this->serviceFactories[$packageKey] ?? ($this->serviceFactories[$packageKey] = $this->get($packageKey)->getFactories()); } /** * Returns the result of the getExtensions call on service provider whose key in the registry is $packageKey. * The result is cached in the registry so two successive calls will trigger `getExtensions` only once. * * @param string $packageKey Key of the service provider in the registry */ public function getExtensions(string $packageKey): array { return $this->serviceExtensions[$packageKey] ?? ($this->serviceExtensions[$packageKey] = $this->get($packageKey)->getExtensions()); } /** * @param string $packageKey Key of the service provider in the registry * @param string $serviceName Name of the service to fetch * @return mixed */ public function createService(string $packageKey, string $serviceName, ContainerInterface $container) { $factory = $this->getFactories($packageKey)[$serviceName]; return $factory($container); } /** * @param string $packageKey Key of the service provider in the registry * @param string $serviceName Name of the service to fetch * @param mixed $previous * @return mixed */ public function extendService(string $packageKey, string $serviceName, ContainerInterface $container, $previous = null) { $extension = $this->getExtensions($packageKey)[$serviceName]; return $extension($container, $previous); } public function getIterator(): \Generator { foreach ($this->packageManager->getActivePackages() as $package) { if ($this->failsafe && $package->isPartOfMinimalUsableSystem() === false) { continue; } $packageKey = $package->getPackageKey(); yield $packageKey => ($this->instances[$packageKey] ?? $this->create($packageKey, $package)); } } }