Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

View file

@ -0,0 +1,38 @@
<?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\Loader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
class ClosureLoaderTest extends TestCase
{
public function testSupports()
{
$loader = new ClosureLoader(new ContainerBuilder());
$this->assertTrue($loader->supports(function ($container) {}), '->supports() returns true if the resource is loadable');
$this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
}
public function testLoad()
{
$loader = new ClosureLoader($container = new ContainerBuilder());
$loader->load(function ($container) {
$container->setParameter('foo', 'foo');
});
$this->assertEquals('foo', $container->getParameter('foo'), '->load() loads a \Closure resource');
}
}

View file

@ -0,0 +1,80 @@
<?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\Loader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\DirectoryLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
class DirectoryLoaderTest extends TestCase
{
private static $fixturesPath;
private $container;
private $loader;
public static function setUpBeforeClass()
{
self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
}
protected function setUp()
{
$locator = new FileLocator(self::$fixturesPath);
$this->container = new ContainerBuilder();
$this->loader = new DirectoryLoader($this->container, $locator);
$resolver = new LoaderResolver(array(
new PhpFileLoader($this->container, $locator),
new IniFileLoader($this->container, $locator),
new YamlFileLoader($this->container, $locator),
$this->loader,
));
$this->loader->setResolver($resolver);
}
public function testDirectoryCanBeLoadedRecursively()
{
$this->loader->load('directory/');
$this->assertEquals(array('ini' => 'ini', 'yaml' => 'yaml', 'php' => 'php'), $this->container->getParameterBag()->all(), '->load() takes a single directory');
}
public function testImports()
{
$this->loader->resolve('directory/import/import.yml')->load('directory/import/import.yml');
$this->assertEquals(array('ini' => 'ini', 'yaml' => 'yaml'), $this->container->getParameterBag()->all(), '->load() takes a single file that imports a directory');
}
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage The file "foo" does not exist (in:
*/
public function testExceptionIsRaisedWhenDirectoryDoesNotExist()
{
$this->loader->load('foo/');
}
public function testSupports()
{
$loader = new DirectoryLoader(new ContainerBuilder(), new FileLocator());
$this->assertTrue($loader->supports('directory/'), '->supports("directory/") returns true');
$this->assertTrue($loader->supports('directory/', 'directory'), '->supports("directory/", "directory") returns true');
$this->assertFalse($loader->supports('directory'), '->supports("directory") returns false');
$this->assertTrue($loader->supports('directory', 'directory'), '->supports("directory", "directory") returns true');
$this->assertFalse($loader->supports('directory', 'foo'), '->supports("directory", "foo") returns false');
}
}

View file

@ -0,0 +1,241 @@
<?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\Loader;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface as PsrContainerInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Loader\FileLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses\MissingParent;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\FooInterface;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\OtherDir\AnotherSub\DeeperBaz;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\OtherDir\Baz;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\BarInterface;
class FileLoaderTest extends TestCase
{
protected static $fixturesPath;
public static function setUpBeforeClass()
{
self::$fixturesPath = realpath(__DIR__.'/../');
}
public function testImportWithGlobPattern()
{
$container = new ContainerBuilder();
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath));
$resolver = new LoaderResolver(array(
new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/ini')),
new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
new PhpFileLoader($container, new FileLocator(self::$fixturesPath.'/php')),
new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')),
));
$loader->setResolver($resolver);
$loader->import('{F}ixtures/{xml,yaml}/services2.{yml,xml}');
$actual = $container->getParameterBag()->all();
$expected = array(
'a string',
'foo' => 'bar',
'values' => array(
0,
'integer' => 4,
100 => null,
'true',
true,
false,
'on',
'off',
'float' => 1.3,
1000.3,
'a string',
array('foo', 'bar'),
),
'mixedcase' => array('MixedCaseKey' => 'value'),
'constant' => PHP_EOL,
'bar' => '%foo%',
'escape' => '@escapeme',
'foo_bar' => new Reference('foo_bar'),
);
$this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files');
}
public function testRegisterClasses()
{
$container = new ContainerBuilder();
$container->setParameter('sub_dir', 'Sub');
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath.'/Fixtures'));
$loader->registerClasses(new Definition(), 'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\\', 'Prototype/%sub_dir%/*');
$this->assertEquals(
array('service_container', Bar::class),
array_keys($container->getDefinitions())
);
$this->assertEquals(
array(
PsrContainerInterface::class,
ContainerInterface::class,
BarInterface::class,
),
array_keys($container->getAliases())
);
}
public function testRegisterClassesWithExclude()
{
$container = new ContainerBuilder();
$container->setParameter('other_dir', 'OtherDir');
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath.'/Fixtures'));
$loader->registerClasses(
new Definition(),
'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\\',
'Prototype/*',
// load everything, except OtherDir/AnotherSub & Foo.php
'Prototype/{%other_dir%/AnotherSub,Foo.php}'
);
$this->assertTrue($container->has(Bar::class));
$this->assertTrue($container->has(Baz::class));
$this->assertFalse($container->has(Foo::class));
$this->assertFalse($container->has(DeeperBaz::class));
$this->assertEquals(
array(
PsrContainerInterface::class,
ContainerInterface::class,
BarInterface::class,
),
array_keys($container->getAliases())
);
}
public function testNestedRegisterClasses()
{
$container = new ContainerBuilder();
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath.'/Fixtures'));
$prototype = new Definition();
$prototype->setPublic(true)->setPrivate(true);
$loader->registerClasses($prototype, 'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\\', 'Prototype/*');
$this->assertTrue($container->has(Bar::class));
$this->assertTrue($container->has(Baz::class));
$this->assertTrue($container->has(Foo::class));
$this->assertEquals(
array(
PsrContainerInterface::class,
ContainerInterface::class,
FooInterface::class,
),
array_keys($container->getAliases())
);
$alias = $container->getAlias(FooInterface::class);
$this->assertSame(Foo::class, (string) $alias);
$this->assertFalse($alias->isPublic());
$this->assertFalse($alias->isPrivate());
}
public function testMissingParentClass()
{
$container = new ContainerBuilder();
$container->setParameter('bad_classes_dir', 'BadClasses');
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath.'/Fixtures'));
$loader->registerClasses(
(new Definition())->setPublic(false),
'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses\\',
'Prototype/%bad_classes_dir%/*'
);
$this->assertTrue($container->has(MissingParent::class));
$this->assertSame(
array('While discovering services from namespace "Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses\", an error was thrown when processing the class "Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses\MissingParent": "Class Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses\MissingClass not found".'),
$container->getDefinition(MissingParent::class)->getErrors()
);
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegExp /Expected to find class "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\Prototype\\Bar" in file ".+" while importing services from resource "Prototype\/Sub\/\*", but it was not found\! Check the namespace prefix used with the resource/
*/
public function testRegisterClassesWithBadPrefix()
{
$container = new ContainerBuilder();
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath.'/Fixtures'));
// the Sub is missing from namespace prefix
$loader->registerClasses(new Definition(), 'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\\', 'Prototype/Sub/*');
}
/**
* @dataProvider getIncompatibleExcludeTests
*/
public function testRegisterClassesWithIncompatibleExclude($resourcePattern, $excludePattern)
{
$container = new ContainerBuilder();
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath.'/Fixtures'));
try {
$loader->registerClasses(
new Definition(),
'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\\',
$resourcePattern,
$excludePattern
);
} catch (InvalidArgumentException $e) {
$this->assertEquals(
sprintf('Invalid "exclude" pattern when importing classes for "Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\": make sure your "exclude" pattern (%s) is a subset of the "resource" pattern (%s)', $excludePattern, $resourcePattern),
$e->getMessage()
);
}
}
public function getIncompatibleExcludeTests()
{
yield array('Prototype/*', 'yaml/*', false);
yield array('Prototype/OtherDir/*', 'Prototype/*', false);
}
}
class TestFileLoader extends FileLoader
{
public function load($resource, $type = null)
{
return $resource;
}
public function supports($resource, $type = null)
{
return false;
}
}

