Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 31657cc

Browse files
[DI] add ServiceClosureArgument::register() to share service locators
1 parent d0e904b commit 31657cc

File tree

21 files changed

+177
-159
lines changed

21 files changed

+177
-159
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslatorPass.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
1313

14-
use Symfony\Component\DependencyInjection\Definition;
1514
use Symfony\Component\DependencyInjection\Reference;
1615
use Symfony\Component\DependencyInjection\ContainerBuilder;
1716
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
18-
use Symfony\Component\DependencyInjection\ServiceLocator;
17+
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
1918

2019
class TranslatorPass implements CompilerPassInterface
2120
{
@@ -46,7 +45,7 @@ public function process(ContainerBuilder $container)
4645

4746
$container
4847
->findDefinition('translator.default')
49-
->replaceArgument(0, (new Definition(ServiceLocator::class, array($loaderRefs)))->addTag('container.service_locator'))
48+
->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs))
5049
->replaceArgument(3, $loaders)
5150
;
5251
}

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,12 @@ public function testThatConstraintValidatorServicesAreProcessed()
4141
$addConstraintValidatorsPass = new AddConstraintValidatorsPass();
4242
$addConstraintValidatorsPass->process($container);
4343

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

5152
public function testThatCompilerPassIsIgnoredIfThereIsNoConstraintValidatorFactoryDefinition()

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public function testAddTaggedTypes()
5353
(new Definition(ServiceLocator::class, array(array(
5454
__CLASS__.'_Type1' => new ServiceClosureArgument(new Reference('my.type1')),
5555
__CLASS__.'_Type2' => new ServiceClosureArgument(new Reference('my.type2')),
56-
))))->addTag('container.service_locator'),
56+
))))->addTag('container.service_locator')->setPublic(false),
5757
$extDefinition->getArgument(0)
5858
);
5959
}

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,45 +12,39 @@
1212
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
16+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
17+
use Symfony\Component\DependencyInjection\ContainerBuilder;
1518
use Symfony\Component\DependencyInjection\Definition;
1619
use Symfony\Component\DependencyInjection\Reference;
17-
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
18-
use Symfony\Component\DependencyInjection\ServiceLocator;
1920

2021
class TranslatorPassTest extends TestCase
2122
{
2223
public function testValidCollector()
2324
{
24-
$definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
25-
$definition->expects($this->at(0))
26-
->method('addMethodCall')
27-
->with('addLoader', array('xliff', new Reference('xliff')));
28-
$definition->expects($this->at(1))
29-
->method('addMethodCall')
30-
->with('addLoader', array('xlf', new Reference('xliff')));
31-
32-
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'findDefinition'))->getMock();
33-
$container->expects($this->any())
34-
->method('hasDefinition')
35-
->will($this->returnValue(true));
36-
$container->expects($this->once())
37-
->method('getDefinition')
38-
->will($this->returnValue($definition));
39-
$container->expects($this->once())
40-
->method('findTaggedServiceIds')
41-
->will($this->returnValue(array('xliff' => array(array('alias' => 'xliff', 'legacy-alias' => 'xlf')))));
42-
$container->expects($this->once())
43-
->method('findDefinition')
44-
->will($this->returnValue($translator = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock()));
45-
$translator->expects($this->at(0))
46-
->method('replaceArgument')
47-
->with(0, $this->equalTo((new Definition(ServiceLocator::class, array(array('xliff' => new Reference('xliff')))))->addTag('container.service_locator')))
48-
->willReturn($translator);
49-
$translator->expects($this->at(1))
50-
->method('replaceArgument')
51-
->with(3, array('xliff' => array('xliff', 'xlf')))
52-
->willReturn($translator);
25+
$loader = (new Definition())
26+
->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf'));
27+
28+
$translator = (new Definition())
29+
->setArguments(array(null, null, null, null));
30+
31+
$container = new ContainerBuilder();
32+
$container->setDefinition('translator.default', $translator);
33+
$container->setDefinition('translation.loader', $loader);
34+
5335
$pass = new TranslatorPass();
5436
$pass->process($container);
37+
38+
$expected = (new Definition())
39+
->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf'))
40+
->addMethodCall('addLoader', array('xliff', new Reference('translation.loader')))
41+
->addMethodCall('addLoader', array('xlf', new Reference('translation.loader')))
42+
;
43+
$this->assertEquals($expected, $loader);
44+
45+
$this->assertSame(array('translation.loader' => array('xliff', 'xlf')), $translator->getArgument(3));
46+
47+
$expected = array('translation.loader' => new ServiceClosureArgument(new Reference('translation.loader')));
48+
$this->assertEquals($expected, $container->getDefinition((string) $translator->getArgument(0))->getArgument(0));
5549
}
5650
}

