Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[DI] add ServiceLocatorTagPass::register() to share service locators #22175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@

namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;

class TranslatorPass implements CompilerPassInterface
{
Expand Down Expand Up @@ -46,7 +45,7 @@ public function process(ContainerBuilder $container)

$container
->findDefinition('translator.default')
->replaceArgument(0, (new Definition(ServiceLocator::class, array($loaderRefs)))->addTag('container.service_locator'))
->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs))
->replaceArgument(3, $loaders)
;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ public function testThatConstraintValidatorServicesAreProcessed()
$addConstraintValidatorsPass = new AddConstraintValidatorsPass();
$addConstraintValidatorsPass->process($container);

$this->assertEquals((new Definition(ServiceLocator::class, array(array(
$expected = (new Definition(ServiceLocator::class, array(array(
Validator1::class => new ServiceClosureArgument(new Reference('my_constraint_validator_service1')),
'my_constraint_validator_alias1' => new ServiceClosureArgument(new Reference('my_constraint_validator_service1')),
Validator2::class => new ServiceClosureArgument(new Reference('my_constraint_validator_service2')),
))))->addTag('container.service_locator'), $validatorFactory->getArgument(0));
))))->addTag('container.service_locator')->setPublic(false);
$this->assertEquals($expected, $container->getDefinition((string) $validatorFactory->getArgument(0)));
}

public function testThatCompilerPassIsIgnoredIfThereIsNoConstraintValidatorFactoryDefinition()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function testAddTaggedTypes()
(new Definition(ServiceLocator::class, array(array(
__CLASS__.'_Type1' => new ServiceClosureArgument(new Reference('my.type1')),
__CLASS__.'_Type2' => new ServiceClosureArgument(new Reference('my.type2')),
))))->addTag('container.service_locator'),
))))->addTag('container.service_locator')->setPublic(false),
$extDefinition->getArgument(0)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,45 +12,39 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;

use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
use Symfony\Component\DependencyInjection\ServiceLocator;

class TranslatorPassTest extends TestCase
{
public function testValidCollector()
{
$definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
$definition->expects($this->at(0))
->method('addMethodCall')
->with('addLoader', array('xliff', new Reference('xliff')));
$definition->expects($this->at(1))
->method('addMethodCall')
->with('addLoader', array('xlf', new Reference('xliff')));

$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'findDefinition'))->getMock();
$container->expects($this->any())
->method('hasDefinition')
->will($this->returnValue(true));
$container->expects($this->once())
->method('getDefinition')
->will($this->returnValue($definition));
$container->expects($this->once())
->method('findTaggedServiceIds')
->will($this->returnValue(array('xliff' => array(array('alias' => 'xliff', 'legacy-alias' => 'xlf')))));
$container->expects($this->once())
->method('findDefinition')
->will($this->returnValue($translator = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock()));
$translator->expects($this->at(0))
->method('replaceArgument')
->with(0, $this->equalTo((new Definition(ServiceLocator::class, array(array('xliff' => new Reference('xliff')))))->addTag('container.service_locator')))
->willReturn($translator);
$translator->expects($this->at(1))
->method('replaceArgument')
->with(3, array('xliff' => array('xliff', 'xlf')))
->willReturn($translator);
$loader = (new Definition())
->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf'));

$translator = (new Definition())
->setArguments(array(null, null, null, null));

$container = new ContainerBuilder();
$container->setDefinition('translator.default', $translator);
$container->setDefinition('translation.loader', $loader);

$pass = new TranslatorPass();
$pass->process($container);

$expected = (new Definition())
->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf'))
->addMethodCall('addLoader', array('xliff', new Reference('translation.loader')))
->addMethodCall('addLoader', array('xlf', new Reference('translation.loader')))
;
$this->assertEquals($expected, $loader);

$this->assertSame(array('translation.loader' => array('xliff', 'xlf')), $translator->getArgument(3));

$expected = array('translation.loader' => new ServiceClosureArgument(new Reference('translation.loader')));
$this->assertEquals($expected, $container->getDefinition((string) $translator->getArgument(0))->getArgument(0));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@
use Symfony\Component\Console\Application;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;

