| Current Path : /var/www/surf/TYPO3/vendor/typo3/cms-core/Classes/DependencyInjection/ |
| Current File : /var/www/surf/TYPO3/vendor/typo3/cms-core/Classes/DependencyInjection/ServiceProviderRegistry.php |
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\DependencyInjection;
use Psr\Container\ContainerInterface;
use TYPO3\CMS\Core\Package\Package;
use TYPO3\CMS\Core\Package\PackageManager;
/**
* A class that holds the list of service providers of a project.
* This class is designed so that service provider do not need to be instantiated each time the registry is filled.
* They can be lazily instantiated if needed.
* @internal
*/
class ServiceProviderRegistry implements \IteratorAggregate
{
/**
* @var PackageManager
*/
private $packageManager;
/**
* @var bool
*/
private $failsafe;
/**
* The array with constructed values.
*
* @var array An array<packageKey, ServiceProviderInterface>
*/
private $instances;
/**
* An array of service factories (the result of the call to 'getFactories'),
* indexed by service provider.
*
* @var array An array<packageKey, array<servicename, callable>>
*/
private $serviceFactories = [];
/**
* An array of service extensions (the result of the call to 'getExtensions'),
* indexed by service provider.
*
* @var array An array<packageKey, array<servicename, callable>>
*/
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));
}
}
}