src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,13 @@
1717
use Symfony\Component\Console\Application;
1818
use Symfony\Component\DependencyInjection\Alias;
1919
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
20-
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
2120
use Symfony\Component\DependencyInjection\ChildDefinition;
21+
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
2222
use Symfony\Component\DependencyInjection\Definition;
2323
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
2424
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
2525
use Symfony\Component\DependencyInjection\ContainerBuilder;
2626
use Symfony\Component\DependencyInjection\Reference;
27-
use Symfony\Component\DependencyInjection\ServiceLocator;
2827
use Symfony\Component\Config\FileLocator;
2928
use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
3029

@@ -262,10 +261,10 @@ private function createFirewalls($config, ContainerBuilder $container)
262261
->replaceArgument(2, new Reference($configId))
263262
;
264263

265-
$contextRefs[$contextId] = new ServiceClosureArgument(new Reference($contextId));
264+
$contextRefs[$contextId] = new Reference($contextId);
266265
$map[$contextId] = $matcher;
267266
}
268-
$mapDef->replaceArgument(0, (new Definition(ServiceLocator::class, array($contextRefs)))->addTag('container.service_locator'));
267+
$mapDef->replaceArgument(0, ServiceLocatorTagPass::register($container, $contextRefs));
269268
$mapDef->replaceArgument(1, new IteratorArgument($map));
270269

271270
// add authentication providers to authentication manager

src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/RuntimeLoaderPass.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@
1111

1212
namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler;
1313

14-
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1514
use Symfony\Component\DependencyInjection\ContainerBuilder;
1615
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16+
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
1717
use Symfony\Component\DependencyInjection\Reference;
18-
use Symfony\Component\DependencyInjection\Definition;
19-
use Symfony\Component\DependencyInjection\ServiceLocator;
2018

2119
/**
2220
* Registers Twig runtime services.
@@ -38,9 +36,9 @@ public function process(ContainerBuilder $container)
3836
continue;
3937
}
4038

41-
$mapping[$def->getClass()] = new ServiceClosureArgument(new Reference($id));
39+
$mapping[$def->getClass()] = new Reference($id);
4240
}
4341

44-
$definition->replaceArgument(0, (new Definition(ServiceLocator::class, array($mapping)))->addTag('container.service_locator'));
42+
$definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $mapping));
4543
}
4644
}

src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ public function testRuntimeLoader()
244244
$container->compile();
245245

246246
$loader = $container->getDefinition('twig.runtime_loader');
247-
$args = $loader->getArgument(0)->getArgument(0);
247+
$args = $container->getDefinition((string) $loader->getArgument(0))->getArgument(0);
248248
$this->assertArrayHasKey('Symfony\Bridge\Twig\Form\TwigRenderer', $args);
249249
$this->assertArrayHasKey('FooClass', $args);
250250
$this->assertEquals('twig.form.renderer', $args['Symfony\Bridge\Twig\Form\TwigRenderer']->getValues()[0]);

src/Symfony/Component/DependencyInjection/Argument/ServiceClosureArgument.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Argument;
1313

14-
use Symfony\Component\DependencyInjection\Reference;
1514
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
15+
use Symfony\Component\DependencyInjection\Reference;
1616

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

31+
/**
32+
* {@inheritdoc}
33+
*/
3134
public function getValues()
3235
{
3336
return $this->values;
3437
}
3538