Expand Down Expand Up @@ -262,10 +261,10 @@ private function createFirewalls($config, ContainerBuilder $container)
->replaceArgument(2, new Reference($configId))
;

$contextRefs[$contextId] = new ServiceClosureArgument(new Reference($contextId));
$contextRefs[$contextId] = new Reference($contextId);
$map[$contextId] = $matcher;
}
$mapDef->replaceArgument(0, (new Definition(ServiceLocator::class, array($contextRefs)))->addTag('container.service_locator'));
$mapDef->replaceArgument(0, ServiceLocatorTagPass::register($container, $contextRefs));
$mapDef->replaceArgument(1, new IteratorArgument($map));

// add authentication providers to authentication manager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@

namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ServiceLocator;

/**
* Registers Twig runtime services.
Expand All @@ -38,9 +36,9 @@ public function process(ContainerBuilder $container)
continue;
}

$mapping[$def->getClass()] = new ServiceClosureArgument(new Reference($id));
$mapping[$def->getClass()] = new Reference($id);
}

$definition->replaceArgument(0, (new Definition(ServiceLocator::class, array($mapping)))->addTag('container.service_locator'));
$definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $mapping));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public function testRuntimeLoader()
$container->compile();

$loader = $container->getDefinition('twig.runtime_loader');
$args = $loader->getArgument(0)->getArgument(0);
$args = $container->getDefinition((string) $loader->getArgument(0))->getArgument(0);
$this->assertArrayHasKey('Symfony\Bridge\Twig\Form\TwigRenderer', $args);
$this->assertArrayHasKey('FooClass', $args);
$this->assertEquals('twig.form.renderer', $args['Symfony\Bridge\Twig\Form\TwigRenderer']->getValues()[0]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

namespace Symfony\Component\DependencyInjection\Argument;

use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;

/**
* Represents a service wrapped in a memoizing closure.
Expand All @@ -28,11 +28,17 @@ public function __construct(Reference $reference)
$this->values = array($reference);
}

/**
* {@inheritdoc}
*/
public function getValues()
{
return $this->values;
}

/**
* {@inheritdoc}
*/
public function setValues(array $values)
{
if (array(0) !== array_keys($values) || !($values[0] instanceof Reference || null === $values[0])) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\DependencyInjection\TypedReference;

/**
Expand Down Expand Up @@ -87,7 +85,7 @@ protected function processValue($value, $isRoot = false)
$serviceMap[$key] = new Reference($type);
}

$subscriberMap[$key] = new ServiceClosureArgument(new TypedReference((string) $serviceMap[$key], $type, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE));
$subscriberMap[$key] = new TypedReference((string) $serviceMap[$key], $type, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
unset($serviceMap[$key]);
}

Expand All @@ -97,12 +95,7 @@ protected function processValue($value, $isRoot = false)
}

$serviceLocator = $this->serviceLocator;
$this->serviceLocator = 'container.'.$this->currentId.'.'.md5(serialize($value));
$this->container->register($this->serviceLocator, ServiceLocator::class)
->addArgument($subscriberMap)
->setPublic(false)
->setAutowired($value->isAutowired())
->addTag('container.service_locator');
$this->serviceLocator = (string) ServiceLocatorTagPass::register($this->container, $subscriberMap, $value->getAutowired());

try {
return parent::processValue($value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
Expand All @@ -22,7 +24,7 @@
*
* @author Nicolas Grekas <p@tchwork.com>
*/
class ServiceLocatorTagPass extends AbstractRecursivePass
final class ServiceLocatorTagPass extends AbstractRecursivePass
{
protected function processValue($value, $isRoot = false)
{
Expand All @@ -48,7 +50,52 @@ protected function processValue($value, $isRoot = false)
}
$arguments[0][$k] = new ServiceClosureArgument($v);
}
ksort($arguments[0]);

return $value->setArguments($arguments);
$value->setArguments($arguments);

if ($public = $value->isPublic()) {
$value->setPublic(false);
}
$id = 'service_locator.'.md5(serialize($value));

if ($isRoot) {
if ($id !== $this->currentId) {
$this->container->setAlias($id, new Alias($this->currentId, $public));
}

return $value;
}

$this->container->setDefinition($id, $value);

return new Reference($id);
}

