3ffcf0dc0ab0d3006a626aa68336f9ae2499a1db
[yaffs-website] / vendor / symfony / dependency-injection / Tests / Dumper / PhpDumperTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\DependencyInjection\Tests\Dumper;
13
14 use PHPUnit\Framework\TestCase;
15 use Psr\Container\ContainerInterface;
16 use Symfony\Component\Config\FileLocator;
17 use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
18 use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
19 use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
20 use Symfony\Component\DependencyInjection\ChildDefinition;
21 use Symfony\Component\DependencyInjection\ContainerBuilder;
22 use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface;
23 use Symfony\Component\DependencyInjection\Definition;
24 use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
25 use Symfony\Component\DependencyInjection\EnvVarProcessorInterface;
26 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
27 use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
28 use Symfony\Component\DependencyInjection\Parameter;
29 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
30 use Symfony\Component\DependencyInjection\Reference;
31 use Symfony\Component\DependencyInjection\ServiceLocator;
32 use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
33 use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator;
34 use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber;
35 use Symfony\Component\DependencyInjection\TypedReference;
36 use Symfony\Component\DependencyInjection\Variable;
37 use Symfony\Component\ExpressionLanguage\Expression;
38
39 require_once __DIR__.'/../Fixtures/includes/classes.php';
40
41 class PhpDumperTest extends TestCase
42 {
43     protected static $fixturesPath;
44
45     public static function setUpBeforeClass()
46     {
47         self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
48     }
49
50     public function testDump()
51     {
52         $container = new ContainerBuilder();
53         $container->compile();
54         $dumper = new PhpDumper($container);
55
56         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services1.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class');
57         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services1-1.php', $dumper->dump(array('class' => 'Container', 'base_class' => 'AbstractContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Dump')), '->dump() takes a class and a base_class options');
58     }
59
60     public function testDumpOptimizationString()
61     {
62         $definition = new Definition();
63         $definition->setClass('stdClass');
64         $definition->addArgument(array(
65             'only dot' => '.',
66             'concatenation as value' => '.\'\'.',
67             'concatenation from the start value' => '\'\'.',
68             '.' => 'dot as a key',
69             '.\'\'.' => 'concatenation as a key',
70             '\'\'.' => 'concatenation from the start key',
71             'optimize concatenation' => 'string1%some_string%string2',
72             'optimize concatenation with empty string' => 'string1%empty_value%string2',
73             'optimize concatenation from the start' => '%empty_value%start',
74             'optimize concatenation at the end' => 'end%empty_value%',
75             'new line' => "string with \nnew line",
76         ));
77         $definition->setPublic(true);
78
79         $container = new ContainerBuilder();
80         $container->setResourceTracking(false);
81         $container->setDefinition('test', $definition);
82         $container->setParameter('empty_value', '');
83         $container->setParameter('some_string', '-');
84         $container->compile();
85
86         $dumper = new PhpDumper($container);
87         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services10.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class');
88     }
89
90     public function testDumpRelativeDir()
91     {
92         $definition = new Definition();
93         $definition->setClass('stdClass');
94         $definition->addArgument('%foo%');
95         $definition->addArgument(array('%foo%' => '%buz%/'));
96         $definition->setPublic(true);
97
98         $container = new ContainerBuilder();
99         $container->setDefinition('test', $definition);
100         $container->setParameter('foo', 'wiz'.\dirname(__DIR__));
101         $container->setParameter('bar', __DIR__);
102         $container->setParameter('baz', '%bar%/PhpDumperTest.php');
103         $container->setParameter('buz', \dirname(\dirname(__DIR__)));
104         $container->compile();
105
106         $dumper = new PhpDumper($container);
107         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services12.php', $dumper->dump(array('file' => __FILE__)), '->dump() dumps __DIR__ relative strings');
108     }
109
110     public function testDumpCustomContainerClassWithoutConstructor()
111     {
112         $container = new ContainerBuilder();
113         $container->compile();
114
115         $dumper = new PhpDumper($container);
116
117         $this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_without_constructor.php', $dumper->dump(array('base_class' => 'NoConstructorContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container')));
118     }
119
120     public function testDumpCustomContainerClassConstructorWithoutArguments()
121     {
122         $container = new ContainerBuilder();
123         $container->compile();
124
125         $dumper = new PhpDumper($container);
126
127         $this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_constructor_without_arguments.php', $dumper->dump(array('base_class' => 'ConstructorWithoutArgumentsContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container')));
128     }
129
130     public function testDumpCustomContainerClassWithOptionalArgumentLessConstructor()
131     {
132         $container = new ContainerBuilder();
133         $container->compile();
134
135         $dumper = new PhpDumper($container);
136
137         $this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_with_optional_constructor_arguments.php', $dumper->dump(array('base_class' => 'ConstructorWithOptionalArgumentsContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container')));
138     }
139
140     public function testDumpCustomContainerClassWithMandatoryArgumentLessConstructor()
141     {
142         $container = new ContainerBuilder();
143         $container->compile();
144
145         $dumper = new PhpDumper($container);
146
147         $this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_with_mandatory_constructor_arguments.php', $dumper->dump(array('base_class' => 'ConstructorWithMandatoryArgumentsContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container')));
148     }
149
150     /**
151      * @dataProvider provideInvalidParameters
152      * @expectedException \InvalidArgumentException
153      */
154     public function testExportParameters($parameters)
155     {
156         $container = new ContainerBuilder(new ParameterBag($parameters));
157         $container->compile();
158         $dumper = new PhpDumper($container);
159         $dumper->dump();
160     }
161
162     public function provideInvalidParameters()
163     {
164         return array(
165             array(array('foo' => new Definition('stdClass'))),
166             array(array('foo' => new Expression('service("foo").foo() ~ (container.hasParameter("foo") ? parameter("foo") : "default")'))),
167             array(array('foo' => new Reference('foo'))),
168             array(array('foo' => new Variable('foo'))),
169         );
170     }
171
172     public function testAddParameters()
173     {
174         $container = include self::$fixturesPath.'/containers/container8.php';
175         $container->compile();
176         $dumper = new PhpDumper($container);
177         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services8.php', $dumper->dump(), '->dump() dumps parameters');
178     }
179
180     /**
181      * @group legacy
182      * @expectedDeprecation Dumping an uncompiled ContainerBuilder is deprecated since Symfony 3.3 and will not be supported anymore in 4.0. Compile the container beforehand.
183      */
184     public function testAddServiceWithoutCompilation()
185     {
186         $container = include self::$fixturesPath.'/containers/container9.php';
187         $dumper = new PhpDumper($container);
188         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services9.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.\DIRECTORY_SEPARATOR.'includes'.\DIRECTORY_SEPARATOR), '%path%', $dumper->dump()), '->dump() dumps services');
189     }
190
191     public function testAddService()
192     {
193         $container = include self::$fixturesPath.'/containers/container9.php';
194         $container->compile();
195         $dumper = new PhpDumper($container);
196         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services9_compiled.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.\DIRECTORY_SEPARATOR.'includes'.\DIRECTORY_SEPARATOR), '%path%', $dumper->dump()), '->dump() dumps services');
197
198         $container = new ContainerBuilder();
199         $container->register('foo', 'FooClass')->addArgument(new \stdClass())->setPublic(true);
200         $container->compile();
201         $dumper = new PhpDumper($container);
202         try {
203             $dumper->dump();
204             $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
205         } catch (\Exception $e) {
206             $this->assertInstanceOf('\Symfony\Component\DependencyInjection\Exception\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
207             $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
208         }
209     }
210
211     public function testDumpAsFiles()
212     {
213         $container = include self::$fixturesPath.'/containers/container9.php';
214         $container->getDefinition('bar')->addTag('hot');
215         $container->compile();
216         $dumper = new PhpDumper($container);
217         $dump = print_r($dumper->dump(array('as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot')), true);
218         if ('\\' === \DIRECTORY_SEPARATOR) {
219             $dump = str_replace('\\\\Fixtures\\\\includes\\\\foo.php', '/Fixtures/includes/foo.php', $dump);
220         }
221         $this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_as_files.txt', $dump);
222     }
223
224     public function testServicesWithAnonymousFactories()
225     {
226         $container = include self::$fixturesPath.'/containers/container19.php';
227         $container->compile();
228         $dumper = new PhpDumper($container);
229
230         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services19.php', $dumper->dump(), '->dump() dumps services with anonymous factories');
231     }
232
233     public function testAddServiceIdWithUnsupportedCharacters()
234     {
235         $class = 'Symfony_DI_PhpDumper_Test_Unsupported_Characters';
236         $container = new ContainerBuilder();
237         $container->register('bar$', 'FooClass')->setPublic(true);
238         $container->register('bar$!', 'FooClass')->setPublic(true);
239         $container->compile();
240         $dumper = new PhpDumper($container);
241         eval('?>'.$dumper->dump(array('class' => $class)));
242
243         $this->assertTrue(method_exists($class, 'getBarService'));
244         $this->assertTrue(method_exists($class, 'getBar2Service'));
245     }
246
247     public function testConflictingServiceIds()
248     {
249         $class = 'Symfony_DI_PhpDumper_Test_Conflicting_Service_Ids';
250         $container = new ContainerBuilder();
251         $container->register('foo_bar', 'FooClass')->setPublic(true);
252         $container->register('foobar', 'FooClass')->setPublic(true);
253         $container->compile();
254         $dumper = new PhpDumper($container);
255         eval('?>'.$dumper->dump(array('class' => $class)));
256
257         $this->assertTrue(method_exists($class, 'getFooBarService'));
258         $this->assertTrue(method_exists($class, 'getFoobar2Service'));
259     }
260
261     public function testConflictingMethodsWithParent()
262     {
263         $class = 'Symfony_DI_PhpDumper_Test_Conflicting_Method_With_Parent';
264         $container = new ContainerBuilder();
265         $container->register('bar', 'FooClass')->setPublic(true);
266         $container->register('foo_bar', 'FooClass')->setPublic(true);
267         $container->compile();
268         $dumper = new PhpDumper($container);
269         eval('?>'.$dumper->dump(array(
270             'class' => $class,
271             'base_class' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\containers\CustomContainer',
272         )));
273
274         $this->assertTrue(method_exists($class, 'getBar2Service'));
275         $this->assertTrue(method_exists($class, 'getFoobar2Service'));
276     }
277
278     /**
279      * @dataProvider provideInvalidFactories
280      * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
281      * @expectedExceptionMessage Cannot dump definition
282      */
283     public function testInvalidFactories($factory)
284     {
285         $container = new ContainerBuilder();
286         $def = new Definition('stdClass');
287         $def->setPublic(true);
288         $def->setFactory($factory);
289         $container->setDefinition('bar', $def);
290         $container->compile();
291         $dumper = new PhpDumper($container);
292         $dumper->dump();
293     }
294
295     public function provideInvalidFactories()
296     {
297         return array(
298             array(array('', 'method')),
299             array(array('class', '')),
300             array(array('...', 'method')),
301             array(array('class', '...')),
302         );
303     }
304
305     public function testAliases()
306     {
307         $container = include self::$fixturesPath.'/containers/container9.php';
308         $container->setParameter('foo_bar', 'foo_bar');
309         $container->compile();
310         $dumper = new PhpDumper($container);
311         eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Aliases')));
312
313         $container = new \Symfony_DI_PhpDumper_Test_Aliases();
314         $foo = $container->get('foo');
315         $this->assertSame($foo, $container->get('alias_for_foo'));
316         $this->assertSame($foo, $container->get('alias_for_alias'));
317     }
318
319     public function testFrozenContainerWithoutAliases()
320     {
321         $container = new ContainerBuilder();
322         $container->compile();
323
324         $dumper = new PhpDumper($container);
325         eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Frozen_No_Aliases')));
326
327         $container = new \Symfony_DI_PhpDumper_Test_Frozen_No_Aliases();
328         $this->assertFalse($container->has('foo'));
329     }
330
331     /**
332      * @group legacy
333      * @expectedDeprecation The "decorator_service" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0.
334      */
335     public function testOverrideServiceWhenUsingADumpedContainer()
336     {
337         require_once self::$fixturesPath.'/php/services9_compiled.php';
338
339         $container = new \ProjectServiceContainer();
340         $container->get('decorator_service');
341         $container->set('decorator_service', $decorator = new \stdClass());
342
343         $this->assertSame($decorator, $container->get('decorator_service'), '->set() overrides an already defined service');
344     }
345
346     public function testDumpAutowireData()
347     {
348         $container = include self::$fixturesPath.'/containers/container24.php';
349         $container->compile();
350         $dumper = new PhpDumper($container);
351
352         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services24.php', $dumper->dump());
353     }
354
355     public function testEnvInId()
356     {
357         $container = include self::$fixturesPath.'/containers/container_env_in_id.php';
358         $container->compile();
359         $dumper = new PhpDumper($container);
360
361         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_env_in_id.php', $dumper->dump());
362     }
363
364     public function testEnvParameter()
365     {
366         $rand = mt_rand();
367         putenv('Baz='.$rand);
368         $container = new ContainerBuilder();
369         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
370         $loader->load('services26.yml');
371         $container->setParameter('env(json_file)', self::$fixturesPath.'/array.json');
372         $container->compile();
373         $dumper = new PhpDumper($container);
374
375         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services26.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_EnvParameters', 'file' => self::$fixturesPath.'/php/services26.php')));
376
377         require self::$fixturesPath.'/php/services26.php';
378         $container = new \Symfony_DI_PhpDumper_Test_EnvParameters();
379         $this->assertSame($rand, $container->getParameter('baz'));
380         $this->assertSame(array(123, 'abc'), $container->getParameter('json'));
381         $this->assertSame('sqlite:///foo/bar/var/data.db', $container->getParameter('db_dsn'));
382         putenv('Baz');
383     }
384
385     public function testResolvedBase64EnvParameters()
386     {
387         $container = new ContainerBuilder();
388         $container->setParameter('env(foo)', base64_encode('world'));
389         $container->setParameter('hello', '%env(base64:foo)%');
390         $container->compile(true);
391
392         $expected = array(
393             'env(foo)' => 'd29ybGQ=',
394             'hello' => 'world',
395         );
396         $this->assertSame($expected, $container->getParameterBag()->all());
397     }
398
399     public function testDumpedBase64EnvParameters()
400     {
401         $container = new ContainerBuilder();
402         $container->setParameter('env(foo)', base64_encode('world'));
403         $container->setParameter('hello', '%env(base64:foo)%');
404         $container->compile();
405
406         $dumper = new PhpDumper($container);
407         $dumper->dump();
408
409         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_base64_env.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Base64Parameters')));
410
411         require self::$fixturesPath.'/php/services_base64_env.php';
412         $container = new \Symfony_DI_PhpDumper_Test_Base64Parameters();
413         $this->assertSame('world', $container->getParameter('hello'));
414     }
415
416     public function testCustomEnvParameters()
417     {
418         $container = new ContainerBuilder();
419         $container->setParameter('env(foo)', str_rot13('world'));
420         $container->setParameter('hello', '%env(rot13:foo)%');
421         $container->register(Rot13EnvVarProcessor::class)->addTag('container.env_var_processor')->setPublic(true);
422         $container->compile();
423
424         $dumper = new PhpDumper($container);
425         $dumper->dump();
426
427         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_rot13_env.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Rot13Parameters')));
428
429         require self::$fixturesPath.'/php/services_rot13_env.php';
430         $container = new \Symfony_DI_PhpDumper_Test_Rot13Parameters();
431         $this->assertSame('world', $container->getParameter('hello'));
432     }
433
434     public function testFileEnvProcessor()
435     {
436         $container = new ContainerBuilder();
437         $container->setParameter('env(foo)', __FILE__);
438         $container->setParameter('random', '%env(file:foo)%');
439         $container->compile(true);
440
441         $this->assertStringEqualsFile(__FILE__, $container->getParameter('random'));
442     }
443
444     /**
445      * @expectedException \Symfony\Component\DependencyInjection\Exception\EnvParameterException
446      * @expectedExceptionMessage Environment variables "FOO" are never used. Please, check your container's configuration.
447      */
448     public function testUnusedEnvParameter()
449     {
450         $container = new ContainerBuilder();
451         $container->getParameter('env(FOO)');
452         $container->compile();
453         $dumper = new PhpDumper($container);
454         $dumper->dump();
455     }
456
457     /**
458      * @expectedException \Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException
459      * @expectedExceptionMessage Circular reference detected for parameter "env(resolve:DUMMY_ENV_VAR)" ("env(resolve:DUMMY_ENV_VAR)" > "env(resolve:DUMMY_ENV_VAR)").
460      */
461     public function testCircularDynamicEnv()
462     {
463         $container = new ContainerBuilder();
464         $container->setParameter('foo', '%bar%');
465         $container->setParameter('bar', '%env(resolve:DUMMY_ENV_VAR)%');
466         $container->compile();
467
468         $dumper = new PhpDumper($container);
469         $dump = $dumper->dump(array('class' => $class = __FUNCTION__));
470
471         eval('?>'.$dump);
472         $container = new $class();
473
474         putenv('DUMMY_ENV_VAR=%foo%');
475         try {
476             $container->getParameter('bar');
477         } finally {
478             putenv('DUMMY_ENV_VAR');
479         }
480     }
481
482     public function testInlinedDefinitionReferencingServiceContainer()
483     {
484         $container = new ContainerBuilder();
485         $container->register('foo', 'stdClass')->addMethodCall('add', array(new Reference('service_container')))->setPublic(false);
486         $container->register('bar', 'stdClass')->addArgument(new Reference('foo'))->setPublic(true);
487         $container->compile();
488
489         $dumper = new PhpDumper($container);
490         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services13.php', $dumper->dump(), '->dump() dumps inline definitions which reference service_container');
491     }
492
493     public function testNonSharedLazyDefinitionReferences()
494     {
495         $container = new ContainerBuilder();
496         $container->register('foo', 'stdClass')->setShared(false)->setLazy(true);
497         $container->register('bar', 'stdClass')->addArgument(new Reference('foo', ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, false));
498         $container->compile();
499
500         $dumper = new PhpDumper($container);
501         $dumper->setProxyDumper(new \DummyProxyDumper());
502
503         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_non_shared_lazy.php', $dumper->dump());
504     }
505
506     public function testInitializePropertiesBeforeMethodCalls()
507     {
508         require_once self::$fixturesPath.'/includes/classes.php';
509
510         $container = new ContainerBuilder();
511         $container->register('foo', 'stdClass')->setPublic(true);
512         $container->register('bar', 'MethodCallClass')
513             ->setPublic(true)
514             ->setProperty('simple', 'bar')
515             ->setProperty('complex', new Reference('foo'))
516             ->addMethodCall('callMe');
517         $container->compile();
518
519         $dumper = new PhpDumper($container);
520         eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Properties_Before_Method_Calls')));
521
522         $container = new \Symfony_DI_PhpDumper_Test_Properties_Before_Method_Calls();
523         $this->assertTrue($container->get('bar')->callPassed(), '->dump() initializes properties before method calls');
524     }
525
526     public function testCircularReferenceAllowanceForLazyServices()
527     {
528         $container = new ContainerBuilder();
529         $container->register('foo', 'stdClass')->addArgument(new Reference('bar'))->setPublic(true);
530         $container->register('bar', 'stdClass')->setLazy(true)->addArgument(new Reference('foo'))->setPublic(true);
531         $container->compile();
532
533         $dumper = new PhpDumper($container);
534         $dumper->setProxyDumper(new \DummyProxyDumper());
535         $dumper->dump();
536
537         $this->addToAssertionCount(1);
538
539         $dumper = new PhpDumper($container);
540
541         $message = 'Circular reference detected for service "foo", path: "foo -> bar -> foo". Try running "composer require symfony/proxy-manager-bridge".';
542         if (method_exists($this, 'expectException')) {
543             $this->expectException(ServiceCircularReferenceException::class);
544             $this->expectExceptionMessage($message);
545         } else {
546             $this->setExpectedException(ServiceCircularReferenceException::class, $message);
547         }
548
549         $dumper->dump();
550     }
551
552     public function testDedupLazyProxy()
553     {
554         $container = new ContainerBuilder();
555         $container->register('foo', 'stdClass')->setLazy(true)->setPublic(true);
556         $container->register('bar', 'stdClass')->setLazy(true)->setPublic(true);
557         $container->compile();
558
559         $dumper = new PhpDumper($container);
560         $dumper->setProxyDumper(new \DummyProxyDumper());
561
562         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_dedup_lazy_proxy.php', $dumper->dump());
563     }
564
565     public function testLazyArgumentProvideGenerator()
566     {
567         require_once self::$fixturesPath.'/includes/classes.php';
568
569         $container = new ContainerBuilder();
570         $container->register('lazy_referenced', 'stdClass')->setPublic(true);
571         $container
572             ->register('lazy_context', 'LazyContext')
573             ->setPublic(true)
574             ->setArguments(array(
575                 new IteratorArgument(array('k1' => new Reference('lazy_referenced'), 'k2' => new Reference('service_container'))),
576                 new IteratorArgument(array()),
577             ))
578         ;
579         $container->compile();
580
581         $dumper = new PhpDumper($container);
582         eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Lazy_Argument_Provide_Generator')));
583
584         $container = new \Symfony_DI_PhpDumper_Test_Lazy_Argument_Provide_Generator();
585         $lazyContext = $container->get('lazy_context');
586
587         $this->assertInstanceOf(RewindableGenerator::class, $lazyContext->lazyValues);
588         $this->assertInstanceOf(RewindableGenerator::class, $lazyContext->lazyEmptyValues);
589         $this->assertCount(2, $lazyContext->lazyValues);
590         $this->assertCount(0, $lazyContext->lazyEmptyValues);
591
592         $i = -1;
593         foreach ($lazyContext->lazyValues as $k => $v) {
594             switch (++$i) {
595                 case 0:
596                     $this->assertEquals('k1', $k);
597                     $this->assertInstanceOf('stdCLass', $v);
598                     break;
599                 case 1:
600                     $this->assertEquals('k2', $k);
601                     $this->assertInstanceOf('Symfony_DI_PhpDumper_Test_Lazy_Argument_Provide_Generator', $v);
602                     break;
603             }
604         }
605
606         $this->assertEmpty(iterator_to_array($lazyContext->lazyEmptyValues));
607     }
608
609     public function testNormalizedId()
610     {
611         $container = include self::$fixturesPath.'/containers/container33.php';
612         $container->compile();
613         $dumper = new PhpDumper($container);
614
615         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services33.php', $dumper->dump());
616     }
617
618     public function testDumpContainerBuilderWithFrozenConstructorIncludingPrivateServices()
619     {
620         $container = new ContainerBuilder();
621         $container->register('foo_service', 'stdClass')->setArguments(array(new Reference('baz_service')))->setPublic(true);
622         $container->register('bar_service', 'stdClass')->setArguments(array(new Reference('baz_service')))->setPublic(true);
623         $container->register('baz_service', 'stdClass')->setPublic(false);
624         $container->compile();
625
626         $dumper = new PhpDumper($container);
627
628         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_private_frozen.php', $dumper->dump());
629     }
630
631     public function testServiceLocator()
632     {
633         $container = new ContainerBuilder();
634         $container->register('foo_service', ServiceLocator::class)
635             ->setPublic(true)
636             ->addArgument(array(
637                 'bar' => new ServiceClosureArgument(new Reference('bar_service')),
638                 'baz' => new ServiceClosureArgument(new TypedReference('baz_service', 'stdClass')),
639                 'nil' => $nil = new ServiceClosureArgument(new Reference('nil')),
640             ))
641         ;
642
643         // no method calls
644         $container->register('translator.loader_1', 'stdClass')->setPublic(true);
645         $container->register('translator.loader_1_locator', ServiceLocator::class)
646             ->setPublic(false)
647             ->addArgument(array(
648                 'translator.loader_1' => new ServiceClosureArgument(new Reference('translator.loader_1')),
649             ));
650         $container->register('translator_1', StubbedTranslator::class)
651             ->setPublic(true)
652             ->addArgument(new Reference('translator.loader_1_locator'));
653
654         // one method calls
655         $container->register('translator.loader_2', 'stdClass')->setPublic(true);
656         $container->register('translator.loader_2_locator', ServiceLocator::class)
657             ->setPublic(false)
658             ->addArgument(array(
659                 'translator.loader_2' => new ServiceClosureArgument(new Reference('translator.loader_2')),
660             ));
661         $container->register('translator_2', StubbedTranslator::class)
662             ->setPublic(true)
663             ->addArgument(new Reference('translator.loader_2_locator'))
664             ->addMethodCall('addResource', array('db', new Reference('translator.loader_2'), 'nl'));
665
666         // two method calls
667         $container->register('translator.loader_3', 'stdClass')->setPublic(true);
668         $container->register('translator.loader_3_locator', ServiceLocator::class)
669             ->setPublic(false)
670             ->addArgument(array(
671                 'translator.loader_3' => new ServiceClosureArgument(new Reference('translator.loader_3')),
672             ));
673         $container->register('translator_3', StubbedTranslator::class)
674             ->setPublic(true)
675             ->addArgument(new Reference('translator.loader_3_locator'))
676             ->addMethodCall('addResource', array('db', new Reference('translator.loader_3'), 'nl'))
677             ->addMethodCall('addResource', array('db', new Reference('translator.loader_3'), 'en'));
678
679         $nil->setValues(array(null));
680         $container->register('bar_service', 'stdClass')->setArguments(array(new Reference('baz_service')))->setPublic(true);
681         $container->register('baz_service', 'stdClass')->setPublic(false);
682         $container->compile();
683
684         $dumper = new PhpDumper($container);
685
686         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_locator.php', $dumper->dump());
687     }
688
689     public function testServiceSubscriber()
690     {
691         $container = new ContainerBuilder();
692         $container->register('foo_service', TestServiceSubscriber::class)
693             ->setPublic(true)
694             ->setAutowired(true)
695             ->addArgument(new Reference(ContainerInterface::class))
696             ->addTag('container.service_subscriber', array(
697                 'key' => 'bar',
698                 'id' => TestServiceSubscriber::class,
699             ))
700         ;
701         $container->register(TestServiceSubscriber::class, TestServiceSubscriber::class)->setPublic(true);
702
703         $container->register(CustomDefinition::class, CustomDefinition::class)
704             ->setPublic(false);
705         $container->compile();
706
707         $dumper = new PhpDumper($container);
708
709         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_subscriber.php', $dumper->dump());
710     }
711
712     public function testPrivateWithIgnoreOnInvalidReference()
713     {
714         require_once self::$fixturesPath.'/includes/classes.php';
715
716         $container = new ContainerBuilder();
717         $container->register('not_invalid', 'BazClass')
718             ->setPublic(false);
719         $container->register('bar', 'BarClass')
720             ->setPublic(true)
721             ->addMethodCall('setBaz', array(new Reference('not_invalid', SymfonyContainerInterface::IGNORE_ON_INVALID_REFERENCE)));
722         $container->compile();
723
724         $dumper = new PhpDumper($container);
725         eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Private_With_Ignore_On_Invalid_Reference')));
726
727         $container = new \Symfony_DI_PhpDumper_Test_Private_With_Ignore_On_Invalid_Reference();
728         $this->assertInstanceOf('BazClass', $container->get('bar')->getBaz());
729     }
730
731     public function testArrayParameters()
732     {
733         $container = new ContainerBuilder();
734         $container->setParameter('array_1', array(123));
735         $container->setParameter('array_2', array(__DIR__));
736         $container->register('bar', 'BarClass')
737             ->setPublic(true)
738             ->addMethodCall('setBaz', array('%array_1%', '%array_2%', '%%array_1%%', array(123)));
739         $container->compile();
740
741         $dumper = new PhpDumper($container);
742
743         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_array_params.php', str_replace('\\\\Dumper', '/Dumper', $dumper->dump(array('file' => self::$fixturesPath.'/php/services_array_params.php'))));
744     }
745
746     public function testExpressionReferencingPrivateService()
747     {
748         $container = new ContainerBuilder();
749         $container->register('private_bar', 'stdClass')
750             ->setPublic(false);
751         $container->register('private_foo', 'stdClass')
752             ->setPublic(false);
753         $container->register('public_foo', 'stdClass')
754             ->setPublic(true)
755             ->addArgument(new Expression('service("private_foo")'));
756
757         $container->compile();
758         $dumper = new PhpDumper($container);
759
760         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_private_in_expression.php', $dumper->dump());
761     }
762
763     public function testUninitializedReference()
764     {
765         $container = include self::$fixturesPath.'/containers/container_uninitialized_ref.php';
766         $container->compile();
767         $dumper = new PhpDumper($container);
768
769         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_uninitialized_ref.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Uninitialized_Reference')));
770
771         require self::$fixturesPath.'/php/services_uninitialized_ref.php';
772
773         $container = new \Symfony_DI_PhpDumper_Test_Uninitialized_Reference();
774
775         $bar = $container->get('bar');
776
777         $this->assertNull($bar->foo1);
778         $this->assertNull($bar->foo2);
779         $this->assertNull($bar->foo3);
780         $this->assertNull($bar->closures[0]());
781         $this->assertNull($bar->closures[1]());
782         $this->assertNull($bar->closures[2]());
783         $this->assertSame(array(), iterator_to_array($bar->iter));
784
785         $container = new \Symfony_DI_PhpDumper_Test_Uninitialized_Reference();
786
787         $container->get('foo1');
788         $container->get('baz');
789
790         $bar = $container->get('bar');
791
792         $this->assertEquals(new \stdClass(), $bar->foo1);
793         $this->assertNull($bar->foo2);
794         $this->assertEquals(new \stdClass(), $bar->foo3);
795         $this->assertEquals(new \stdClass(), $bar->closures[0]());
796         $this->assertNull($bar->closures[1]());
797         $this->assertEquals(new \stdClass(), $bar->closures[2]());
798         $this->assertEquals(array('foo1' => new \stdClass(), 'foo3' => new \stdClass()), iterator_to_array($bar->iter));
799     }
800
801     /**
802      * @dataProvider provideAlmostCircular
803      */
804     public function testAlmostCircular($visibility)
805     {
806         $container = include self::$fixturesPath.'/containers/container_almost_circular.php';
807         $container->compile();
808         $dumper = new PhpDumper($container);
809
810         $container = 'Symfony_DI_PhpDumper_Test_Almost_Circular_'.ucfirst($visibility);
811         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_almost_circular_'.$visibility.'.php', $dumper->dump(array('class' => $container)));
812
813         require self::$fixturesPath.'/php/services_almost_circular_'.$visibility.'.php';
814
815         $container = new $container();
816
817         $foo = $container->get('foo');
818         $this->assertSame($foo, $foo->bar->foobar->foo);
819
820         $foo2 = $container->get('foo2');
821         $this->assertSame($foo2, $foo2->bar->foobar->foo);
822
823         $this->assertSame(array(), (array) $container->get('foobar4'));
824
825         $foo5 = $container->get('foo5');
826         $this->assertSame($foo5, $foo5->bar->foo);
827
828         $manager = $container->get('manager');
829         $this->assertEquals(new \stdClass(), $manager);
830
831         $manager = $container->get('manager2');
832         $this->assertEquals(new \stdClass(), $manager);
833
834         $foo6 = $container->get('foo6');
835         $this->assertEquals((object) array('bar6' => (object) array()), $foo6);
836     }
837
838     public function provideAlmostCircular()
839     {
840         yield array('public');
841         yield array('private');
842     }
843
844     public function testDeepServiceGraph()
845     {
846         $container = new ContainerBuilder();
847
848         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
849         $loader->load('services_deep_graph.yml');
850
851         $container->compile();
852
853         $dumper = new PhpDumper($container);
854         $dumper->dump();
855
856         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_deep_graph.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Deep_Graph')));
857
858         require self::$fixturesPath.'/php/services_deep_graph.php';
859
860         $container = new \Symfony_DI_PhpDumper_Test_Deep_Graph();
861
862         $this->assertInstanceOf(FooForDeepGraph::class, $container->get('foo'));
863         $this->assertEquals((object) array('p2' => (object) array('p3' => (object) array())), $container->get('foo')->bClone);
864     }
865
866     public function testInlineSelfRef()
867     {
868         $container = new ContainerBuilder();
869
870         $bar = (new Definition('App\Bar'))
871             ->setProperty('foo', new Reference('App\Foo'));
872
873         $baz = (new Definition('App\Baz'))
874             ->setProperty('bar', $bar)
875             ->addArgument($bar);
876
877         $container->register('App\Foo')
878             ->setPublic(true)
879             ->addArgument($baz);
880
881         $passConfig = $container->getCompiler()->getPassConfig();
882         $container->compile();
883
884         $dumper = new PhpDumper($container);
885         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_inline_self_ref.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Inline_Self_Ref')));
886     }
887
888     public function testHotPathOptimizations()
889     {
890         $container = include self::$fixturesPath.'/containers/container_inline_requires.php';
891         $container->setParameter('inline_requires', true);
892         $container->compile();
893         $dumper = new PhpDumper($container);
894
895         $dump = $dumper->dump(array('hot_path_tag' => 'container.hot_path', 'inline_class_loader_parameter' => 'inline_requires', 'file' => self::$fixturesPath.'/php/services_inline_requires.php'));
896         if ('\\' === \DIRECTORY_SEPARATOR) {
897             $dump = str_replace("'\\\\includes\\\\HotPath\\\\", "'/includes/HotPath/", $dump);
898         }
899
900         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_inline_requires.php', $dump);
901     }
902
903     public function testDumpHandlesLiteralClassWithRootNamespace()
904     {
905         $container = new ContainerBuilder();
906         $container->register('foo', '\\stdClass')->setPublic(true);
907         $container->compile();
908
909         $dumper = new PhpDumper($container);
910         eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace')));
911
912         $container = new \Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace();
913
914         $this->assertInstanceOf('stdClass', $container->get('foo'));
915     }
916
917     public function testDumpHandlesObjectClassNames()
918     {
919         $container = new ContainerBuilder(new ParameterBag(array(
920             'class' => 'stdClass',
921         )));
922
923         $container->setDefinition('foo', new Definition(new Parameter('class')));
924         $container->setDefinition('bar', new Definition('stdClass', array(
925             new Reference('foo'),
926         )))->setPublic(true);
927
928         $container->setParameter('inline_requires', true);
929         $container->compile();
930
931         $dumper = new PhpDumper($container);
932         eval('?>'.$dumper->dump(array(
933             'class' => 'Symfony_DI_PhpDumper_Test_Object_Class_Name',
934             'inline_class_loader_parameter' => 'inline_requires',
935         )));
936
937         $container = new \Symfony_DI_PhpDumper_Test_Object_Class_Name();
938
939         $this->assertInstanceOf('stdClass', $container->get('bar'));
940     }
941
942     public function testUninitializedSyntheticReference()
943     {
944         $container = new ContainerBuilder();
945         $container->register('foo', 'stdClass')->setPublic(true)->setSynthetic(true);
946         $container->register('bar', 'stdClass')->setPublic(true)->setShared(false)
947             ->setProperty('foo', new Reference('foo', ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE));
948
949         $container->compile();
950
951         $dumper = new PhpDumper($container);
952         eval('?>'.$dumper->dump(array(
953             'class' => 'Symfony_DI_PhpDumper_Test_UninitializedSyntheticReference',
954             'inline_class_loader_parameter' => 'inline_requires',
955         )));
956
957         $container = new \Symfony_DI_PhpDumper_Test_UninitializedSyntheticReference();
958
959         $this->assertEquals((object) array('foo' => null), $container->get('bar'));
960
961         $container->set('foo', (object) array(123));
962         $this->assertEquals((object) array('foo' => (object) array(123)), $container->get('bar'));
963     }
964
965     public function testAdawsonContainer()
966     {
967         $container = new ContainerBuilder();
968         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
969         $loader->load('services_adawson.yml');
970         $container->compile();
971
972         $dumper = new PhpDumper($container);
973         $dump = $dumper->dump();
974         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_adawson.php', $dumper->dump());
975     }
976
977     /**
978      * @group legacy
979      * @expectedDeprecation The "private" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.
980      * @expectedDeprecation The "private_alias" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.
981      * @expectedDeprecation The "decorated_private" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.
982      * @expectedDeprecation The "decorated_private_alias" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.
983      * @expectedDeprecation The "private_not_inlined" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.
984      * @expectedDeprecation The "private_not_removed" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.
985      * @expectedDeprecation The "private_child" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.
986      * @expectedDeprecation The "private_parent" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.
987      */
988     public function testLegacyPrivateServices()
989     {
990         $container = new ContainerBuilder();
991         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
992         $loader->load('services_legacy_privates.yml');
993
994         $container->setDefinition('private_child', new ChildDefinition('foo'));
995         $container->setDefinition('private_parent', new ChildDefinition('private'));
996
997         $container->getDefinition('private')->setPrivate(true);
998         $container->getDefinition('private_not_inlined')->setPrivate(true);
999         $container->getDefinition('private_not_removed')->setPrivate(true);
1000         $container->getDefinition('decorated_private')->setPrivate(true);
1001         $container->getDefinition('private_child')->setPrivate(true);
1002         $container->getAlias('decorated_private_alias')->setPrivate(true);
1003         $container->getAlias('private_alias')->setPrivate(true);
1004
1005         $container->compile();
1006         $dumper = new PhpDumper($container);
1007
1008         $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_legacy_privates.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Legacy_Privates', 'file' => self::$fixturesPath.'/php/services_legacy_privates.php')));
1009
1010         require self::$fixturesPath.'/php/services_legacy_privates.php';
1011
1012         $container = new \Symfony_DI_PhpDumper_Test_Legacy_Privates();
1013
1014         $container->get('private');
1015         $container->get('private_alias');
1016         $container->get('alias_to_private');
1017         $container->get('decorated_private');
1018         $container->get('decorated_private_alias');
1019         $container->get('private_not_inlined');
1020         $container->get('private_not_removed');
1021         $container->get('private_child');
1022         $container->get('private_parent');
1023         $container->get('public_child');
1024     }
1025
1026     /**
1027      * This test checks the trigger of a deprecation note and should not be removed in major releases.
1028      *
1029      * @group legacy
1030      * @expectedDeprecation The "foo" service is deprecated. You should stop using it, as it will soon be removed.
1031      */
1032     public function testPrivateServiceTriggersDeprecation()
1033     {
1034         $container = new ContainerBuilder();
1035         $container->register('foo', 'stdClass')
1036             ->setPublic(false)
1037             ->setDeprecated(true);
1038         $container->register('bar', 'stdClass')
1039             ->setPublic(true)
1040             ->setProperty('foo', new Reference('foo'));
1041
1042         $container->compile();
1043
1044         $dumper = new PhpDumper($container);
1045         eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Private_Service_Triggers_Deprecation')));
1046
1047         $container = new \Symfony_DI_PhpDumper_Test_Private_Service_Triggers_Deprecation();
1048
1049         $container->get('bar');
1050     }
1051
1052     /**
1053      * @group legacy
1054      * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "foo" instead of "Foo" is deprecated since Symfony 3.4.
1055      * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "Foo" is deprecated since Symfony 3.4.
1056      * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "bar" instead of "BAR" is deprecated since Symfony 3.4.
1057      */
1058     public function testParameterWithMixedCase()
1059     {
1060         $container = new ContainerBuilder(new ParameterBag(array('Foo' => 'bar', 'BAR' => 'foo')));
1061         $container->compile();
1062
1063         $dumper = new PhpDumper($container);
1064         eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Parameter_With_Mixed_Case')));
1065
1066         $container = new \Symfony_DI_PhpDumper_Test_Parameter_With_Mixed_Case();
1067
1068         $this->assertSame('bar', $container->getParameter('foo'));
1069         $this->assertSame('bar', $container->getParameter('FOO'));
1070         $this->assertSame('foo', $container->getParameter('bar'));
1071         $this->assertSame('foo', $container->getParameter('BAR'));
1072     }
1073
1074     /**
1075      * @group legacy
1076      * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since Symfony 3.4.
1077      */
1078     public function testParameterWithLowerCase()
1079     {
1080         $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar')));
1081         $container->compile();
1082
1083         $dumper = new PhpDumper($container);
1084         eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Parameter_With_Lower_Case')));
1085
1086         $container = new \Symfony_DI_PhpDumper_Test_Parameter_With_Lower_Case();
1087
1088         $this->assertSame('bar', $container->getParameter('FOO'));
1089     }
1090
1091     /**
1092      * @group legacy
1093      * @expectedDeprecation Service identifiers will be made case sensitive in Symfony 4.0. Using "foo" instead of "Foo" is deprecated since Symfony 3.3.
1094      * @expectedDeprecation The "Foo" service is deprecated. You should stop using it, as it will soon be removed.
1095      */
1096     public function testReferenceWithLowerCaseId()
1097     {
1098         $container = new ContainerBuilder();
1099         $container->register('Bar', 'stdClass')->setProperty('foo', new Reference('foo'))->setPublic(true);
1100         $container->register('Foo', 'stdClass')->setDeprecated();
1101         $container->compile();
1102
1103         $dumper = new PhpDumper($container);
1104         eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Reference_With_Lower_Case_Id')));
1105
1106         $container = new \Symfony_DI_PhpDumper_Test_Reference_With_Lower_Case_Id();
1107
1108         $this->assertEquals((object) array('foo' => (object) array()), $container->get('Bar'));
1109     }
1110 }
1111
1112 class Rot13EnvVarProcessor implements EnvVarProcessorInterface
1113 {
1114     public function getEnv($prefix, $name, \Closure $getEnv)
1115     {
1116         return str_rot13($getEnv($name));
1117     }
1118
1119     public static function getProvidedTypes()
1120     {
1121         return array('rot13' => 'string');
1122     }
1123 }
1124
1125 class FooForDeepGraph
1126 {
1127     public $bClone;
1128
1129     public function __construct(\stdClass $a, \stdClass $b)
1130     {
1131         // clone to verify that $b has been fully initialized before
1132         $this->bClone = clone $b;
1133     }
1134 }