4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\DependencyInjection\Tests\Compiler;
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
16 use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
17 use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
18 use Symfony\Component\DependencyInjection\Compiler\InlineServiceDefinitionsPass;
19 use Symfony\Component\DependencyInjection\Compiler\RepeatedPass;
20 use Symfony\Component\DependencyInjection\ContainerBuilder;
21 use Symfony\Component\DependencyInjection\Definition;
22 use Symfony\Component\DependencyInjection\Reference;
24 class InlineServiceDefinitionsPassTest extends TestCase
26 public function testProcess()
28 $container = new ContainerBuilder();
30 ->register('inlinable.service')
36 ->setArguments(array(new Reference('inlinable.service')))
39 $this->process($container);
41 $arguments = $container->getDefinition('service')->getArguments();
42 $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $arguments[0]);
43 $this->assertSame($container->getDefinition('inlinable.service'), $arguments[0]);
46 public function testProcessDoesNotInlinesWhenAliasedServiceIsShared()
48 $container = new ContainerBuilder();
53 $container->setAlias('moo', 'foo');
57 ->setArguments(array($ref = new Reference('foo')))
60 $this->process($container);
62 $arguments = $container->getDefinition('service')->getArguments();
63 $this->assertSame($ref, $arguments[0]);
66 public function testProcessDoesInlineNonSharedService()
68 $container = new ContainerBuilder();
78 $container->setAlias('moo', 'bar');
82 ->setArguments(array(new Reference('foo'), $ref = new Reference('moo'), new Reference('bar')))
85 $this->process($container);
87 $arguments = $container->getDefinition('service')->getArguments();
88 $this->assertEquals($container->getDefinition('foo'), $arguments[0]);
89 $this->assertNotSame($container->getDefinition('foo'), $arguments[0]);
90 $this->assertSame($ref, $arguments[1]);
91 $this->assertEquals($container->getDefinition('bar'), $arguments[2]);
92 $this->assertNotSame($container->getDefinition('bar'), $arguments[2]);
95 public function testProcessDoesNotInlineMixedServicesLoop()
97 $container = new ContainerBuilder();
100 ->addArgument(new Reference('bar'))
106 ->addMethodCall('setFoo', array(new Reference('foo')))
109 $this->process($container);
111 $this->assertEquals(new Reference('bar'), $container->getDefinition('foo')->getArgument(0));
115 * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
116 * @expectedExceptionMessage Circular reference detected for service "bar", path: "bar -> foo -> bar".
118 public function testProcessThrowsOnNonSharedLoops()
120 $container = new ContainerBuilder();
123 ->addArgument(new Reference('bar'))
129 ->addMethodCall('setFoo', array(new Reference('foo')))
132 $this->process($container);
135 public function testProcessNestedNonSharedServices()
137 $container = new ContainerBuilder();
140 ->addArgument(new Reference('bar1'))
141 ->addArgument(new Reference('bar2'))
146 ->addArgument(new Reference('baz'))
151 ->addArgument(new Reference('baz'))
158 $this->process($container);
160 $baz1 = $container->getDefinition('foo')->getArgument(0)->getArgument(0);
161 $baz2 = $container->getDefinition('foo')->getArgument(1)->getArgument(0);
163 $this->assertEquals($container->getDefinition('baz'), $baz1);
164 $this->assertEquals($container->getDefinition('baz'), $baz2);
165 $this->assertNotSame($baz1, $baz2);
168 public function testProcessInlinesIfMultipleReferencesButAllFromTheSameDefinition()
170 $container = new ContainerBuilder();
172 $a = $container->register('a')->setPublic(false);
175 ->addArgument(new Reference('a'))
176 ->addArgument(new Definition(null, array(new Reference('a'))))
179 $this->process($container);
181 $arguments = $b->getArguments();
182 $this->assertSame($a, $arguments[0]);
184 $inlinedArguments = $arguments[1]->getArguments();
185 $this->assertSame($a, $inlinedArguments[0]);
188 public function testProcessInlinesPrivateFactoryReference()
190 $container = new ContainerBuilder();
192 $container->register('a')->setPublic(false);
196 ->setFactory(array(new Reference('a'), 'a'))
201 ->setArguments(array(
202 $ref = new Reference('b'),
205 $this->process($container);
207 $inlinedArguments = $container->getDefinition('foo')->getArguments();
208 $this->assertSame($b, $inlinedArguments[0]);
211 public function testProcessDoesNotInlinePrivateFactoryIfReferencedMultipleTimesWithinTheSameDefinition()
213 $container = new ContainerBuilder();
220 ->setFactory(array(new Reference('a'), 'a'))
225 ->setArguments(array(
226 $ref1 = new Reference('b'),
227 $ref2 = new Reference('b'),
230 $this->process($container);
232 $args = $container->getDefinition('foo')->getArguments();
233 $this->assertSame($ref1, $args[0]);
234 $this->assertSame($ref2, $args[1]);
237 public function testProcessDoesNotInlineReferenceWhenUsedByInlineFactory()
239 $container = new ContainerBuilder();
246 ->setFactory(array(new Reference('a'), 'a'))
249 $inlineFactory = new Definition();
250 $inlineFactory->setPublic(false);
251 $inlineFactory->setFactory(array(new Reference('b'), 'b'));
255 ->setArguments(array(
256 $ref = new Reference('b'),
260 $this->process($container);
262 $args = $container->getDefinition('foo')->getArguments();
263 $this->assertSame($ref, $args[0]);
266 public function testProcessDoesNotInlineWhenServiceIsPrivateButLazy()
268 $container = new ContainerBuilder();
276 ->register('service')
277 ->setArguments(array($ref = new Reference('foo')))
280 $this->process($container);
282 $arguments = $container->getDefinition('service')->getArguments();
283 $this->assertSame($ref, $arguments[0]);
286 public function testProcessDoesNotInlineWhenServiceReferencesItself()
288 $container = new ContainerBuilder();
292 ->addMethodCall('foo', array($ref = new Reference('foo')))
295 $this->process($container);
297 $calls = $container->getDefinition('foo')->getMethodCalls();
298 $this->assertSame($ref, $calls[0][1][0]);
301 public function testProcessDoesNotSetLazyArgumentValuesAfterInlining()
303 $container = new ContainerBuilder();
309 ->register('service-closure')
310 ->setArguments(array(new ServiceClosureArgument(new Reference('inline'))))
313 ->register('iterator')
314 ->setArguments(array(new IteratorArgument(array(new Reference('inline')))))
317 $this->process($container);
319 $values = $container->getDefinition('service-closure')->getArgument(0)->getValues();
320 $this->assertInstanceOf(Reference::class, $values[0]);
321 $this->assertSame('inline', (string) $values[0]);
323 $values = $container->getDefinition('iterator')->getArgument(0)->getValues();
324 $this->assertInstanceOf(Reference::class, $values[0]);
325 $this->assertSame('inline', (string) $values[0]);
331 public function testGetInlinedServiceIdData()
333 $container = new ContainerBuilder();
335 ->register('inlinable.service')
339 ->register('non_inlinable.service')
344 ->register('other_service')
345 ->setArguments(array(new Reference('inlinable.service')))
348 $inlinePass = new InlineServiceDefinitionsPass();
349 $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), $inlinePass));
350 $repeatedPass->process($container);
352 $this->assertEquals(array('inlinable.service' => array('other_service')), $inlinePass->getInlinedServiceIds());
355 protected function process(ContainerBuilder $container)
357 $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass()));
358 $repeatedPass->process($container);