/**
* @param ContainerBuilder $container
* @param Reference[] $refMap
* @param int|bool $autowired
*
* @return Reference
*/
public static function register(ContainerBuilder $container, array $refMap, $autowired = false)
{
foreach ($refMap as $id => $ref) {
$refMap[$id] = new ServiceClosureArgument($ref);
}
ksort($refMap);

$locator = (new Definition(ServiceLocator::class))
->addArgument($refMap)
->setPublic(false)
->setAutowired($autowired)
->addTag('container.service_locator');

if (!$container->has($id = 'service_locator.'.md5(serialize($locator)))) {
$container->setDefinition($id, $locator);
}

return new Reference($id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ protected function getFooServiceService()
{
return $this->services['foo_service'] = new \TestServiceSubscriber(new \Symfony\Component\DependencyInjection\ServiceLocator(array('TestServiceSubscriber' => function () {
$f = function (\TestServiceSubscriber $v) { return $v; }; return $f(${($_ = isset($this->services['TestServiceSubscriber']) ? $this->services['TestServiceSubscriber'] : $this->get('TestServiceSubscriber')) && false ?: '_'});
}, 'stdClass' => function () {
$f = function (\stdClass $v = null) { return $v; }; return $f(${($_ = isset($this->services['autowired.stdClass']) ? $this->services['autowired.stdClass'] : $this->getAutowired_StdClassService()) && false ?: '_'});
}, 'bar' => function () {
$f = function (\stdClass $v) { return $v; }; return $f(${($_ = isset($this->services['TestServiceSubscriber']) ? $this->services['TestServiceSubscriber'] : $this->get('TestServiceSubscriber')) && false ?: '_'});
}, 'baz' => function () {
$f = function (\stdClass $v = null) { return $v; }; return $f(${($_ = isset($this->services['autowired.stdClass']) ? $this->services['autowired.stdClass'] : $this->getAutowired_StdClassService()) && false ?: '_'});
}, 'stdClass' => function () {
$f = function (\stdClass $v = null) { return $v; }; return $f(${($_ = isset($this->services['autowired.stdClass']) ? $this->services['autowired.stdClass'] : $this->getAutowired_StdClassService()) && false ?: '_'});
})));
}

Expand Down
8 changes: 3 additions & 5 deletions 8 src/Symfony/Component/Form/DependencyInjection/FormPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@
namespace Symfony\Component\Form\DependencyInjection;

use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ServiceLocator;

/**
* Adds all services with the tags "form.type", "form.type_extension" and
Expand Down Expand Up @@ -60,17 +59,16 @@ private function processFormTypes(ContainerBuilder $container, Definition $defin
{
// Get service locator argument
$servicesMap = array();
$locator = $definition->getArgument(0);

// Builds an array with fully-qualified type class names as keys and service IDs as values
foreach ($container->findTaggedServiceIds($this->formTypeTag) as $serviceId => $tag) {
$serviceDefinition = $container->getDefinition($serviceId);

// Add form type service to the service locator
$servicesMap[$serviceDefinition->getClass()] = new ServiceClosureArgument(new Reference($serviceId));
$servicesMap[$serviceDefinition->getClass()] = new Reference($serviceId);
}

return (new Definition(ServiceLocator::class, array($servicesMap)))->addTag('container.service_locator');
return ServiceLocatorTagPass::register($container, $servicesMap);
}

private function processFormTypeExtensions(ContainerBuilder $container)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function testAddTaggedTypes()
(new Definition(ServiceLocator::class, array(array(
__CLASS__.'_Type1' => new ServiceClosureArgument(new Reference('my.type1')),
__CLASS__.'_Type2' => new ServiceClosureArgument(new Reference('my.type2')),
))))->addTag('container.service_locator'),
))))->addTag('container.service_locator')->setPublic(false),
$extDefinition->getArgument(0)
);
}
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.