tikiwiki/packages/tiki-pkg-tikimanager/symfony/dependency-injection/Tests/Dumper/PhpDumperTest.php

1490 lines
62 KiB
PHP
Raw Normal View History

2023-11-20 21:52:04 +01:00
<?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;
}
}