1490 lines
62 KiB
PHP
Executable File
1490 lines
62 KiB
PHP
Executable File
<?php
|
|
|
|
/*
|
|
* This file is part of the Symfony package.
|
|
*
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Symfony\Component\DependencyInjection\Tests\Dumper;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use Psr\Container\ContainerInterface;
|
|
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
|
|
use Symfony\Component\Config\FileLocator;
|
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
|
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
|
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
|
use Symfony\Component\DependencyInjection\Argument\ServiceLocator as ArgumentServiceLocator;
|
|
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
|
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
|
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
|
|
use Symfony\Component\DependencyInjection\Container;
|
|
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\EnvParameterException;
|
|
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
|
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
|
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
|
|
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
|
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
|
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
|
use Symfony\Component\DependencyInjection\Reference;
|
|
use Symfony\Component\DependencyInjection\ServiceLocator;
|
|
use Symfony\Component\DependencyInjection\Tests\Compiler\Foo;
|
|
use Symfony\Component\DependencyInjection\Tests\Compiler\Wither;
|
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
|
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
|
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
|
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\NewInInitializer;
|
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\ScalarFactory;
|
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator;
|
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition1;
|
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber;
|
|
use Symfony\Component\DependencyInjection\TypedReference;
|
|
use Symfony\Component\ExpressionLanguage\Expression;
|
|
|
|
require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php';
|
|
require_once __DIR__.'/../Fixtures/includes/classes.php';
|
|
require_once __DIR__.'/../Fixtures/includes/foo.php';
|
|
require_once __DIR__.'/../Fixtures/includes/foo_lazy.php';
|
|
|
|
class PhpDumperTest extends TestCase
|
|
{
|
|
protected static $fixturesPath;
|
|
|
|
public static function setUpBeforeClass(): void
|
|
{
|
|
self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
|
|
}
|
|
|
|
public function testDump()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services1.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class');
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services1-1.php', $dumper->dump(['class' => 'Container', 'base_class' => 'AbstractContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Dump']), '->dump() takes a class and a base_class options');
|
|
}
|
|
|
|
public function testDumpOptimizationString()
|
|
{
|
|
$definition = new Definition();
|
|
$definition->setClass('stdClass');
|
|
$definition->addArgument([
|
|
'only dot' => '.',
|
|
'concatenation as value' => '.\'\'.',
|
|
'concatenation from the start value' => '\'\'.',
|
|
'.' => 'dot as a key',
|
|
'.\'\'.' => 'concatenation as a key',
|
|
'\'\'.' => 'concatenation from the start key',
|
|
'optimize concatenation' => 'string1%some_string%string2',
|
|
'optimize concatenation with empty string' => 'string1%empty_value%string2',
|
|
'optimize concatenation from the start' => '%empty_value%start',
|
|
'optimize concatenation at the end' => 'end%empty_value%',
|
|
'new line' => "string with \nnew line",
|
|
]);
|
|
$definition->setPublic(true);
|
|
|
|
$container = new ContainerBuilder();
|
|
$container->setResourceTracking(false);
|
|
$container->setDefinition('test', $definition);
|
|
$container->setParameter('empty_value', '');
|
|
$container->setParameter('some_string', '-');
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services10.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class');
|
|
}
|
|
|
|
public function testDumpRelativeDir()
|
|
{
|
|
$definition = new Definition();
|
|
$definition->setClass('stdClass');
|
|
$definition->addArgument('%foo%');
|
|
$definition->addArgument(['%foo%' => '%buz%/']);
|
|
$definition->setPublic(true);
|
|
|
|
$container = new ContainerBuilder();
|
|
$container->setDefinition('test', $definition);
|
|
$container->setParameter('foo', 'file://'.\dirname(__DIR__));
|
|
$container->setParameter('bar', __DIR__);
|
|
$container->setParameter('baz', '%bar%/PhpDumperTest.php');
|
|
$container->setParameter('buz', \dirname(__DIR__, 2));
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services12.php', $dumper->dump(['file' => __FILE__]), '->dump() dumps __DIR__ relative strings');
|
|
}
|
|
|
|
public function testDumpCustomContainerClassWithoutConstructor()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_without_constructor.php', $dumper->dump(['base_class' => 'NoConstructorContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container']));
|
|
}
|
|
|
|
public function testDumpCustomContainerClassConstructorWithoutArguments()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_constructor_without_arguments.php', $dumper->dump(['base_class' => 'ConstructorWithoutArgumentsContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container']));
|
|
}
|
|
|
|
public function testDumpCustomContainerClassWithOptionalArgumentLessConstructor()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_with_optional_constructor_arguments.php', $dumper->dump(['base_class' => 'ConstructorWithOptionalArgumentsContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container']));
|
|
}
|
|
|
|
public function testDumpCustomContainerClassWithMandatoryArgumentLessConstructor()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_with_mandatory_constructor_arguments.php', $dumper->dump(['base_class' => 'ConstructorWithMandatoryArgumentsContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container']));
|
|
}
|
|
|
|
public function testAddParameters()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container8.php';
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services8.php', $dumper->dump(), '->dump() dumps parameters');
|
|
}
|
|
|
|
public function testAddServiceWithoutCompilation()
|
|
{
|
|
$this->expectException(LogicException::class);
|
|
$this->expectExceptionMessage('Cannot dump an uncompiled container.');
|
|
$container = include self::$fixturesPath.'/containers/container9.php';
|
|
new PhpDumper($container);
|
|
}
|
|
|
|
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');
|
|
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo', 'FooClass')->addArgument(new \stdClass())->setPublic(true);
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
try {
|
|
$dumper->dump();
|
|
$this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
|
|
} catch (\Exception $e) {
|
|
$this->assertInstanceOf(RuntimeException::class, $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
|
|
$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');
|
|
}
|
|
}
|
|
|
|
public function testDumpAsFiles()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container9.php';
|
|
$container->getDefinition('bar')->addTag('hot');
|
|
$container->register('non_shared_foo', \Bar\FooClass::class)
|
|
->setFile(realpath(self::$fixturesPath.'/includes/foo.php'))
|
|
->setShared(false)
|
|
->setPublic(true);
|
|
$container->register('throwing_one', \Bar\FooClass::class)
|
|
->addArgument(new Reference('errored_one', ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE))
|
|
->setPublic(true);
|
|
$container->register('errored_one', 'stdClass')
|
|
->addError('No-no-no-no');
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot']), true);
|
|
if ('\\' === \DIRECTORY_SEPARATOR) {
|
|
$dump = str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dump);
|
|
}
|
|
$this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_as_files.txt', $dump);
|
|
}
|
|
|
|
public function testDumpAsFilesWithFactoriesInlined()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container9.php';
|
|
$container->setParameter('container.dumper.inline_factories', true);
|
|
$container->setParameter('container.dumper.inline_class_loader', true);
|
|
|
|
$container->getDefinition('bar')->addTag('hot');
|
|
$container->register('non_shared_foo', \Bar\FooClass::class)
|
|
->setFile(realpath(self::$fixturesPath.'/includes/foo.php'))
|
|
->setShared(false)
|
|
->setPublic(true);
|
|
$container->register('throwing_one', \Bar\FooClass::class)
|
|
->addArgument(new Reference('errored_one', ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE))
|
|
->setPublic(true);
|
|
$container->register('errored_one', 'stdClass')
|
|
->addError('No-no-no-no');
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'build_time' => 1563381341]), true);
|
|
|
|
if ('\\' === \DIRECTORY_SEPARATOR) {
|
|
$dump = str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dump);
|
|
}
|
|
$this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_inlined_factories.txt', $dump);
|
|
}
|
|
|
|
/**
|
|
* @requires function \Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper::getProxyCode
|
|
*/
|
|
public function testDumpAsFilesWithLazyFactoriesInlined()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('container.dumper.inline_factories', true);
|
|
$container->setParameter('container.dumper.inline_class_loader', true);
|
|
|
|
$container->register('lazy_foo', \Bar\FooClass::class)
|
|
->addArgument(new Definition(\Bar\FooLazyClass::class))
|
|
->setPublic(true)
|
|
->setLazy(true);
|
|
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->setProxyDumper(new ProxyDumper());
|
|
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'build_time' => 1563381341]), true);
|
|
|
|
if ('\\' === \DIRECTORY_SEPARATOR) {
|
|
$dump = str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dump);
|
|
}
|
|
$this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_lazy_inlined_factories.txt', $dump);
|
|
}
|
|
|
|
public function testNonSharedLazyDumpAsFiles()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container_non_shared_lazy.php';
|
|
$container->register('non_shared_foo', \Bar\FooLazyClass::class)
|
|
->setFile(realpath(self::$fixturesPath.'/includes/foo_lazy.php'))
|
|
->setShared(false)
|
|
->setPublic(true)
|
|
->setLazy(true);
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__]), true);
|
|
|
|
if ('\\' === \DIRECTORY_SEPARATOR) {
|
|
$dump = str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dump);
|
|
}
|
|
$this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services_non_shared_lazy_as_files.txt', $dump);
|
|
}
|
|
|
|
public function testServicesWithAnonymousFactories()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container19.php';
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services19.php', $dumper->dump(), '->dump() dumps services with anonymous factories');
|
|
}
|
|
|
|
public function testAddServiceIdWithUnsupportedCharacters()
|
|
{
|
|
$class = 'Symfony_DI_PhpDumper_Test_Unsupported_Characters';
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter("'", 'oh-no');
|
|
$container->register('foo*/oh-no', 'FooClass')->setPublic(true);
|
|
$container->register('bar$', 'FooClass')->setPublic(true);
|
|
$container->register('bar$!', 'FooClass')->setPublic(true);
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_unsupported_characters.php', $dumper->dump(['class' => $class]));
|
|
|
|
require_once self::$fixturesPath.'/php/services_unsupported_characters.php';
|
|
|
|
$this->assertTrue(method_exists($class, 'getFooOhNoService'));
|
|
$this->assertTrue(method_exists($class, 'getBarService'));
|
|
$this->assertTrue(method_exists($class, 'getBar2Service'));
|
|
}
|
|
|
|
public function testConflictingServiceIds()
|
|
{
|
|
$class = 'Symfony_DI_PhpDumper_Test_Conflicting_Service_Ids';
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo_bar', 'FooClass')->setPublic(true);
|
|
$container->register('foobar', 'FooClass')->setPublic(true);
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump(['class' => $class]));
|
|
|
|
$this->assertTrue(method_exists($class, 'getFooBarService'));
|
|
$this->assertTrue(method_exists($class, 'getFoobar2Service'));
|
|
}
|
|
|
|
public function testConflictingMethodsWithParent()
|
|
{
|
|
$class = 'Symfony_DI_PhpDumper_Test_Conflicting_Method_With_Parent';
|
|
$container = new ContainerBuilder();
|
|
$container->register('bar', 'FooClass')->setPublic(true);
|
|
$container->register('foo_bar', 'FooClass')->setPublic(true);
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump([
|
|
'class' => $class,
|
|
'base_class' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\containers\CustomContainer',
|
|
]));
|
|
|
|
$this->assertTrue(method_exists($class, 'getBar2Service'));
|
|
$this->assertTrue(method_exists($class, 'getFoobar2Service'));
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideInvalidFactories
|
|
*/
|
|
public function testInvalidFactories($factory)
|
|
{
|
|
$this->expectException(RuntimeException::class);
|
|
$this->expectExceptionMessage('Cannot dump definition');
|
|
$container = new ContainerBuilder();
|
|
$def = new Definition('stdClass');
|
|
$def->setPublic(true);
|
|
$def->setFactory($factory);
|
|
$container->setDefinition('bar', $def);
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->dump();
|
|
}
|
|
|
|
public function provideInvalidFactories()
|
|
{
|
|
return [
|
|
[['', 'method']],
|
|
[['class', '']],
|
|
[['...', 'method']],
|
|
[['class', '...']],
|
|
];
|
|
}
|
|
|
|
public function testAliases()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container9.php';
|
|
$container->setParameter('foo_bar', 'foo_bar');
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Aliases']));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Aliases();
|
|
$foo = $container->get('foo');
|
|
$this->assertSame($foo, $container->get('alias_for_foo'));
|
|
$this->assertSame($foo, $container->get('alias_for_alias'));
|
|
}
|
|
|
|
/**
|
|
* @group legacy
|
|
* @expectedDeprecation The "alias_for_foo_deprecated" service alias is deprecated. You should stop using it, as it will be removed in the future.
|
|
*/
|
|
public function testAliasesDeprecation()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container_alias_deprecation.php';
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/container_alias_deprecation.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Aliases_Deprecation']));
|
|
|
|
require self::$fixturesPath.'/php/container_alias_deprecation.php';
|
|
$container = new \Symfony_DI_PhpDumper_Test_Aliases_Deprecation();
|
|
$container->get('alias_for_foo_non_deprecated');
|
|
$container->get('alias_for_foo_deprecated');
|
|
}
|
|
|
|
public function testFrozenContainerWithoutAliases()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Frozen_No_Aliases']));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Frozen_No_Aliases();
|
|
$this->assertFalse($container->has('foo'));
|
|
}
|
|
|
|
public function testOverrideServiceWhenUsingADumpedContainer()
|
|
{
|
|
$this->expectException(InvalidArgumentException::class);
|
|
$this->expectExceptionMessage('The "decorator_service" service is already initialized, you cannot replace it.');
|
|
require_once self::$fixturesPath.'/php/services9_compiled.php';
|
|
|
|
$container = new \ProjectServiceContainer();
|
|
$container->get('decorator_service');
|
|
$container->set('decorator_service', $decorator = new \stdClass());
|
|
|
|
$this->assertSame($decorator, $container->get('decorator_service'), '->set() overrides an already defined service');
|
|
}
|
|
|
|
public function testDumpAutowireData()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container24.php';
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services24.php', $dumper->dump());
|
|
}
|
|
|
|
public function testEnvInId()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container_env_in_id.php';
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_env_in_id.php', $dumper->dump());
|
|
}
|
|
|
|
public function testEnvParameter()
|
|
{
|
|
$rand = mt_rand();
|
|
putenv('Baz='.$rand);
|
|
$container = new ContainerBuilder();
|
|
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
|
|
$loader->load('services26.yml');
|
|
$container->setParameter('env(json_file)', self::$fixturesPath.'/array.json');
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services26.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_EnvParameters', 'file' => self::$fixturesPath.'/php/services26.php']));
|
|
|
|
require self::$fixturesPath.'/php/services26.php';
|
|
$container = new \Symfony_DI_PhpDumper_Test_EnvParameters();
|
|
$this->assertSame($rand, $container->getParameter('baz'));
|
|
$this->assertSame([123, 'abc'], $container->getParameter('json'));
|
|
$this->assertSame('sqlite:///foo/bar/var/data.db', $container->getParameter('db_dsn'));
|
|
putenv('Baz');
|
|
}
|
|
|
|
public function testResolvedBase64EnvParameters()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('env(foo)', base64_encode('world'));
|
|
$container->setParameter('hello', '%env(base64:foo)%');
|
|
$container->compile(true);
|
|
|
|
$expected = [
|
|
'env(foo)' => 'd29ybGQ=',
|
|
'hello' => 'world',
|
|
];
|
|
$this->assertSame($expected, $container->getParameterBag()->all());
|
|
}
|
|
|
|
public function testDumpedBase64EnvParameters()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('env(foo)', base64_encode('world'));
|
|
$container->setParameter('hello', '%env(base64:foo)%');
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->dump();
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_base64_env.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Base64Parameters']));
|
|
|
|
require self::$fixturesPath.'/php/services_base64_env.php';
|
|
$container = new \Symfony_DI_PhpDumper_Test_Base64Parameters();
|
|
$this->assertSame('world', $container->getParameter('hello'));
|
|
}
|
|
|
|
public function testDumpedCsvEnvParameters()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('env(foo)', 'foo,bar');
|
|
$container->setParameter('hello', '%env(csv:foo)%');
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->dump();
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_csv_env.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_CsvParameters']));
|
|
|
|
require self::$fixturesPath.'/php/services_csv_env.php';
|
|
$container = new \Symfony_DI_PhpDumper_Test_CsvParameters();
|
|
$this->assertSame(['foo', 'bar'], $container->getParameter('hello'));
|
|
}
|
|
|
|
public function testDumpedDefaultEnvParameters()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('fallback_param', 'baz');
|
|
$container->setParameter('fallback_env', '%env(foobar)%');
|
|
$container->setParameter('env(foobar)', 'foobaz');
|
|
$container->setParameter('env(foo)', '{"foo": "bar"}');
|
|
$container->setParameter('hello', '%env(default:fallback_param:bar)%');
|
|
$container->setParameter('hello-bar', '%env(default:fallback_env:key:baz:json:foo)%');
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->dump();
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_default_env.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_DefaultParameters']));
|
|
|
|
require self::$fixturesPath.'/php/services_default_env.php';
|
|
$container = new \Symfony_DI_PhpDumper_Test_DefaultParameters();
|
|
$this->assertSame('baz', $container->getParameter('hello'));
|
|
$this->assertSame('foobaz', $container->getParameter('hello-bar'));
|
|
}
|
|
|
|
public function testDumpedUrlEnvParameters()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('env(foo)', 'postgres://user@localhost:5432/database?sslmode=disable');
|
|
$container->setParameter('hello', '%env(url:foo)%');
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->dump();
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_url_env.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_UrlParameters']));
|
|
|
|
require self::$fixturesPath.'/php/services_url_env.php';
|
|
$container = new \Symfony_DI_PhpDumper_Test_UrlParameters();
|
|
$this->assertSame([
|
|
'scheme' => 'postgres',
|
|
'host' => 'localhost',
|
|
'port' => 5432,
|
|
'user' => 'user',
|
|
'path' => 'database',
|
|
'query' => 'sslmode=disable',
|
|
'pass' => null,
|
|
'fragment' => null,
|
|
], $container->getParameter('hello'));
|
|
}
|
|
|
|
public function testDumpedQueryEnvParameters()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('env(foo)', 'foo=bar&baz[]=qux');
|
|
$container->setParameter('hello', '%env(query_string:foo)%');
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->dump();
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_query_string_env.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_QueryStringParameters']));
|
|
|
|
require self::$fixturesPath.'/php/services_query_string_env.php';
|
|
$container = new \Symfony_DI_PhpDumper_Test_QueryStringParameters();
|
|
$this->assertSame([
|
|
'foo' => 'bar',
|
|
'baz' => ['qux'],
|
|
], $container->getParameter('hello'));
|
|
}
|
|
|
|
public function testDumpedJsonEnvParameters()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('env(foo)', '["foo","bar"]');
|
|
$container->setParameter('env(bar)', 'null');
|
|
$container->setParameter('hello', '%env(json:foo)%');
|
|
$container->setParameter('hello-bar', '%env(json:bar)%');
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->dump();
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_json_env.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_JsonParameters']));
|
|
|
|
putenv('foobar="hello"');
|
|
require self::$fixturesPath.'/php/services_json_env.php';
|
|
$container = new \Symfony_DI_PhpDumper_Test_JsonParameters();
|
|
$this->assertSame(['foo', 'bar'], $container->getParameter('hello'));
|
|
$this->assertNull($container->getParameter('hello-bar'));
|
|
}
|
|
|
|
public function testCustomEnvParameters()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('env(foo)', str_rot13('world'));
|
|
$container->setParameter('hello', '%env(rot13:foo)%');
|
|
$container->register(Rot13EnvVarProcessor::class)->addTag('container.env_var_processor')->setPublic(true);
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->dump();
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_rot13_env.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Rot13Parameters']));
|
|
|
|
require self::$fixturesPath.'/php/services_rot13_env.php';
|
|
$container = new \Symfony_DI_PhpDumper_Test_Rot13Parameters();
|
|
$this->assertSame('world', $container->getParameter('hello'));
|
|
}
|
|
|
|
public function testFileEnvProcessor()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('env(foo)', __FILE__);
|
|
$container->setParameter('random', '%env(file:foo)%');
|
|
$container->compile(true);
|
|
|
|
$this->assertStringEqualsFile(__FILE__, $container->getParameter('random'));
|
|
}
|
|
|
|
public function testUnusedEnvParameter()
|
|
{
|
|
$this->expectException(EnvParameterException::class);
|
|
$this->expectExceptionMessage('Environment variables "FOO" are never used. Please, check your container\'s configuration.');
|
|
$container = new ContainerBuilder();
|
|
$container->getParameter('env(FOO)');
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->dump();
|
|
}
|
|
|
|
public function testCircularDynamicEnv()
|
|
{
|
|
$this->expectException(ParameterCircularReferenceException::class);
|
|
$this->expectExceptionMessage('Circular reference detected for parameter "env(resolve:DUMMY_ENV_VAR)" ("env(resolve:DUMMY_ENV_VAR)" > "env(resolve:DUMMY_ENV_VAR)").');
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('foo', '%bar%');
|
|
$container->setParameter('bar', '%env(resolve:DUMMY_ENV_VAR)%');
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dump = $dumper->dump(['class' => $class = __FUNCTION__]);
|
|
|
|
eval('?>'.$dump);
|
|
$container = new $class();
|
|
|
|
putenv('DUMMY_ENV_VAR=%foo%');
|
|
try {
|
|
$container->getParameter('bar');
|
|
} finally {
|
|
putenv('DUMMY_ENV_VAR');
|
|
}
|
|
}
|
|
|
|
public function testInlinedDefinitionReferencingServiceContainer()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo', 'stdClass')->addMethodCall('add', [new Reference('service_container')])->setPublic(false);
|
|
$container->register('bar', 'stdClass')->addArgument(new Reference('foo'))->setPublic(true);
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$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))->setPublic(true);
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->setProxyDumper(new \DummyProxyDumper());
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_non_shared_lazy.php', $dumper->dump());
|
|
}
|
|
|
|
public function testNonSharedDuplicates()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo', 'stdClass')->setShared(false);
|
|
$container->register('baz', 'stdClass')->setPublic(true)
|
|
->addArgument(new ServiceLocatorArgument(['foo' => new Reference('foo')]));
|
|
$container->register('bar', 'stdClass')->setPublic(true)
|
|
->addArgument(new Reference('foo'))
|
|
->addArgument(new Reference('foo'))
|
|
;
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->setProxyDumper(new \DummyProxyDumper());
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_non_shared_duplicates.php', $dumper->dump());
|
|
}
|
|
|
|
public function testInitializePropertiesBeforeMethodCalls()
|
|
{
|
|
require_once self::$fixturesPath.'/includes/classes.php';
|
|
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo', 'stdClass')->setPublic(true);
|
|
$container->register('bar', 'MethodCallClass')
|
|
->setPublic(true)
|
|
->setProperty('simple', 'bar')
|
|
->setProperty('complex', new Reference('foo'))
|
|
->addMethodCall('callMe');
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Properties_Before_Method_Calls']));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Properties_Before_Method_Calls();
|
|
$this->assertTrue($container->get('bar')->callPassed(), '->dump() initializes properties before method calls');
|
|
}
|
|
|
|
public function testCircularReferenceAllowanceForLazyServices()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo', 'stdClass')->addArgument(new Reference('bar'))->setPublic(true);
|
|
$container->register('bar', 'stdClass')->setLazy(true)->addArgument(new Reference('foo'))->setPublic(true);
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dumper->setProxyDumper(new \DummyProxyDumper());
|
|
$dumper->dump();
|
|
|
|
$this->addToAssertionCount(1);
|
|
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$message = 'Circular reference detected for service "foo", path: "foo -> bar -> foo". Try running "composer require symfony/proxy-manager-bridge".';
|
|
$this->expectException(ServiceCircularReferenceException::class);
|
|
$this->expectExceptionMessage($message);
|
|
|
|
$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());
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_dedup_lazy_proxy.php', $dumper->dump());
|
|
}
|
|
|
|
public function testLazyArgumentProvideGenerator()
|
|
{
|
|
require_once self::$fixturesPath.'/includes/classes.php';
|
|
|
|
$container = new ContainerBuilder();
|
|
$container->register('lazy_referenced', 'stdClass')->setPublic(true);
|
|
$container
|
|
->register('lazy_context', 'LazyContext')
|
|
->setPublic(true)
|
|
->setArguments([
|
|
new IteratorArgument(['k1' => new Reference('lazy_referenced'), 'k2' => new Reference('service_container')]),
|
|
new IteratorArgument([]),
|
|
])
|
|
;
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Lazy_Argument_Provide_Generator']));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Lazy_Argument_Provide_Generator();
|
|
$lazyContext = $container->get('lazy_context');
|
|
|
|
$this->assertInstanceOf(RewindableGenerator::class, $lazyContext->lazyValues);
|
|
$this->assertInstanceOf(RewindableGenerator::class, $lazyContext->lazyEmptyValues);
|
|
$this->assertCount(2, $lazyContext->lazyValues);
|
|
$this->assertCount(0, $lazyContext->lazyEmptyValues);
|
|
|
|
$i = -1;
|
|
foreach ($lazyContext->lazyValues as $k => $v) {
|
|
switch (++$i) {
|
|
case 0:
|
|
$this->assertEquals('k1', $k);
|
|
$this->assertInstanceOf(\stdClass::class, $v);
|
|
break;
|
|
case 1:
|
|
$this->assertEquals('k2', $k);
|
|
$this->assertInstanceOf(\Symfony_DI_PhpDumper_Test_Lazy_Argument_Provide_Generator::class, $v);
|
|
break;
|
|
}
|
|
}
|
|
|
|
$this->assertEmpty(iterator_to_array($lazyContext->lazyEmptyValues));
|
|
}
|
|
|
|
public function testNormalizedId()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container33.php';
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services33.php', $dumper->dump());
|
|
}
|
|
|
|
public function testDumpContainerBuilderWithFrozenConstructorIncludingPrivateServices()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo_service', 'stdClass')->setArguments([new Reference('baz_service')])->setPublic(true);
|
|
$container->register('bar_service', 'stdClass')->setArguments([new Reference('baz_service')])->setPublic(true);
|
|
$container->register('baz_service', 'stdClass')->setPublic(false);
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_private_frozen.php', $dumper->dump());
|
|
}
|
|
|
|
public function testServiceLocator()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo_service', ServiceLocator::class)
|
|
->setPublic(true)
|
|
->addArgument([
|
|
'bar' => new ServiceClosureArgument(new Reference('bar_service')),
|
|
'baz' => new ServiceClosureArgument(new TypedReference('baz_service', 'stdClass')),
|
|
'nil' => $nil = new ServiceClosureArgument(new Reference('nil')),
|
|
])
|
|
;
|
|
|
|
// no method calls
|
|
$container->register('translator.loader_1', 'stdClass')->setPublic(true);
|
|
$container->register('translator.loader_1_locator', ServiceLocator::class)
|
|
->setPublic(false)
|
|
->addArgument([
|
|
'translator.loader_1' => new ServiceClosureArgument(new Reference('translator.loader_1')),
|
|
]);
|
|
$container->register('translator_1', StubbedTranslator::class)
|
|
->setPublic(true)
|
|
->addArgument(new Reference('translator.loader_1_locator'));
|
|
|
|
// one method calls
|
|
$container->register('translator.loader_2', 'stdClass')->setPublic(true);
|
|
$container->register('translator.loader_2_locator', ServiceLocator::class)
|
|
->setPublic(false)
|
|
->addArgument([
|
|
'translator.loader_2' => new ServiceClosureArgument(new Reference('translator.loader_2')),
|
|
]);
|
|
$container->register('translator_2', StubbedTranslator::class)
|
|
->setPublic(true)
|
|
->addArgument(new Reference('translator.loader_2_locator'))
|
|
->addMethodCall('addResource', ['db', new Reference('translator.loader_2'), 'nl']);
|
|
|
|
// two method calls
|
|
$container->register('translator.loader_3', 'stdClass')->setPublic(true);
|
|
$container->register('translator.loader_3_locator', ServiceLocator::class)
|
|
->setPublic(false)
|
|
->addArgument([
|
|
'translator.loader_3' => new ServiceClosureArgument(new Reference('translator.loader_3')),
|
|
]);
|
|
$container->register('translator_3', StubbedTranslator::class)
|
|
->setPublic(true)
|
|
->addArgument(new Reference('translator.loader_3_locator'))
|
|
->addMethodCall('addResource', ['db', new Reference('translator.loader_3'), 'nl'])
|
|
->addMethodCall('addResource', ['db', new Reference('translator.loader_3'), 'en']);
|
|
|
|
$nil->setValues([null]);
|
|
$container->register('bar_service', 'stdClass')->setArguments([new Reference('baz_service')])->setPublic(true);
|
|
$container->register('baz_service', 'stdClass')->setPublic(false);
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_locator.php', $dumper->dump());
|
|
}
|
|
|
|
public function testServiceSubscriber()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo_service', TestServiceSubscriber::class)
|
|
->setPublic(true)
|
|
->setAutowired(true)
|
|
->addArgument(new Reference(ContainerInterface::class))
|
|
->addTag('container.service_subscriber', [
|
|
'key' => 'bar',
|
|
'id' => TestServiceSubscriber::class,
|
|
])
|
|
;
|
|
$container->register(TestServiceSubscriber::class, TestServiceSubscriber::class)->setPublic(true);
|
|
|
|
$container->register(CustomDefinition::class, CustomDefinition::class)
|
|
->setPublic(false);
|
|
|
|
$container->register(TestDefinition1::class, TestDefinition1::class)->setPublic(true);
|
|
|
|
$container->addCompilerPass(new class() implements CompilerPassInterface {
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function process(ContainerBuilder $container)
|
|
{
|
|
$container->setDefinition('late_alias', new Definition(TestDefinition1::class));
|
|
$container->setAlias(TestDefinition1::class, 'late_alias');
|
|
}
|
|
}, PassConfig::TYPE_AFTER_REMOVING);
|
|
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
|
|
if (80100 <= \PHP_VERSION_ID) {
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_subscriber_php81.php', $dumper->dump());
|
|
} else {
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_subscriber.php', $dumper->dump());
|
|
}
|
|
}
|
|
|
|
public function testPrivateWithIgnoreOnInvalidReference()
|
|
{
|
|
require_once self::$fixturesPath.'/includes/classes.php';
|
|
|
|
$container = new ContainerBuilder();
|
|
$container->register('not_invalid', 'BazClass')
|
|
->setPublic(false);
|
|
$container->register('bar', 'BarClass')
|
|
->setPublic(true)
|
|
->addMethodCall('setBaz', [new Reference('not_invalid', SymfonyContainerInterface::IGNORE_ON_INVALID_REFERENCE)]);
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Private_With_Ignore_On_Invalid_Reference']));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Private_With_Ignore_On_Invalid_Reference();
|
|
$this->assertInstanceOf(\BazClass::class, $container->get('bar')->getBaz());
|
|
}
|
|
|
|
public function testArrayParameters()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setParameter('array_1', [123]);
|
|
$container->setParameter('array_2', [__DIR__]);
|
|
$container->register('bar', 'BarClass')
|
|
->setPublic(true)
|
|
->addMethodCall('setBaz', ['%array_1%', '%array_2%', '%%array_1%%', [123]]);
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_array_params.php', str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dumper->dump(['file' => self::$fixturesPath.'/php/services_array_params.php'])));
|
|
}
|
|
|
|
public function testExpressionReferencingPrivateService()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('private_bar', 'stdClass')
|
|
->setPublic(false);
|
|
$container->register('private_foo', 'stdClass')
|
|
->setPublic(false);
|
|
$container->register('public_foo', 'stdClass')
|
|
->setPublic(true)
|
|
->addArgument(new Expression('service("private_foo").bar'));
|
|
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_private_in_expression.php', $dumper->dump());
|
|
}
|
|
|
|
public function testUninitializedReference()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container_uninitialized_ref.php';
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_uninitialized_ref.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Uninitialized_Reference']));
|
|
|
|
require self::$fixturesPath.'/php/services_uninitialized_ref.php';
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Uninitialized_Reference();
|
|
|
|
$bar = $container->get('bar');
|
|
|
|
$this->assertNull($bar->foo1);
|
|
$this->assertNull($bar->foo2);
|
|
$this->assertNull($bar->foo3);
|
|
$this->assertNull($bar->closures[0]());
|
|
$this->assertNull($bar->closures[1]());
|
|
$this->assertNull($bar->closures[2]());
|
|
$this->assertSame([], iterator_to_array($bar->iter));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Uninitialized_Reference();
|
|
|
|
$container->get('foo1');
|
|
$container->get('baz');
|
|
|
|
$bar = $container->get('bar');
|
|
|
|
$this->assertEquals(new \stdClass(), $bar->foo1);
|
|
$this->assertNull($bar->foo2);
|
|
$this->assertEquals(new \stdClass(), $bar->foo3);
|
|
$this->assertEquals(new \stdClass(), $bar->closures[0]());
|
|
$this->assertNull($bar->closures[1]());
|
|
$this->assertEquals(new \stdClass(), $bar->closures[2]());
|
|
$this->assertEquals(['foo1' => new \stdClass(), 'foo3' => new \stdClass()], iterator_to_array($bar->iter));
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideAlmostCircular
|
|
*/
|
|
public function testAlmostCircular($visibility)
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container_almost_circular.php';
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$container = 'Symfony_DI_PhpDumper_Test_Almost_Circular_'.ucfirst($visibility);
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_almost_circular_'.$visibility.'.php', $dumper->dump(['class' => $container]));
|
|
|
|
require self::$fixturesPath.'/php/services_almost_circular_'.$visibility.'.php';
|
|
|
|
$container = new $container();
|
|
|
|
$entityManager = $container->get('doctrine.entity_manager');
|
|
$this->assertEquals(new \stdClass(), $entityManager);
|
|
|
|
$pA = $container->get('pA');
|
|
$this->assertEquals(new \stdClass(), $pA);
|
|
|
|
$logger = $container->get('monolog.logger');
|
|
$this->assertEquals(new \stdClass(), $logger->handler);
|
|
|
|
$logger_inline = $container->get('monolog_inline.logger');
|
|
$this->assertEquals(new \stdClass(), $logger_inline->handler);
|
|
|
|
$foo = $container->get('foo');
|
|
$this->assertSame($foo, $foo->bar->foobar->foo);
|
|
|
|
$foo2 = $container->get('foo2');
|
|
$this->assertSame($foo2, $foo2->bar->foobar->foo);
|
|
|
|
$this->assertSame([], (array) $container->get('foobar4'));
|
|
|
|
$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) ['bar6' => (object) []], $foo6);
|
|
|
|
$this->assertInstanceOf(\stdClass::class, $container->get('root'));
|
|
|
|
$manager3 = $container->get('manager3');
|
|
$listener3 = $container->get('listener3');
|
|
$this->assertSame($manager3, $listener3->manager);
|
|
|
|
$listener4 = $container->get('listener4');
|
|
$this->assertInstanceOf(\stdClass::class, $listener4);
|
|
}
|
|
|
|
public function provideAlmostCircular()
|
|
{
|
|
yield ['public'];
|
|
yield ['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(['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) ['p2' => (object) ['p3' => (object) []]], $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);
|
|
|
|
$container->getCompiler()->getPassConfig();
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_inline_self_ref.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Inline_Self_Ref']));
|
|
}
|
|
|
|
public function testHotPathOptimizations()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container_inline_requires.php';
|
|
$container->setParameter('inline_requires', true);
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
|
|
$dump = $dumper->dump(['hot_path_tag' => 'container.hot_path', 'inline_class_loader_parameter' => 'inline_requires', 'file' => self::$fixturesPath.'/php/services_inline_requires.php']);
|
|
if ('\\' === \DIRECTORY_SEPARATOR) {
|
|
$dump = str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dump);
|
|
}
|
|
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_inline_requires.php', $dump);
|
|
}
|
|
|
|
public function testDumpHandlesLiteralClassWithRootNamespace()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo', '\\stdClass')->setPublic(true);
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace']));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace();
|
|
|
|
$this->assertInstanceOf(\stdClass::class, $container->get('foo'));
|
|
}
|
|
|
|
public function testDumpHandlesObjectClassNames()
|
|
{
|
|
$container = new ContainerBuilder(new ParameterBag([
|
|
'class' => 'stdClass',
|
|
]));
|
|
|
|
$container->setDefinition('foo', new Definition('%class%'));
|
|
$container->setDefinition('bar', new Definition('stdClass', [
|
|
new Reference('foo'),
|
|
]))->setPublic(true);
|
|
|
|
$container->setParameter('inline_requires', true);
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump([
|
|
'class' => 'Symfony_DI_PhpDumper_Test_Object_Class_Name',
|
|
'inline_class_loader_parameter' => 'inline_requires',
|
|
]));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Object_Class_Name();
|
|
|
|
$this->assertInstanceOf(\stdClass::class, $container->get('bar'));
|
|
}
|
|
|
|
/**
|
|
* @requires PHP 8.1
|
|
*/
|
|
public function testNewInInitializer()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container
|
|
->register('foo', NewInInitializer::class)
|
|
->setPublic(true)
|
|
->setAutowired(true)
|
|
->setArguments(['$bar' => 234]);
|
|
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_new_in_initializer.php', $dumper->dump());
|
|
}
|
|
|
|
/**
|
|
* @requires PHP 8.1
|
|
*/
|
|
public function testDumpHandlesEnumeration()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container
|
|
->register('foo', FooClassWithEnumAttribute::class)
|
|
->setPublic(true)
|
|
->addArgument(FooUnitEnum::BAR);
|
|
|
|
$container->setParameter('unit_enum', FooUnitEnum::BAR);
|
|
$container->setParameter('enum_array', [FooUnitEnum::BAR, FooUnitEnum::FOO]);
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumpedContainer = $dumper->dump([
|
|
'class' => 'Symfony_DI_PhpDumper_Test_Enumeration',
|
|
]));
|
|
|
|
/** @var Container $container */
|
|
$container = new \Symfony_DI_PhpDumper_Test_Enumeration();
|
|
|
|
$this->assertSame(FooUnitEnum::BAR, $container->get('foo')->getBar());
|
|
$this->assertSame(FooUnitEnum::BAR, $container->getParameter('unit_enum'));
|
|
$this->assertSame([FooUnitEnum::BAR, FooUnitEnum::FOO], $container->getParameter('enum_array'));
|
|
$this->assertStringMatchesFormat(<<<'PHP'
|
|
%A
|
|
private function getDynamicParameter(string $name)
|
|
{
|
|
switch ($name) {
|
|
case 'unit_enum': $value = \Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum::BAR; break;
|
|
case 'enum_array': $value = [
|
|
0 => \Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum::BAR,
|
|
1 => \Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum::FOO,
|
|
]; break;
|
|
default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
|
|
}
|
|
%A
|
|
PHP
|
|
, $dumpedContainer
|
|
);
|
|
}
|
|
|
|
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([
|
|
'class' => 'Symfony_DI_PhpDumper_Test_UninitializedSyntheticReference',
|
|
'inline_class_loader_parameter' => 'inline_requires',
|
|
]));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_UninitializedSyntheticReference();
|
|
|
|
$this->assertEquals((object) ['foo' => null], $container->get('bar'));
|
|
|
|
$container->set('foo', (object) [123]);
|
|
$this->assertEquals((object) ['foo' => (object) [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);
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_adawson.php', $dumper->dump());
|
|
}
|
|
|
|
/**
|
|
* This test checks the trigger of a deprecation note and should not be removed in major releases.
|
|
*
|
|
* @group legacy
|
|
* @expectedDeprecation The "foo" service is deprecated. You should stop using it, as it will be removed in the future.
|
|
*/
|
|
public function testPrivateServiceTriggersDeprecation()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo', 'stdClass')
|
|
->setPublic(false)
|
|
->setDeprecated(true);
|
|
$container->register('bar', 'stdClass')
|
|
->setPublic(true)
|
|
->setProperty('foo', new Reference('foo'));
|
|
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Private_Service_Triggers_Deprecation']));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Private_Service_Triggers_Deprecation();
|
|
|
|
$container->get('bar');
|
|
}
|
|
|
|
public function testParameterWithMixedCase()
|
|
{
|
|
$container = new ContainerBuilder(new ParameterBag(['Foo' => 'bar', 'BAR' => 'foo']));
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Parameter_With_Mixed_Case']));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Parameter_With_Mixed_Case();
|
|
|
|
$this->assertSame('bar', $container->getParameter('Foo'));
|
|
$this->assertSame('foo', $container->getParameter('BAR'));
|
|
}
|
|
|
|
public function testErroredDefinition()
|
|
{
|
|
$this->expectException(RuntimeException::class);
|
|
$this->expectExceptionMessage('Service "errored_definition" is broken.');
|
|
$container = include self::$fixturesPath.'/containers/container9.php';
|
|
$container->setParameter('foo_bar', 'foo_bar');
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
$dump = $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Errored_Definition']);
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_errored_definition.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.\DIRECTORY_SEPARATOR.'includes'.\DIRECTORY_SEPARATOR), '%path%', $dump));
|
|
eval('?>'.$dump);
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Errored_Definition();
|
|
$container->get('runtime_error');
|
|
}
|
|
|
|
public function testServiceLocatorArgument()
|
|
{
|
|
$container = include self::$fixturesPath.'/containers/container_service_locator_argument.php';
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
$dump = $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Service_Locator_Argument']);
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_service_locator_argument.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.\DIRECTORY_SEPARATOR.'includes'.\DIRECTORY_SEPARATOR), '%path%', $dump));
|
|
eval('?>'.$dump);
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Service_Locator_Argument();
|
|
$locator = $container->get('bar')->locator;
|
|
|
|
$this->assertInstanceOf(ArgumentServiceLocator::class, $locator);
|
|
$this->assertSame($container->get('foo1'), $locator->get('foo1'));
|
|
$this->assertEquals(new \stdClass(), $locator->get('foo2'));
|
|
$this->assertSame($locator->get('foo2'), $locator->get('foo2'));
|
|
$this->assertEquals(new \stdClass(), $locator->get('foo3'));
|
|
$this->assertNotSame($locator->get('foo3'), $locator->get('foo3'));
|
|
|
|
try {
|
|
$locator->get('foo4');
|
|
$this->fail('RuntimeException expected.');
|
|
} catch (RuntimeException $e) {
|
|
$this->assertSame('BOOM', $e->getMessage());
|
|
}
|
|
|
|
$this->assertNull($locator->get('foo5'));
|
|
|
|
$container->set('foo5', $foo5 = new \stdClass());
|
|
$this->assertSame($foo5, $locator->get('foo5'));
|
|
}
|
|
|
|
public function testScalarService()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register('foo', 'string')
|
|
->setFactory([ScalarFactory::class, 'getSomeValue'])
|
|
;
|
|
$container->register('bar', 'stdClass')
|
|
->setProperty('foo', new Reference('foo'))
|
|
->setPublic(true)
|
|
;
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
eval('?>'.$dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Scalar_Service']));
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Test_Scalar_Service();
|
|
|
|
$this->assertSame('some value', $container->get('bar')->foo);
|
|
}
|
|
|
|
public function testAliasCanBeFoundInTheDumpedContainerWhenBothTheAliasAndTheServiceArePublic()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
|
|
$container->register('foo', 'stdClass')->setPublic(true);
|
|
$container->setAlias('bar', 'foo')->setPublic(true);
|
|
|
|
$container->compile();
|
|
|
|
// Bar is found in the compiled container
|
|
$service_ids = $container->getServiceIds();
|
|
$this->assertContains('bar', $service_ids);
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dump = $dumper->dump(['class' => 'Symfony_DI_PhpDumper_AliasesCanBeFoundInTheDumpedContainer']);
|
|
eval('?>'.$dump);
|
|
|
|
$container = new \Symfony_DI_PhpDumper_AliasesCanBeFoundInTheDumpedContainer();
|
|
|
|
// Bar should still be found in the compiled container
|
|
$service_ids = $container->getServiceIds();
|
|
$this->assertContains('bar', $service_ids);
|
|
}
|
|
|
|
public function testWither()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->register(Foo::class);
|
|
|
|
$container
|
|
->register('wither', Wither::class)
|
|
->setPublic(true)
|
|
->setAutowired(true);
|
|
|
|
$container->compile();
|
|
$dumper = new PhpDumper($container);
|
|
$dump = $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Service_Wither']);
|
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_wither.php', $dump);
|
|
eval('?>'.$dump);
|
|
|
|
$container = new \Symfony_DI_PhpDumper_Service_Wither();
|
|
|
|
$wither = $container->get('wither');
|
|
$this->assertInstanceOf(Foo::class, $wither->foo);
|
|
}
|
|
|
|
/**
|
|
* @group legacy
|
|
* @expectedDeprecation The "deprecated1" service alias is deprecated. You should stop using it, as it will be removed in the future.
|
|
* @expectedDeprecation The "deprecated2" service alias is deprecated. You should stop using it, as it will be removed in the future.
|
|
*/
|
|
public function testMultipleDeprecatedAliasesWorking()
|
|
{
|
|
$container = new ContainerBuilder();
|
|
$container->setDefinition('bar', new Definition('stdClass'))->setPublic(true);
|
|
$container->setAlias('deprecated1', 'bar')->setPublic(true)->setDeprecated('%alias_id% is deprecated');
|
|
$container->setAlias('deprecated2', 'bar')->setPublic(true)->setDeprecated('%alias_id% is deprecated');
|
|
$container->compile();
|
|
|
|
$dumper = new PhpDumper($container);
|
|
$dump = $dumper->dump(['class' => $class = __FUNCTION__]);
|
|
|
|
eval('?>'.$dump);
|
|
$container = new $class();
|
|
|
|
$this->assertInstanceOf(\stdClass::class, $container->get('bar'));
|
|
$this->assertInstanceOf(\stdClass::class, $container->get('deprecated1'));
|
|
$this->assertInstanceOf(\stdClass::class, $container->get('deprecated2'));
|
|
}
|
|
}
|
|
|
|
class Rot13EnvVarProcessor implements EnvVarProcessorInterface
|
|
{
|
|
public function getEnv($prefix, $name, \Closure $getEnv)
|
|
{
|
|
return str_rot13($getEnv($name));
|
|
}
|
|
|
|
public static function getProvidedTypes(): array
|
|
{
|
|
return ['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;
|
|
}
|
|
}
|