View file

@ -0,0 +1,44 @@
<?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\Loader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Resource\GlobResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\GlobFileLoader;
class GlobFileLoaderTest extends TestCase
{
public function testSupports()
{
$loader = new GlobFileLoader(new ContainerBuilder(), new FileLocator());
$this->assertTrue($loader->supports('any-path', 'glob'), '->supports() returns true if the resource has the glob type');
$this->assertFalse($loader->supports('any-path'), '->supports() returns false if the resource is not of glob type');
}
public function testLoadAddsTheGlobResourceToTheContainer()
{
$loader = new GlobFileLoaderWithoutImport($container = new ContainerBuilder(), new FileLocator());
$loader->load(__DIR__.'/../Fixtures/config/*');
$this->assertEquals(new GlobResource(__DIR__.'/../Fixtures/config', '/*', false), $container->getResources()[1]);
}
}
class GlobFileLoaderWithoutImport extends GlobFileLoader
{
public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
{
}
}

View file

@ -0,0 +1,133 @@
<?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\Loader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
class IniFileLoaderTest extends TestCase
{
protected $container;
protected $loader;
protected function setUp()
{
$this->container = new ContainerBuilder();
$this->loader = new IniFileLoader($this->container, new FileLocator(realpath(__DIR__.'/../Fixtures/').'/ini'));
}
public function testIniFileCanBeLoaded()
{
$this->loader->load('parameters.ini');
$this->assertEquals(array('foo' => 'bar', 'bar' => '%foo%'), $this->container->getParameterBag()->all(), '->load() takes a single file name as its first argument');
}
/**
* @dataProvider getTypeConversions
*/
public function testTypeConversions($key, $value, $supported)
{
$this->loader->load('types.ini');
$parameters = $this->container->getParameterBag()->all();
$this->assertSame($value, $parameters[$key], '->load() converts values to PHP types');
}
/**
* @dataProvider getTypeConversions
* @requires PHP 5.6.1
* This test illustrates where our conversions differs from INI_SCANNER_TYPED introduced in PHP 5.6.1
*/
public function testTypeConversionsWithNativePhp($key, $value, $supported)
{
if (\defined('HHVM_VERSION_ID')) {
$this->markTestSkipped();
}
if (!$supported) {
$this->markTestSkipped(sprintf('Converting the value "%s" to "%s" is not supported by the IniFileLoader.', $key, $value));
}
$this->loader->load('types.ini');
$expected = parse_ini_file(__DIR__.'/../Fixtures/ini/types.ini', true, INI_SCANNER_TYPED);
$this->assertSame($value, $expected['parameters'][$key], '->load() converts values to PHP types');
}
public function getTypeConversions()
{
return array(
array('true_comment', true, true),
array('true', true, true),
array('false', false, true),
array('on', true, true),
array('off', false, true),
array('yes', true, true),
array('no', false, true),
array('none', false, true),
array('null', null, true),
array('constant', PHP_VERSION, true),
array('12', 12, true),
array('12_string', '12', true),
array('12_comment', 12, true),
array('12_string_comment', '12', true),
array('12_string_comment_again', '12', true),
array('-12', -12, true),
array('1', 1, true),
array('0', 0, true),
array('0b0110', bindec('0b0110'), false), // not supported by INI_SCANNER_TYPED
array('11112222333344445555', '1111,2222,3333,4444,5555', true),
array('0777', 0777, false), // not supported by INI_SCANNER_TYPED
array('255', 0xFF, false), // not supported by INI_SCANNER_TYPED
array('100.0', 1e2, false), // not supported by INI_SCANNER_TYPED
array('-120.0', -1.2E2, false), // not supported by INI_SCANNER_TYPED
array('-10100.1', -10100.1, false), // not supported by INI_SCANNER_TYPED
array('-10,100.1', '-10,100.1', true),
);
}
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage The file "foo.ini" does not exist (in:
*/
public function testExceptionIsRaisedWhenIniFileDoesNotExist()
{
$this->loader->load('foo.ini');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage The "nonvalid.ini" file is not valid.
*/
public function testExceptionIsRaisedWhenIniFileCannotBeParsed()
{
@$this->loader->load('nonvalid.ini');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage The "almostvalid.ini" file is not valid.
*/
public function testExceptionIsRaisedWhenIniFileIsAlmostValid()
{
@$this->loader->load('almostvalid.ini');
}
public function testSupports()
{
$loader = new IniFileLoader(new ContainerBuilder(), new FileLocator());
$this->assertTrue($loader->supports('foo.ini'), '->supports() returns true if the resource is loadable');
$this->assertFalse($loader->supports('foo.foo'), '->supports() returns false if the resource is not loadable');
$this->assertTrue($loader->supports('with_wrong_ext.yml', 'ini'), '->supports() returns true if the resource with forced type is loadable');
}
}

View file

@ -0,0 +1,62 @@
<?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\Loader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
class LoaderResolverTest extends TestCase
{
private static $fixturesPath;
/** @var LoaderResolver */
private $resolver;
protected function setUp()
{
self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
$container = new ContainerBuilder();
$this->resolver = new LoaderResolver(array(
new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')),
new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/ini')),
new PhpFileLoader($container, new FileLocator(self::$fixturesPath.'/php')),
new ClosureLoader($container),
));
}
public function provideResourcesToLoad()
{
return array(
array('ini_with_wrong_ext.xml', 'ini', IniFileLoader::class),
array('xml_with_wrong_ext.php', 'xml', XmlFileLoader::class),
array('php_with_wrong_ext.yml', 'php', PhpFileLoader::class),
array('yaml_with_wrong_ext.ini', 'yaml', YamlFileLoader::class),
);
}
/**
* @dataProvider provideResourcesToLoad
*/
public function testResolvesForcedType($resource, $type, $expectedClass)
{
$this->assertInstanceOf($expectedClass, $this->resolver->resolve($resource, $type));
}
}

View file

@ -0,0 +1,105 @@
<?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\Loader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
class PhpFileLoaderTest extends TestCase
{
public function testSupports()
{
$loader = new PhpFileLoader(new ContainerBuilder(), new FileLocator());
$this->assertTrue($loader->supports('foo.php'), '->supports() returns true if the resource is loadable');
$this->assertFalse($loader->supports('foo.foo'), '->supports() returns false if the resource is not loadable');
$this->assertTrue($loader->supports('with_wrong_ext.yml', 'php'), '->supports() returns true if the resource with forced type is loadable');
}
public function testLoad()
{
$loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator());
$loader->load(__DIR__.'/../Fixtures/php/simple.php');
$this->assertEquals('foo', $container->getParameter('foo'), '->load() loads a PHP file resource');
}
public function testConfigServices()
{
$fixtures = realpath(__DIR__.'/../Fixtures');
$loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator());
$loader->load($fixtures.'/config/services9.php');
$container->compile();
$dumper = new PhpDumper($container);
$this->assertStringEqualsFile($fixtures.'/php/services9_compiled.php', str_replace(str_replace('\\', '\\\\', $fixtures.\DIRECTORY_SEPARATOR.'includes'.\DIRECTORY_SEPARATOR), '%path%', $dumper->dump()));
}
/**
* @dataProvider provideConfig
*/
public function testConfig($file)
{
$fixtures = realpath(__DIR__.'/../Fixtures');
$loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator());
$loader->load($fixtures.'/config/'.$file.'.php');
$container->compile();
$dumper = new YamlDumper($container);
$this->assertStringEqualsFile($fixtures.'/config/'.$file.'.expected.yml', $dumper->dump());
}
public function provideConfig()
{
yield array('basic');
yield array('defaults');
yield array('instanceof');
yield array('prototype');
yield array('child');
if (\PHP_VERSION_ID >= 70000) {
yield array('php7');
}
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage The service "child_service" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service.
*/
public function testAutoConfigureAndChildDefinitionNotAllowed()
{
$fixtures = realpath(__DIR__.'/../Fixtures');
$container = new ContainerBuilder();
$loader = new PhpFileLoader($container, new FileLocator());
$loader->load($fixtures.'/config/services_autoconfigure_with_parent.php');
$container->compile();
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage Invalid factory "factory:method": the `service:method` notation is not available when using PHP-based DI configuration. Use "[ref('factory'), 'method']" instead.
*/
public function testFactoryShortNotationNotAllowed()
{
$fixtures = realpath(__DIR__.'/../Fixtures');
$container = new ContainerBuilder();
$loader = new PhpFileLoader($container, new FileLocator());
$loader->load($fixtures.'/config/factory_short_notation.php');
$container->compile();
}
}

View file

@ -0,0 +1,823 @@
<?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\Loader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Resource\GlobResource;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Bar;
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface;
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
use Symfony\Component\ExpressionLanguage\Expression;
class XmlFileLoaderTest extends TestCase
{
protected static $fixturesPath;
public static function setUpBeforeClass()
{
self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
require_once self::$fixturesPath.'/includes/foo.php';
require_once self::$fixturesPath.'/includes/ProjectExtension.php';
require_once self::$fixturesPath.'/includes/ProjectWithXsdExtension.php';
}
public function testLoad()
{
$loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));
try {
$loader->load('foo.xml');
$this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist');
} catch (\Exception $e) {
$this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist');
$this->assertStringStartsWith('The file "foo.xml" does not exist (in:', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist');
}
}
public function testParseFile()
{
$loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));
$r = new \ReflectionObject($loader);
$m = $r->getMethod('parseFileToDOM');
$m->setAccessible(true);
try {
$m->invoke($loader, self::$fixturesPath.'/ini/parameters.ini');
$this->fail('->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'parameters.ini'), $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
$e = $e->getPrevious();
$this->assertInstanceOf('InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
$this->assertStringStartsWith('[ERROR 4] Start tag expected, \'<\' not found (in', $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
}
$loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/xml'));
try {
$m->invoke($loader, self::$fixturesPath.'/xml/nonvalid.xml');
$this->fail('->parseFileToDOM() throws an InvalidArgumentException if the loaded file does not validate the XSD');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file does not validate the XSD');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'nonvalid.xml'), $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
$e = $e->getPrevious();
$this->assertInstanceOf('InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file does not validate the XSD');
$this->assertStringStartsWith('[ERROR 1845] Element \'nonvalid\': No matching global declaration available for the validation root. (in', $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file does not validate the XSD');
}
$xml = $m->invoke($loader, self::$fixturesPath.'/xml/services1.xml');
$this->assertInstanceOf('DOMDocument', $xml, '->parseFileToDOM() returns an SimpleXMLElement object');
}
public function testLoadWithExternalEntitiesDisabled()
{
$disableEntities = libxml_disable_entity_loader(true);
$containerBuilder = new ContainerBuilder();
$loader = new XmlFileLoader($containerBuilder, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services2.xml');
libxml_disable_entity_loader($disableEntities);
$this->assertGreaterThan(0, $containerBuilder->getParameterBag()->all(), 'Parameters can be read from the config file.');
}
public function testLoadParameters()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services2.xml');
$actual = $container->getParameterBag()->all();
$expected = array(
'a string',
'foo' => 'bar',
'values' => array(
0,
'integer' => 4,
100 => null,
'true',
true,
false,
'on',
'off',
'float' => 1.3,
1000.3,
'a string',
array('foo', 'bar'),
),
'mixedcase' => array('MixedCaseKey' => 'value'),
'constant' => PHP_EOL,
);
$this->assertEquals($expected, $actual, '->load() converts XML values to PHP ones');
}
public function testLoadImports()
{
$container = new ContainerBuilder();
$resolver = new LoaderResolver(array(
new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/ini')),
new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yml')),
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
));
$loader->setResolver($resolver);
$loader->load('services4.xml');
$actual = $container->getParameterBag()->all();
$expected = array(
'a string',
'foo' => 'bar',
'values' => array(
0,
'integer' => 4,
100 => null,
'true',
true,
false,
'on',
'off',
'float' => 1.3,
1000.3,
'a string',
array('foo', 'bar'),
),
'mixedcase' => array('MixedCaseKey' => 'value'),
'constant' => PHP_EOL,
'bar' => '%foo%',
'imported_from_ini' => true,
'imported_from_yaml' => true,
'with_wrong_ext' => 'from yaml',
);
$this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files');
$this->assertTrue($actual['imported_from_ini']);
// Bad import throws no exception due to ignore_errors value.
$loader->load('services4_bad_import.xml');
}
public function testLoadAnonymousServices()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services5.xml');
$services = $container->getDefinitions();
$this->assertCount(7, $services, '->load() attributes unique ids to anonymous services');
// anonymous service as an argument
$args = $services['foo']->getArguments();
$this->assertCount(1, $args, '->load() references anonymous services as "normal" ones');
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $args[0], '->load() converts anonymous services to references to "normal" services');
$this->assertArrayHasKey((string) $args[0], $services, '->load() makes a reference to the created ones');
$inner = $services[(string) $args[0]];
$this->assertEquals('BarClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');
$this->assertFalse($inner->isPublic());
// inner anonymous services
$args = $inner->getArguments();
$this->assertCount(1, $args, '->load() references anonymous services as "normal" ones');
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $args[0], '->load() converts anonymous services to references to "normal" services');
$this->assertArrayHasKey((string) $args[0], $services, '->load() makes a reference to the created ones');
$inner = $services[(string) $args[0]];
$this->assertEquals('BazClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');
$this->assertFalse($inner->isPublic());
// anonymous service as a property
$properties = $services['foo']->getProperties();
$property = $properties['p'];
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $property, '->load() converts anonymous services to references to "normal" services');
$this->assertArrayHasKey((string) $property, $services, '->load() makes a reference to the created ones');
$inner = $services[(string) $property];
$this->assertEquals('BuzClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');
$this->assertFalse($inner->isPublic());
// "wild" service
$service = $container->findTaggedServiceIds('biz_tag');
$this->assertCount(1, $service);
foreach ($service as $id => $tag) {
$service = $container->getDefinition($id);
}
$this->assertEquals('BizClass', $service->getClass(), '->load() uses the same configuration as for the anonymous ones');
$this->assertTrue($service->isPublic());
// anonymous services are shared when using decoration definitions
$container->compile();
$services = $container->getDefinitions();
$fooArgs = $services['foo']->getArguments();
$barArgs = $services['bar']->getArguments();
$this->assertSame($fooArgs[0], $barArgs[0]);
}
/**
* @group legacy
* @expectedDeprecation Top-level anonymous services are deprecated since Symfony 3.4, the "id" attribute will be required in version 4.0 in %sservices_without_id.xml at line 5.
*/
public function testLoadAnonymousServicesWithoutId()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_without_id.xml');
}
public function testLoadAnonymousNestedServices()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('nested_service_without_id.xml');
$this->assertTrue($container->hasDefinition('FooClass'));
$arguments = $container->getDefinition('FooClass')->getArguments();
$this->assertInstanceOf(Reference::class, array_shift($arguments));
}
public function testLoadServices()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services6.xml');
$services = $container->getDefinitions();
$this->assertArrayHasKey('foo', $services, '->load() parses <service> elements');
$this->assertFalse($services['not_shared']->isShared(), '->load() parses shared flag');
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Definition', $services['foo'], '->load() converts <service> element to Definition instances');
$this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute');
$this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag');
$this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags');
$this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag');
$this->assertEquals(array(new Reference('baz'), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag');
$this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag');
$this->assertEquals(array(array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ (container.hasParameter("foo") ? parameter("foo") : "default")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag');
$this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag');
$this->assertEquals('factory', $services['new_factory1']->getFactory(), '->load() parses the factory tag');
$this->assertEquals(array(new Reference('baz'), 'getClass'), $services['new_factory2']->getFactory(), '->load() parses the factory tag');
$this->assertEquals(array('BazClass', 'getInstance'), $services['new_factory3']->getFactory(), '->load() parses the factory tag');
$this->assertSame(array(null, 'getInstance'), $services['new_factory4']->getFactory(), '->load() accepts factory tag without class');
$aliases = $container->getAliases();
$this->assertArrayHasKey('alias_for_foo', $aliases, '->load() parses <service> elements');
$this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases');
$this->assertTrue($aliases['alias_for_foo']->isPublic());
$this->assertArrayHasKey('another_alias_for_foo', $aliases);
$this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
$this->assertFalse($aliases['another_alias_for_foo']->isPublic());
$this->assertEquals(array('decorated', null, 0), $services['decorator_service']->getDecoratedService());
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 0), $services['decorator_service_with_name']->getDecoratedService());
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 5), $services['decorator_service_with_name_and_priority']->getDecoratedService());
}
public function testParsesIteratorArgument()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services9.xml');
$lazyDefinition = $container->getDefinition('lazy_context');
$this->assertEquals(array(new IteratorArgument(array('k1' => new Reference('foo.baz'), 'k2' => new Reference('service_container'))), new IteratorArgument(array())), $lazyDefinition->getArguments(), '->load() parses lazy arguments');
}
public function testParsesTags()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services10.xml');
$services = $container->findTaggedServiceIds('foo_tag');
$this->assertCount(1, $services);
foreach ($services as $id => $tagAttributes) {
foreach ($tagAttributes as $attributes) {
$this->assertArrayHasKey('other_option', $attributes);
$this->assertEquals('lorem', $attributes['other_option']);
$this->assertArrayHasKey('other-option', $attributes, 'unnormalized tag attributes should not be removed');
$this->assertEquals('ciz', $attributes['some_option'], 'no overriding should be done when normalizing');
$this->assertEquals('cat', $attributes['some-option']);
$this->assertArrayNotHasKey('an_other_option', $attributes, 'normalization should not be done when an underscore is already found');
}
}
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
*/
public function testParseTagsWithoutNameThrowsException()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('tag_without_name.xml');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegExp /The tag name for service ".+" in .* must be a non-empty string/
*/
public function testParseTagWithEmptyNameThrowsException()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('tag_with_empty_name.xml');
}
public function testDeprecated()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_deprecated.xml');
$this->assertTrue($container->getDefinition('foo')->isDeprecated());
$message = 'The "foo" service is deprecated. You should stop using it, as it will soon be removed.';
$this->assertSame($message, $container->getDefinition('foo')->getDeprecationMessage('foo'));
$this->assertTrue($container->getDefinition('bar')->isDeprecated());
$message = 'The "bar" service is deprecated.';
$this->assertSame($message, $container->getDefinition('bar')->getDeprecationMessage('bar'));
}
public function testConvertDomElementToArray()
{
$doc = new \DOMDocument('1.0');
$doc->loadXML('<foo>bar</foo>');
$this->assertEquals('bar', XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
$doc = new \DOMDocument('1.0');
$doc->loadXML('<foo foo="bar" />');
$this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
$doc = new \DOMDocument('1.0');
$doc->loadXML('<foo><foo>bar</foo></foo>');
$this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
$doc = new \DOMDocument('1.0');
$doc->loadXML('<foo><foo>bar<foo>bar</foo></foo></foo>');
$this->assertEquals(array('foo' => array('value' => 'bar', 'foo' => 'bar')), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
$doc = new \DOMDocument('1.0');
$doc->loadXML('<foo><foo></foo></foo>');
$this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
$doc = new \DOMDocument('1.0');
$doc->loadXML('<foo><foo><!-- foo --></foo></foo>');
$this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
$doc = new \DOMDocument('1.0');
$doc->loadXML('<foo><foo foo="bar"/><foo foo="bar"/></foo>');
$this->assertEquals(array('foo' => array(array('foo' => 'bar'), array('foo' => 'bar'))), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
}
public function testExtensions()
{
$container = new ContainerBuilder();
$container->registerExtension(new \ProjectExtension());
$container->registerExtension(new \ProjectWithXsdExtension());
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
// extension without an XSD
$loader->load('extensions/services1.xml');
$container->compile();
$services = $container->getDefinitions();
$parameters = $container->getParameterBag()->all();
$this->assertArrayHasKey('project.service.bar', $services, '->load() parses extension elements');
$this->assertArrayHasKey('project.parameter.bar', $parameters, '->load() parses extension elements');
$this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
$this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');
// extension with an XSD
$container = new ContainerBuilder();
$container->registerExtension(new \ProjectExtension());
$container->registerExtension(new \ProjectWithXsdExtension());
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('extensions/services2.xml');
$container->compile();
$services = $container->getDefinitions();
$parameters = $container->getParameterBag()->all();
$this->assertArrayHasKey('project.service.bar', $services, '->load() parses extension elements');
$this->assertArrayHasKey('project.parameter.bar', $parameters, '->load() parses extension elements');
$this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
$this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');
$container = new ContainerBuilder();
$container->registerExtension(new \ProjectExtension());
$container->registerExtension(new \ProjectWithXsdExtension());
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
// extension with an XSD (does not validate)
try {
$loader->load('extensions/services3.xml');
$this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services3.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
$e = $e->getPrevious();
$this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
$this->assertContains('The attribute \'bar\' is not allowed', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
}
// non-registered extension
try {
$loader->load('extensions/services4.xml');
$this->fail('->load() throws an InvalidArgumentException if the tag is not valid');
} catch (\Exception $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid');
$this->assertStringStartsWith('There is no extension able to load the configuration for "project:bar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid');
}
}
public function testExtensionInPhar()
{
if (\extension_loaded('suhosin') && false === strpos(ini_get('suhosin.executor.include.whitelist'), 'phar')) {
$this->markTestSkipped('To run this test, add "phar" to the "suhosin.executor.include.whitelist" settings in your php.ini file.');
}
if (\defined('HHVM_VERSION')) {
$this->markTestSkipped('HHVM makes this test conflict with those run in separate processes.');
}
require_once self::$fixturesPath.'/includes/ProjectWithXsdExtensionInPhar.phar';
// extension with an XSD in PHAR archive
$container = new ContainerBuilder();
$container->registerExtension(new \ProjectWithXsdExtensionInPhar());
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('extensions/services6.xml');
// extension with an XSD in PHAR archive (does not validate)
try {
$loader->load('extensions/services7.xml');
$this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services7.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
$e = $e->getPrevious();
$this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
$this->assertContains('The attribute \'bar\' is not allowed', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
}
}
public function testSupports()
{
$loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator());
$this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable');
$this->assertFalse($loader->supports('foo.foo'), '->supports() returns false if the resource is not loadable');
$this->assertTrue($loader->supports('with_wrong_ext.yml', 'xml'), '->supports() returns true if the resource with forced type is loadable');
}
public function testNoNamingConflictsForAnonymousServices()
{
$container = new ContainerBuilder();
$loader1 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension1'));
$loader1->load('services.xml');
$services = $container->getDefinitions();
$this->assertCount(3, $services, '->load() attributes unique ids to anonymous services');
$loader2 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension2'));
$loader2->load('services.xml');
$services = $container->getDefinitions();
$this->assertCount(5, $services, '->load() attributes unique ids to anonymous services');
$services = $container->getDefinitions();
$args1 = $services['extension1.foo']->getArguments();
$inner1 = $services[(string) $args1[0]];
$this->assertEquals('BarClass1', $inner1->getClass(), '->load() uses the same configuration as for the anonymous ones');
$args2 = $services['extension2.foo']->getArguments();
$inner2 = $services[(string) $args2[0]];
$this->assertEquals('BarClass2', $inner2->getClass(), '->load() uses the same configuration as for the anonymous ones');
}
public function testDocTypeIsNotAllowed()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
// document types are not allowed.
try {
$loader->load('withdoctype.xml');
$this->fail('->load() throws an InvalidArgumentException if the configuration contains a document type');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'withdoctype.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type');
$e = $e->getPrevious();
$this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type');
$this->assertSame('Document types are not allowed.', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type');
}
}
public function testXmlNamespaces()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('namespaces.xml');
$services = $container->getDefinitions();
$this->assertArrayHasKey('foo', $services, '->load() parses <srv:service> elements');
$this->assertCount(1, $services['foo']->getTag('foo.tag'), '->load parses <srv:tag> elements');
$this->assertEquals(array(array('setBar', array('foo'))), $services['foo']->getMethodCalls(), '->load() parses the <srv:call> tag');
}
public function testLoadIndexedArguments()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services14.xml');
$this->assertEquals(array('index_0' => 'app'), $container->findDefinition('logger')->getArguments());
}
public function testLoadInlinedServices()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services21.xml');
$foo = $container->getDefinition('foo');
$fooFactory = $foo->getFactory();
$this->assertInstanceOf(Reference::class, $fooFactory[0]);
$this->assertTrue($container->has((string) $fooFactory[0]));
$fooFactoryDefinition = $container->getDefinition((string) $fooFactory[0]);
$this->assertSame('FooFactory', $fooFactoryDefinition->getClass());
$this->assertSame('createFoo', $fooFactory[1]);
$fooFactoryFactory = $fooFactoryDefinition->getFactory();
$this->assertInstanceOf(Reference::class, $fooFactoryFactory[0]);
$this->assertTrue($container->has((string) $fooFactoryFactory[0]));
$this->assertSame('Foobar', $container->getDefinition((string) $fooFactoryFactory[0])->getClass());
$this->assertSame('createFooFactory', $fooFactoryFactory[1]);
$fooConfigurator = $foo->getConfigurator();
$this->assertInstanceOf(Reference::class, $fooConfigurator[0]);
$this->assertTrue($container->has((string) $fooConfigurator[0]));
$fooConfiguratorDefinition = $container->getDefinition((string) $fooConfigurator[0]);
$this->assertSame('Bar', $fooConfiguratorDefinition->getClass());
$this->assertSame('configureFoo', $fooConfigurator[1]);
$barConfigurator = $fooConfiguratorDefinition->getConfigurator();
$this->assertInstanceOf(Reference::class, $barConfigurator[0]);
$this->assertSame('Baz', $container->getDefinition((string) $barConfigurator[0])->getClass());
$this->assertSame('configureBar', $barConfigurator[1]);
}
/**
* @group legacy
*/
public function testType()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services22.xml');
$this->assertEquals(array('Bar', 'Baz'), $container->getDefinition('foo')->getAutowiringTypes());
}
public function testAutowire()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services23.xml');
$this->assertTrue($container->getDefinition('bar')->isAutowired());
}
public function testClassFromId()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('class_from_id.xml');
$container->compile();
$this->assertEquals(CaseSensitiveClass::class, $container->getDefinition(CaseSensitiveClass::class)->getClass());
}
public function testPrototype()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_prototype.xml');
$ids = array_keys($container->getDefinitions());
sort($ids);
$this->assertSame(array(Prototype\Foo::class, Prototype\Sub\Bar::class, 'service_container'), $ids);
$resources = $container->getResources();
$fixturesDir = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Fixtures'.\DIRECTORY_SEPARATOR;
$resources = array_map('strval', $resources);
$this->assertContains((string) (new FileResource($fixturesDir.'xml'.\DIRECTORY_SEPARATOR.'services_prototype.xml')), $resources);
$this->assertContains((string) (new GlobResource($fixturesDir.'Prototype', '/*', true)), $resources);
$this->assertContains('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo', $resources);
$this->assertContains('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar', $resources);
}
/**
* @group legacy
* @expectedDeprecation Using the attribute "class" is deprecated for the service "bar" which is defined as an alias %s.
* @expectedDeprecation Using the element "tag" is deprecated for the service "bar" which is defined as an alias %s.
* @expectedDeprecation Using the element "factory" is deprecated for the service "bar" which is defined as an alias %s.
*/
public function testAliasDefinitionContainsUnsupportedElements()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('legacy_invalid_alias_definition.xml');
$this->assertTrue($container->has('bar'));
}
public function testArgumentWithKeyOutsideCollection()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('with_key_outside_collection.xml');
$this->assertSame(array('type' => 'foo', 'bar'), $container->getDefinition('foo')->getArguments());
}
public function testDefaults()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services28.xml');
$this->assertFalse($container->getDefinition('with_defaults')->isPublic());
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
$this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
$this->assertArrayNotHasKey('public', $container->getDefinition('with_defaults')->getChanges());
$this->assertArrayNotHasKey('autowire', $container->getDefinition('with_defaults')->getChanges());
$container->compile();
$this->assertTrue($container->getDefinition('no_defaults')->isPublic());
$this->assertSame(array('foo' => array(array())), $container->getDefinition('no_defaults')->getTags());
$this->assertFalse($container->getDefinition('no_defaults')->isAutowired());
$this->assertTrue($container->getDefinition('child_def')->isPublic());
$this->assertSame(array('foo' => array(array())), $container->getDefinition('child_def')->getTags());
$this->assertFalse($container->getDefinition('child_def')->isAutowired());
$definitions = $container->getDefinitions();
$this->assertSame('service_container', key($definitions));
array_shift($definitions);
$anonymous = current($definitions);
$this->assertSame('bar', key($definitions));
$this->assertTrue($anonymous->isPublic());
$this->assertTrue($anonymous->isAutowired());
$this->assertSame(array('foo' => array(array())), $anonymous->getTags());
}
public function testNamedArguments()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_named_args.xml');
$this->assertEquals(array('$apiKey' => 'ABCD', CaseSensitiveClass::class => null), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
$container->compile();
$this->assertEquals(array(null, 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
$this->assertEquals(array(array('setApiKey', array('123'))), $container->getDefinition(NamedArgumentsDummy::class)->getMethodCalls());
}
public function testInstanceof()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_instanceof.xml');
$container->compile();
$definition = $container->getDefinition(Bar::class);
$this->assertTrue($definition->isAutowired());
$this->assertTrue($definition->isLazy());
$this->assertSame(array('foo' => array(array()), 'bar' => array(array())), $definition->getTags());
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage The service "child_service" cannot use the "parent" option in the same file where "instanceof" configuration is defined as using both is not supported. Move your child definitions to a separate file.
*/
public function testInstanceOfAndChildDefinitionNotAllowed()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_instanceof_with_parent.xml');
$container->compile();
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage The service "child_service" cannot have a "parent" and also have "autoconfigure". Try setting autoconfigure="false" for the service.
*/
public function testAutoConfigureAndChildDefinitionNotAllowed()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_autoconfigure_with_parent.xml');
$container->compile();
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage Attribute "autowire" on service "child_service" cannot be inherited from "defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.
*/
public function testDefaultsAndChildDefinitionNotAllowed()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_defaults_with_parent.xml');
$container->compile();
}
public function testAutoConfigureInstanceof()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_autoconfigure.xml');
$this->assertTrue($container->getDefinition('use_defaults_settings')->isAutoconfigured());
$this->assertFalse($container->getDefinition('override_defaults_settings_to_false')->isAutoconfigured());
}
public function testBindings()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_bindings.xml');
$container->compile();
$definition = $container->getDefinition('bar');
$this->assertEquals(array(
'NonExistent' => null,
BarInterface::class => new Reference(Bar::class),
'$foo' => array(null),
'$quz' => 'quz',
'$factory' => 'factory',
), array_map(function ($v) { return $v->getValues()[0]; }, $definition->getBindings()));
$this->assertEquals(array(
'quz',
null,
new Reference(Bar::class),
array(null),
), $definition->getArguments());
$definition = $container->getDefinition(Bar::class);
$this->assertEquals(array(
null,
'factory',
), $definition->getArguments());
$this->assertEquals(array(
'NonExistent' => null,
'$quz' => 'quz',
'$factory' => 'factory',
), array_map(function ($v) { return $v->getValues()[0]; }, $definition->getBindings()));
}
public function testTsantosContainer()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_tsantos.xml');
$container->compile();
$dumper = new PhpDumper($container);
$dump = $dumper->dump();
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_tsantos.php', $dumper->dump());
}
}

