* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; /** * @author Nicolas Grekas */ class RegisterReverseContainerPass implements CompilerPassInterface { private $beforeRemoving; private $serviceId; private $tagName; public function __construct(bool $beforeRemoving, string $serviceId = 'reverse_container', string $tagName = 'container.reversible') { $this->beforeRemoving = $beforeRemoving; $this->serviceId = $serviceId; $this->tagName = $tagName; } public function process(ContainerBuilder $container) { if (!$container->hasDefinition($this->serviceId)) { return; } $refType = $this->beforeRemoving ? ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; $services = []; foreach ($container->findTaggedServiceIds($this->tagName) as $id => $tags) { $services[$id] = new Reference($id, $refType); } if ($this->beforeRemoving) { // prevent inlining of the reverse container $services[$this->serviceId] = new Reference($this->serviceId, $refType); } $locator = $container->getDefinition($this->serviceId)->getArgument(1); if ($locator instanceof Reference) { $locator = $container->getDefinition((string) $locator); } if ($locator instanceof Definition) { foreach ($services as $id => $ref) { $services[$id] = new ServiceClosureArgument($ref); } $locator->replaceArgument(0, $services); } else { $locator->setValues($services); } } }