namespace Symfony\Component\DependencyInjection\Tests\Dumper;
-use DummyProxyDumper;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface;
+use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\EnvVarProcessorInterface;
+use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
+use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator;
-use Symfony\Component\DependencyInjection\TypedReference;
-use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
+use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator;
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber;
+use Symfony\Component\DependencyInjection\TypedReference;
use Symfony\Component\DependencyInjection\Variable;
use Symfony\Component\ExpressionLanguage\Expression;
$container = new ContainerBuilder();
$container->setDefinition('test', $definition);
- $container->setParameter('foo', 'wiz'.dirname(__DIR__));
+ $container->setParameter('foo', 'wiz'.\dirname(__DIR__));
$container->setParameter('bar', __DIR__);
$container->setParameter('baz', '%bar%/PhpDumperTest.php');
- $container->setParameter('buz', dirname(dirname(__DIR__)));
+ $container->setParameter('buz', \dirname(\dirname(__DIR__)));
$container->compile();
$dumper = new PhpDumper($container);
{
$container = include self::$fixturesPath.'/containers/container9.php';
$dumper = new PhpDumper($container);
- $this->assertStringEqualsFile(self::$fixturesPath.'/php/services9.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), '%path%', $dumper->dump()), '->dump() dumps services');
+ $this->assertStringEqualsFile(self::$fixturesPath.'/php/services9.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.\DIRECTORY_SEPARATOR.'includes'.\DIRECTORY_SEPARATOR), '%path%', $dumper->dump()), '->dump() dumps services');
}
public function testAddService()
$container = include self::$fixturesPath.'/containers/container9.php';
$container->compile();
$dumper = new PhpDumper($container);
- $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');
+ $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');
$container = new ContainerBuilder();
$container->register('foo', 'FooClass')->addArgument(new \stdClass())->setPublic(true);
$container->compile();
$dumper = new PhpDumper($container);
$dump = print_r($dumper->dump(array('as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot')), true);
- if ('\\' === DIRECTORY_SEPARATOR) {
+ if ('\\' === \DIRECTORY_SEPARATOR) {
$dump = str_replace('\\\\Fixtures\\\\includes\\\\foo.php', '/Fixtures/includes/foo.php', $dump);
}
$this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_as_files.txt', $dump);
$container->compile(true);
$expected = array(
- 'env(foo)' => 'd29ybGQ=',
- 'hello' => 'world',
+ 'env(foo)' => 'd29ybGQ=',
+ 'hello' => 'world',
);
$this->assertSame($expected, $container->getParameterBag()->all());
}
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services13.php', $dumper->dump(), '->dump() dumps inline definitions which reference service_container');
}
+ public function testNonSharedLazyDefinitionReferences()
+ {
+ $container = new ContainerBuilder();
+ $container->register('foo', 'stdClass')->setShared(false)->setLazy(true);
+ $container->register('bar', 'stdClass')->addArgument(new Reference('foo', ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, false));
+ $container->compile();
+
+ $dumper = new PhpDumper($container);
+ $dumper->setProxyDumper(new \DummyProxyDumper());
+
+ $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_non_shared_lazy.php', $dumper->dump());
+ }
+
public function testInitializePropertiesBeforeMethodCalls()
{
require_once self::$fixturesPath.'/includes/classes.php';
$container->compile();
$dumper = new PhpDumper($container);
+ $dumper->setProxyDumper(new \DummyProxyDumper());
$dumper->dump();
$this->addToAssertionCount(1);
- }
-
- public function testCircularReferenceAllowanceForInlinedDefinitionsForLazyServices()
- {
- /*
- * test graph:
- * [connection] -> [event_manager] --> [entity_manager](lazy)
- * |
- * --(call)- addEventListener ("@lazy_service")
- *
- * [lazy_service](lazy) -> [entity_manager](lazy)
- *
- */
-
- $container = new ContainerBuilder();
-
- $eventManagerDefinition = new Definition('stdClass');
-
- $connectionDefinition = $container->register('connection', 'stdClass')->setPublic(true);
- $connectionDefinition->addArgument($eventManagerDefinition);
- $container->register('entity_manager', 'stdClass')
- ->setPublic(true)
- ->setLazy(true)
- ->addArgument(new Reference('connection'));
+ $dumper = new PhpDumper($container);
- $lazyServiceDefinition = $container->register('lazy_service', 'stdClass');
- $lazyServiceDefinition->setPublic(true);
- $lazyServiceDefinition->setLazy(true);
- $lazyServiceDefinition->addArgument(new Reference('entity_manager'));
+ $message = 'Circular reference detected for service "foo", path: "foo -> bar -> foo". Try running "composer require symfony/proxy-manager-bridge".';
+ if (method_exists($this, 'expectException')) {
+ $this->expectException(ServiceCircularReferenceException::class);
+ $this->expectExceptionMessage($message);
+ } else {
+ $this->setExpectedException(ServiceCircularReferenceException::class, $message);
+ }
- $eventManagerDefinition->addMethodCall('addEventListener', array(new Reference('lazy_service')));
+ $dumper->dump();
+ }
+ public function testDedupLazyProxy()
+ {
+ $container = new ContainerBuilder();
+ $container->register('foo', 'stdClass')->setLazy(true)->setPublic(true);
+ $container->register('bar', 'stdClass')->setLazy(true)->setPublic(true);
$container->compile();
$dumper = new PhpDumper($container);
+ $dumper->setProxyDumper(new \DummyProxyDumper());
- $dumper->setProxyDumper(new DummyProxyDumper());
- $dumper->dump();
-
- $this->addToAssertionCount(1);
+ $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_dedup_lazy_proxy.php', $dumper->dump());
}
public function testLazyArgumentProvideGenerator()
$foo5 = $container->get('foo5');
$this->assertSame($foo5, $foo5->bar->foo);
+
+ $manager = $container->get('manager');
+ $this->assertEquals(new \stdClass(), $manager);
+
+ $manager = $container->get('manager2');
+ $this->assertEquals(new \stdClass(), $manager);
+
+ $foo6 = $container->get('foo6');
+ $this->assertEquals((object) array('bar6' => (object) array()), $foo6);
}
public function provideAlmostCircular()
yield array('private');
}
+ public function testDeepServiceGraph()
+ {
+ $container = new ContainerBuilder();
+
+ $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
+ $loader->load('services_deep_graph.yml');
+
+ $container->compile();
+
+ $dumper = new PhpDumper($container);
+ $dumper->dump();
+
+ $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_deep_graph.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Deep_Graph')));
+
+ require self::$fixturesPath.'/php/services_deep_graph.php';
+
+ $container = new \Symfony_DI_PhpDumper_Test_Deep_Graph();
+
+ $this->assertInstanceOf(FooForDeepGraph::class, $container->get('foo'));
+ $this->assertEquals((object) array('p2' => (object) array('p3' => (object) array())), $container->get('foo')->bClone);
+ }
+
+ public function testInlineSelfRef()
+ {
+ $container = new ContainerBuilder();
+
+ $bar = (new Definition('App\Bar'))
+ ->setProperty('foo', new Reference('App\Foo'));
+
+ $baz = (new Definition('App\Baz'))
+ ->setProperty('bar', $bar)
+ ->addArgument($bar);
+
+ $container->register('App\Foo')
+ ->setPublic(true)
+ ->addArgument($baz);
+
+ $passConfig = $container->getCompiler()->getPassConfig();
+ $container->compile();
+
+ $dumper = new PhpDumper($container);
+ $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_inline_self_ref.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Inline_Self_Ref')));
+ }
+
public function testHotPathOptimizations()
{
$container = include self::$fixturesPath.'/containers/container_inline_requires.php';
$dumper = new PhpDumper($container);
$dump = $dumper->dump(array('hot_path_tag' => 'container.hot_path', 'inline_class_loader_parameter' => 'inline_requires', 'file' => self::$fixturesPath.'/php/services_inline_requires.php'));
- if ('\\' === DIRECTORY_SEPARATOR) {
+ if ('\\' === \DIRECTORY_SEPARATOR) {
$dump = str_replace("'\\\\includes\\\\HotPath\\\\", "'/includes/HotPath/", $dump);
}
$this->assertInstanceOf('stdClass', $container->get('bar'));
}
+ public function testUninitializedSyntheticReference()
+ {
+ $container = new ContainerBuilder();
+ $container->register('foo', 'stdClass')->setPublic(true)->setSynthetic(true);
+ $container->register('bar', 'stdClass')->setPublic(true)->setShared(false)
+ ->setProperty('foo', new Reference('foo', ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE));
+
+ $container->compile();
+
+ $dumper = new PhpDumper($container);
+ eval('?>'.$dumper->dump(array(
+ 'class' => 'Symfony_DI_PhpDumper_Test_UninitializedSyntheticReference',
+ 'inline_class_loader_parameter' => 'inline_requires',
+ )));
+
+ $container = new \Symfony_DI_PhpDumper_Test_UninitializedSyntheticReference();
+
+ $this->assertEquals((object) array('foo' => null), $container->get('bar'));
+
+ $container->set('foo', (object) array(123));
+ $this->assertEquals((object) array('foo' => (object) array(123)), $container->get('bar'));
+ }
+
+ public function testAdawsonContainer()
+ {
+ $container = new ContainerBuilder();
+ $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
+ $loader->load('services_adawson.yml');
+ $container->compile();
+
+ $dumper = new PhpDumper($container);
+ $dump = $dumper->dump();
+ $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_adawson.php', $dumper->dump());
+ }
+
/**
* @group legacy
* @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.
return array('rot13' => 'string');
}
}
+
+class FooForDeepGraph
+{
+ public $bClone;
+
+ public function __construct(\stdClass $a, \stdClass $b)
+ {
+ // clone to verify that $b has been fully initialized before
+ $this->bClone = clone $b;
+ }
+}