View file

@ -0,0 +1,735 @@
<?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\Loader;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Resource\GlobResource;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Bar;
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface;
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
use Symfony\Component\ExpressionLanguage\Expression;
class YamlFileLoaderTest extends TestCase
{
protected static $fixturesPath;
public static function setUpBeforeClass()
{
self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
require_once self::$fixturesPath.'/includes/foo.php';
require_once self::$fixturesPath.'/includes/ProjectExtension.php';
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegExp /The file ".+" does not exist./
*/
public function testLoadUnExistFile()
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));
$r = new \ReflectionObject($loader);
$m = $r->getMethod('loadFile');
$m->setAccessible(true);
$m->invoke($loader, 'foo.yml');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegExp /The file ".+" does not contain valid YAML./
*/
public function testLoadInvalidYamlFile()
{
$path = self::$fixturesPath.'/ini';
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator($path));
$r = new \ReflectionObject($loader);
$m = $r->getMethod('loadFile');
$m->setAccessible(true);
$m->invoke($loader, $path.'/parameters.ini');
}
/**
* @dataProvider provideInvalidFiles
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
*/
public function testLoadInvalidFile($file)
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load($file.'.yml');
}
public function provideInvalidFiles()
{
return array(
array('bad_parameters'),
array('bad_imports'),
array('bad_import'),
array('bad_services'),
array('bad_service'),
array('bad_calls'),
array('bad_format'),
array('nonvalid1'),
array('nonvalid2'),
);
}
public function testLoadParameters()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services2.yml');
$this->assertEquals(array('foo' => 'bar', 'mixedcase' => array('MixedCaseKey' => 'value'), 'values' => array(true, false, 0, 1000.3, PHP_INT_MAX), 'bar' => 'foo', 'escape' => '@escapeme', 'foo_bar' => new Reference('foo_bar')), $container->getParameterBag()->all(), '->load() converts YAML keys to lowercase');
}
public function testLoadImports()
{
$container = new ContainerBuilder();
$resolver = new LoaderResolver(array(
new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/ini')),
new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
new PhpFileLoader($container, new FileLocator(self::$fixturesPath.'/php')),
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')),
));
$loader->setResolver($resolver);
$loader->load('services4.yml');
$actual = $container->getParameterBag()->all();
$expected = array(
'foo' => 'bar',
'values' => array(true, false, PHP_INT_MAX),
'bar' => '%foo%',
'escape' => '@escapeme',
'foo_bar' => new Reference('foo_bar'),
'mixedcase' => array('MixedCaseKey' => 'value'),
'imported_from_ini' => true,
'imported_from_xml' => true,
'with_wrong_ext' => 'from yaml',
);
$this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files');
$this->assertTrue($actual['imported_from_ini']);
// Bad import throws no exception due to ignore_errors value.
$loader->load('services4_bad_import.yml');
}
public function testLoadServices()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services6.yml');
$services = $container->getDefinitions();
$this->assertArrayHasKey('foo', $services, '->load() parses service elements');
$this->assertFalse($services['not_shared']->isShared(), '->load() parses the shared flag');
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Definition', $services['foo'], '->load() converts service element to Definition instances');
$this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute');
$this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag');
$this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags');
$this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag');
$this->assertEquals(array(new Reference('baz'), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag');
$this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag');
$this->assertEquals(array(array('setBar', array()), array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ (container.hasParameter("foo") ? parameter("foo") : "default")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag');
$this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag');
$this->assertEquals('factory', $services['new_factory1']->getFactory(), '->load() parses the factory tag');
$this->assertEquals(array(new Reference('baz'), 'getClass'), $services['new_factory2']->getFactory(), '->load() parses the factory tag');
$this->assertEquals(array('BazClass', 'getInstance'), $services['new_factory3']->getFactory(), '->load() parses the factory tag');
$this->assertSame(array(null, 'getInstance'), $services['new_factory4']->getFactory(), '->load() accepts factory tag without class');
$this->assertEquals(array('foo', new Reference('baz')), $services['Acme\WithShortCutArgs']->getArguments(), '->load() parses short service definition');
$aliases = $container->getAliases();
$this->assertArrayHasKey('alias_for_foo', $aliases, '->load() parses aliases');
$this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases');
$this->assertTrue($aliases['alias_for_foo']->isPublic());
$this->assertArrayHasKey('another_alias_for_foo', $aliases);
$this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
$this->assertFalse($aliases['another_alias_for_foo']->isPublic());
$this->assertTrue(isset($aliases['another_third_alias_for_foo']));
$this->assertEquals('foo', (string) $aliases['another_third_alias_for_foo']);
$this->assertTrue($aliases['another_third_alias_for_foo']->isPublic());
$this->assertEquals(array('decorated', null, 0), $services['decorator_service']->getDecoratedService());
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 0), $services['decorator_service_with_name']->getDecoratedService());
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 5), $services['decorator_service_with_name_and_priority']->getDecoratedService());
}
public function testLoadFactoryShortSyntax()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services14.yml');
$services = $container->getDefinitions();
$this->assertEquals(array(new Reference('baz'), 'getClass'), $services['factory']->getFactory(), '->load() parses the factory tag with service:method');
$this->assertEquals(array('FooBacFactory', 'createFooBar'), $services['factory_with_static_call']->getFactory(), '->load() parses the factory tag with Class::method');
}
public function testLoadConfiguratorShortSyntax()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_configurator_short_syntax.yml');
$services = $container->getDefinitions();
$this->assertEquals(array(new Reference('foo_bar_configurator'), 'configure'), $services['foo_bar']->getConfigurator(), '->load() parses the configurator tag with service:method');
$this->assertEquals(array('FooBarConfigurator', 'configureFooBar'), $services['foo_bar_with_static_call']->getConfigurator(), '->load() parses the configurator tag with Class::method');
}
public function testExtensions()
{
$container = new ContainerBuilder();
$container->registerExtension(new \ProjectExtension());
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services10.yml');
$container->compile();
$services = $container->getDefinitions();
$parameters = $container->getParameterBag()->all();
$this->assertArrayHasKey('project.service.bar', $services, '->load() parses extension elements');
$this->assertArrayHasKey('project.parameter.bar', $parameters, '->load() parses extension elements');
$this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
$this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');
try {
$loader->load('services11.yml');
$this->fail('->load() throws an InvalidArgumentException if the tag is not valid');
} catch (\Exception $e) {
$this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid');
$this->assertStringStartsWith('There is no extension able to load the configuration for "foobarfoobar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid');
}
}
public function testExtensionWithNullConfig()
{
$container = new ContainerBuilder();
$container->registerExtension(new \ProjectExtension());
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('null_config.yml');
$container->compile();
$this->assertSame(array(null), $container->getParameter('project.configs'));
}
public function testSupports()
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator());
$this->assertTrue($loader->supports('foo.yml'), '->supports() returns true if the resource is loadable');
$this->assertTrue($loader->supports('foo.yaml'), '->supports() returns true if the resource is loadable');
$this->assertFalse($loader->supports('foo.foo'), '->supports() returns false if the resource is not loadable');
$this->assertTrue($loader->supports('with_wrong_ext.xml', 'yml'), '->supports() returns true if the resource with forced type is loadable');
$this->assertTrue($loader->supports('with_wrong_ext.xml', 'yaml'), '->supports() returns true if the resource with forced type is loadable');
}
public function testNonArrayTagsThrowsException()
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
try {
$loader->load('badtag1.yml');
$this->fail('->load() should throw an exception when the tags key of a service is not an array');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tags key is not an array');
$this->assertStringStartsWith('Parameter "tags" must be an array for service', $e->getMessage(), '->load() throws an InvalidArgumentException if the tags key is not an array');
}
}
public function testTagWithoutNameThrowsException()
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
try {
$loader->load('badtag2.yml');
$this->fail('->load() should throw an exception when a tag is missing the name key');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag is missing the name key');
$this->assertStringStartsWith('A "tags" entry is missing a "name" key for service ', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag is missing the name key');
}
}
public function testNameOnlyTagsAreAllowedAsString()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('tag_name_only.yml');
$this->assertCount(1, $container->getDefinition('foo_service')->getTag('foo'));
}
public function testTagWithAttributeArrayThrowsException()
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
try {
$loader->load('badtag3.yml');
$this->fail('->load() should throw an exception when a tag-attribute is not a scalar');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar');
$this->assertStringStartsWith('A "tags" attribute must be of a scalar-type for service "foo_service", tag "foo", attribute "bar"', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar');
}
}
public function testLoadYamlOnlyWithKeys()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services21.yml');
$definition = $container->getDefinition('manager');
$this->assertEquals(array(array('setLogger', array(new Reference('logger'))), array('setClass', array('User'))), $definition->getMethodCalls());
$this->assertEquals(array(true), $definition->getArguments());
$this->assertEquals(array('manager' => array(array('alias' => 'user'))), $definition->getTags());
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegExp /The tag name for service ".+" in .+ must be a non-empty string/
*/
public function testTagWithEmptyNameThrowsException()
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('tag_name_empty_string.yml');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageREgExp /The tag name for service "\.+" must be a non-empty string/
*/
public function testTagWithNonStringNameThrowsException()
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('tag_name_no_string.yml');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
*/
public function testTypesNotArray()
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('bad_types1.yml');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
*/
public function testTypeNotString()
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('bad_types2.yml');
}
/**
* @group legacy
*/
public function testTypes()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services22.yml');
$this->assertEquals(array('Foo', 'Bar'), $container->getDefinition('foo_service')->getAutowiringTypes());
$this->assertEquals(array('Foo'), $container->getDefinition('baz_service')->getAutowiringTypes());
}
public function testParsesIteratorArgument()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services9.yml');
$lazyDefinition = $container->getDefinition('lazy_context');
$this->assertEquals(array(new IteratorArgument(array('k1' => new Reference('foo.baz'), 'k2' => new Reference('service_container'))), new IteratorArgument(array())), $lazyDefinition->getArguments(), '->load() parses lazy arguments');
}
public function testAutowire()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services23.yml');
$this->assertTrue($container->getDefinition('bar_service')->isAutowired());
}
public function testClassFromId()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('class_from_id.yml');
$container->compile();
$this->assertEquals(CaseSensitiveClass::class, $container->getDefinition(CaseSensitiveClass::class)->getClass());
}
public function testPrototype()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_prototype.yml');
$ids = array_keys($container->getDefinitions());
sort($ids);
$this->assertSame(array(Prototype\Foo::class, Prototype\Sub\Bar::class, 'service_container'), $ids);
$resources = $container->getResources();
$fixturesDir = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Fixtures'.\DIRECTORY_SEPARATOR;
$resources = array_map('strval', $resources);
$this->assertContains((string) (new FileResource($fixturesDir.'yaml'.\DIRECTORY_SEPARATOR.'services_prototype.yml')), $resources);
$this->assertContains((string) (new GlobResource($fixturesDir.'Prototype', '', true)), $resources);
$this->assertContains('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo', $resources);
$this->assertContains('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar', $resources);
}
public function testPrototypeWithNamespace()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_prototype_namespace.yml');
$ids = array_keys($container->getDefinitions());
sort($ids);
$this->assertSame(array(
Prototype\OtherDir\Component1\Dir1\Service1::class,
Prototype\OtherDir\Component1\Dir2\Service2::class,
Prototype\OtherDir\Component2\Dir1\Service4::class,
Prototype\OtherDir\Component2\Dir2\Service5::class,
'service_container',
), $ids);
$this->assertTrue($container->getDefinition(Prototype\OtherDir\Component1\Dir1\Service1::class)->hasTag('foo'));
$this->assertTrue($container->getDefinition(Prototype\OtherDir\Component2\Dir1\Service4::class)->hasTag('foo'));
$this->assertFalse($container->getDefinition(Prototype\OtherDir\Component1\Dir1\Service1::class)->hasTag('bar'));
$this->assertFalse($container->getDefinition(Prototype\OtherDir\Component2\Dir1\Service4::class)->hasTag('bar'));
$this->assertTrue($container->getDefinition(Prototype\OtherDir\Component1\Dir2\Service2::class)->hasTag('bar'));
$this->assertTrue($container->getDefinition(Prototype\OtherDir\Component2\Dir2\Service5::class)->hasTag('bar'));
$this->assertFalse($container->getDefinition(Prototype\OtherDir\Component1\Dir2\Service2::class)->hasTag('foo'));
$this->assertFalse($container->getDefinition(Prototype\OtherDir\Component2\Dir2\Service5::class)->hasTag('foo'));
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegExp /A "resource" attribute must be set when the "namespace" attribute is set for service ".+" in .+/
*/
public function testPrototypeWithNamespaceAndNoResource()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_prototype_namespace_without_resource.yml');
}
public function testDefaults()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services28.yml');
$this->assertFalse($container->getDefinition('with_defaults')->isPublic());
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
$this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
$this->assertArrayNotHasKey('public', $container->getDefinition('with_defaults')->getChanges());
$this->assertArrayNotHasKey('autowire', $container->getDefinition('with_defaults')->getChanges());
$this->assertFalse($container->getAlias('with_defaults_aliased')->isPublic());
$this->assertFalse($container->getAlias('with_defaults_aliased_short')->isPublic());
$this->assertFalse($container->getDefinition('Acme\WithShortCutArgs')->isPublic());
$this->assertSame(array('foo' => array(array())), $container->getDefinition('Acme\WithShortCutArgs')->getTags());
$this->assertTrue($container->getDefinition('Acme\WithShortCutArgs')->isAutowired());
$container->compile();
$this->assertTrue($container->getDefinition('with_null')->isPublic());
$this->assertTrue($container->getDefinition('no_defaults')->isPublic());
// foo tag is inherited from defaults
$this->assertSame(array('foo' => array(array())), $container->getDefinition('with_null')->getTags());
$this->assertSame(array('foo' => array(array())), $container->getDefinition('no_defaults')->getTags());
$this->assertTrue($container->getDefinition('with_null')->isAutowired());
$this->assertFalse($container->getDefinition('no_defaults')->isAutowired());
$this->assertTrue($container->getDefinition('child_def')->isPublic());
$this->assertSame(array('foo' => array(array())), $container->getDefinition('child_def')->getTags());
$this->assertFalse($container->getDefinition('child_def')->isAutowired());
}
public function testNamedArguments()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_named_args.yml');
$this->assertEquals(array(null, '$apiKey' => 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
$this->assertEquals(array('$apiKey' => 'ABCD', CaseSensitiveClass::class => null), $container->getDefinition('another_one')->getArguments());
$container->compile();
$this->assertEquals(array(null, 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
$this->assertEquals(array(null, 'ABCD'), $container->getDefinition('another_one')->getArguments());
$this->assertEquals(array(array('setApiKey', array('123'))), $container->getDefinition('another_one')->getMethodCalls());
}
public function testInstanceof()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_instanceof.yml');
$container->compile();
$definition = $container->getDefinition(Bar::class);
$this->assertTrue($definition->isAutowired());
$this->assertTrue($definition->isLazy());
$this->assertSame(array('foo' => array(array()), 'bar' => array(array())), $definition->getTags());
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage The service "child_service" cannot use the "parent" option in the same file where "_instanceof" configuration is defined as using both is not supported. Move your child definitions to a separate file.
*/
public function testInstanceOfAndChildDefinitionNotAllowed()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_instanceof_with_parent.yml');
$container->compile();
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage The service "child_service" cannot have a "parent" and also have "autoconfigure". Try setting "autoconfigure: false" for the service.
*/
public function testAutoConfigureAndChildDefinitionNotAllowed()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_autoconfigure_with_parent.yml');
$container->compile();
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage Attribute "autowire" on service "child_service" cannot be inherited from "_defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.
*/
public function testDefaultsAndChildDefinitionNotAllowed()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_defaults_with_parent.yml');
$container->compile();
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage The value of the "decorates" option for the "bar" service must be the id of the service without the "@" prefix (replace "@foo" with "foo").
*/
public function testDecoratedServicesWithWrongSyntaxThrowsException()
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('bad_decorates.yml');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegExp /Parameter "tags" must be an array for service "Foo\\Bar" in .+services31_invalid_tags\.yml\. Check your YAML syntax./
*/
public function testInvalidTagsWithDefaults()
{
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services31_invalid_tags.yml');
}
/**
* @group legacy
* @expectedDeprecation Service names that start with an underscore are deprecated since Symfony 3.3 and will be reserved in 4.0. Rename the "_foo" service or define it in XML instead.
*/
public function testUnderscoreServiceId()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_underscore.yml');
}
public function testAnonymousServices()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('anonymous_services.yml');
$definition = $container->getDefinition('Foo');
$this->assertTrue($definition->isAutowired());
// Anonymous service in an argument
$args = $definition->getArguments();
$this->assertCount(1, $args);
$this->assertInstanceOf(Reference::class, $args[0]);
$this->assertTrue($container->has((string) $args[0]));
$this->assertRegExp('/^\d+_Bar~[._A-Za-z0-9]{7}$/', (string) $args[0]);
$anonymous = $container->getDefinition((string) $args[0]);
$this->assertEquals('Bar', $anonymous->getClass());
$this->assertFalse($anonymous->isPublic());
$this->assertTrue($anonymous->isAutowired());
// Anonymous service in a callable
$factory = $definition->getFactory();
$this->assertInternalType('array', $factory);
$this->assertInstanceOf(Reference::class, $factory[0]);
$this->assertTrue($container->has((string) $factory[0]));
$this->assertRegExp('/^\d+_Quz~[._A-Za-z0-9]{7}$/', (string) $factory[0]);
$this->assertEquals('constructFoo', $factory[1]);
$anonymous = $container->getDefinition((string) $factory[0]);
$this->assertEquals('Quz', $anonymous->getClass());
$this->assertFalse($anonymous->isPublic());
$this->assertFalse($anonymous->isAutowired());
}
public function testAnonymousServicesInDifferentFilesWithSameNameDoNotConflict()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml/foo'));
$loader->load('services.yml');
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml/bar'));
$loader->load('services.yml');
$this->assertCount(5, $container->getDefinitions());
}
public function testAnonymousServicesInInstanceof()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('anonymous_services_in_instanceof.yml');
$definition = $container->getDefinition('Dummy');
$instanceof = $definition->getInstanceofConditionals();
$this->assertCount(3, $instanceof);
$this->assertArrayHasKey('DummyInterface', $instanceof);
$args = $instanceof['DummyInterface']->getProperties();
$this->assertCount(1, $args);
$this->assertInstanceOf(Reference::class, $args['foo']);
$this->assertTrue($container->has((string) $args['foo']));
$anonymous = $container->getDefinition((string) $args['foo']);
$this->assertEquals('Anonymous', $anonymous->getClass());
$this->assertFalse($anonymous->isPublic());
$this->assertEmpty($anonymous->getInstanceofConditionals());
$this->assertFalse($container->has('Bar'));
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegExp /Creating an alias using the tag "!service" is not allowed in ".+anonymous_services_alias\.yml"\./
*/
public function testAnonymousServicesWithAliases()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('anonymous_services_alias.yml');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegExp /Using an anonymous service in a parameter is not allowed in ".+anonymous_services_in_parameters\.yml"\./
*/
public function testAnonymousServicesInParameters()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('anonymous_services_in_parameters.yml');
}
public function testAutoConfigureInstanceof()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_autoconfigure.yml');
$this->assertTrue($container->getDefinition('use_defaults_settings')->isAutoconfigured());
$this->assertFalse($container->getDefinition('override_defaults_settings_to_false')->isAutoconfigured());
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegExp /Service "_defaults" key must be an array, "NULL" given in ".+bad_empty_defaults\.yml"\./
*/
public function testEmptyDefaultsThrowsClearException()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('bad_empty_defaults.yml');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegExp /Service "_instanceof" key must be an array, "NULL" given in ".+bad_empty_instanceof\.yml"\./
*/
public function testEmptyInstanceofThrowsClearException()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('bad_empty_instanceof.yml');
}
public function testBindings()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_bindings.yml');
$container->compile();
$definition = $container->getDefinition('bar');
$this->assertEquals(array(
'NonExistent' => null,
BarInterface::class => new Reference(Bar::class),
'$foo' => array(null),
'$quz' => 'quz',
'$factory' => 'factory',
), array_map(function ($v) { return $v->getValues()[0]; }, $definition->getBindings()));
$this->assertEquals(array(
'quz',
null,
new Reference(Bar::class),
array(null),
), $definition->getArguments());
$definition = $container->getDefinition(Bar::class);
$this->assertEquals(array(
null,
'factory',
), $definition->getArguments());
$this->assertEquals(array(
'NonExistent' => null,
'$quz' => 'quz',
'$factory' => 'factory',
), array_map(function ($v) { return $v->getValues()[0]; }, $definition->getBindings()));
}
}