39+
/**
40+
* {@inheritdoc}
41+
*/
3642
public function setValues(array $values)
3743
{
3844
if (array(0) !== array_keys($values) || !($values[0] instanceof Reference || null === $values[0])) {

src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

14-
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
14+
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
1515
use Symfony\Component\DependencyInjection\ContainerInterface;
1616
use Symfony\Component\DependencyInjection\Definition;
1717
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1818
use Symfony\Component\DependencyInjection\Reference;
1919
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
20-
use Symfony\Component\DependencyInjection\ServiceLocator;
2120
use Symfony\Component\DependencyInjection\TypedReference;
2221

2322
/**
@@ -87,7 +86,7 @@ protected function processValue($value, $isRoot = false)
8786
$serviceMap[$key] = new Reference($type);
8887
}
8988

90-
$subscriberMap[$key] = new ServiceClosureArgument(new TypedReference((string) $serviceMap[$key], $type, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE));
89+
$subscriberMap[$key] = new TypedReference((string) $serviceMap[$key], $type, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
9190
unset($serviceMap[$key]);
9291
}
9392

@@ -96,12 +95,7 @@ protected function processValue($value, $isRoot = false)
9695
}
9796

9897
$serviceLocator = $this->serviceLocator;
99-
$this->serviceLocator = 'container.'.$this->currentId.'.'.md5(serialize($value));
100-
$this->container->register($this->serviceLocator, ServiceLocator::class)
101-
->addArgument($subscriberMap)
102-
->setPublic(false)
103-
->setAutowired($value->isAutowired())
104-
->addTag('container.service_locator');
98+
$this->serviceLocator = (string) ServiceLocatorTagPass::register($this->container, $subscriberMap, $value->getAutowired());
10599

106100
try {
107101
return parent::processValue($value);

src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

14+
use Symfony\Component\DependencyInjection\Alias;
1415
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
1517
use Symfony\Component\DependencyInjection\Definition;
1618
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1719
use Symfony\Component\DependencyInjection\Reference;
@@ -22,7 +24,7 @@
2224
*
2325
* @author Nicolas Grekas <[email protected]>
2426
*/
25-
class ServiceLocatorTagPass extends AbstractRecursivePass
27+
final class ServiceLocatorTagPass extends AbstractRecursivePass
2628
{
2729
protected function processValue($value, $isRoot = false)
2830
{
@@ -48,7 +50,51 @@ protected function processValue($value, $isRoot = false)
4850
}
4951
$arguments[0][$k] = new ServiceClosureArgument($v);
5052
}
53+
ksort($arguments[0]);
5154

52-
return $value->setArguments($arguments);
55+
$value->setArguments($arguments);
56+
57+
if ($public = $value->isPublic()) {
58+
$value->setPublic(false);
59+
}
60+
$id = 'service_locator.'.md5(serialize($value));
61+
62+
if ($isRoot) {
63+
if ($id !== $this->currentId) {
64+
$this->container->setAlias($id, new Alias($this->currentId, $public));
65+
}
66+
67+
return $value;
68+
}
69+
70+
$this->container->setDefinition($id, $value);
71+
72+
return new Reference($id);
73+
}
74+
75+
/**
76+
* @param Reference[] $refMap
77+
* @param int|bool $autowired
78+
*
79+
* @return Reference
80+
*/
81+
public static function register(ContainerBuilder $container, array $refMap, $autowired = false)
82+
{
83+
foreach ($refMap as $id => $ref) {
84+
$refMap[$id] = new ServiceClosureArgument($ref);
85+
}
86+
ksort($refMap);
87+
88+
$locator = (new Definition(ServiceLocator::class))
89+
->addArgument($refMap)
90+
->setPublic(false)
91+
->setAutowired($autowired)
92+
->addTag('container.service_locator');
93+
94+
if (!$container->has($id = 'service_locator.'.md5(serialize($locator)))) {
95+
$container->setDefinition($id, $locator);
96+
}
97+
98+
return new Reference($id);
5399
}
54100
}

0 commit comments

Comments
 (0)