[DI] Added safeguards against invalid config in the YamlFileLoader
Exceptions explaining the mistake are better than fatal errors or weird notices appearing when trying to deal with such invalid data. Closes #11333
This commit is contained in:
parent
b554961a5b
commit
5183501e0b
|
@ -55,6 +55,10 @@ class YamlFileLoader extends FileLoader
|
|||
|
||||
// parameters
|
||||
if (isset($content['parameters'])) {
|
||||
if (!is_array($content['parameters'])) {
|
||||
throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $file));
|
||||
}
|
||||
|
||||
foreach ($content['parameters'] as $key => $value) {
|
||||
$this->container->setParameter($key, $this->resolveServices($value));
|
||||
}
|
||||
|
@ -92,7 +96,15 @@ class YamlFileLoader extends FileLoader
|
|||
return;
|
||||
}
|
||||
|
||||
if (!is_array($content['imports'])) {
|
||||
throw new InvalidArgumentException(sprintf('The "imports" key should contain an array in %s. Check your YAML syntax.', $file));
|
||||
}
|
||||
|
||||
foreach ($content['imports'] as $import) {
|
||||
if (!is_array($import)) {
|
||||
throw new InvalidArgumentException(sprintf('The values in the "imports" key should be arrays in %s. Check your YAML syntax.', $file));
|
||||
}
|
||||
|
||||
$this->setCurrentDir(dirname($file));
|
||||
$this->import($import['resource'], null, isset($import['ignore_errors']) ? (bool) $import['ignore_errors'] : false, $file);
|
||||
}
|
||||
|
@ -110,6 +122,10 @@ class YamlFileLoader extends FileLoader
|
|||
return;
|
||||
}
|
||||
|
||||
if (!is_array($content['services'])) {
|
||||
throw new InvalidArgumentException(sprintf('The "services" key should contain an array in %s. Check your YAML syntax.', $file));
|
||||
}
|
||||
|
||||
foreach ($content['services'] as $id => $service) {
|
||||
$this->parseDefinition($id, $service, $file);
|
||||
}
|
||||
|
@ -130,7 +146,13 @@ class YamlFileLoader extends FileLoader
|
|||
$this->container->setAlias($id, substr($service, 1));
|
||||
|
||||
return;
|
||||
} elseif (isset($service['alias'])) {
|
||||
}
|
||||
|
||||
if (!is_array($service)) {
|
||||
throw new InvalidArgumentException(sprintf('A service definition must be an array or a string starting with "@" but %s found for service "%s" in %s. Check your YAML syntax.', gettype($service), $id, $file));
|
||||
}
|
||||
|
||||
if (isset($service['alias'])) {
|
||||
$public = !array_key_exists('public', $service) || (bool) $service['public'];
|
||||
$this->container->setAlias($id, new Alias($service['alias'], $public));
|
||||
|
||||
|
@ -204,6 +226,10 @@ class YamlFileLoader extends FileLoader
|
|||
}
|
||||
|
||||
if (isset($service['calls'])) {
|
||||
if (!is_array($service['calls'])) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter "calls" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
|
||||
}
|
||||
|
||||
foreach ($service['calls'] as $call) {
|
||||
$args = isset($call[1]) ? $this->resolveServices($call[1]) : array();
|
||||
$definition->addMethodCall($call[0], $args);
|
||||
|
@ -212,10 +238,14 @@ class YamlFileLoader extends FileLoader
|
|||
|
||||
if (isset($service['tags'])) {
|
||||
if (!is_array($service['tags'])) {
|
||||
throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s.', $id, $file));
|
||||
throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
|
||||
}
|
||||
|
||||
foreach ($service['tags'] as $tag) {
|
||||
if (!is_array($tag)) {
|
||||
throw new InvalidArgumentException(sprintf('A "tags" entry must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
|
||||
}
|
||||
|
||||
if (!isset($tag['name'])) {
|
||||
throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in %s.', $id, $file));
|
||||
}
|
||||
|
@ -223,9 +253,9 @@ class YamlFileLoader extends FileLoader
|
|||
$name = $tag['name'];
|
||||
unset($tag['name']);
|
||||
|
||||
foreach ($tag as $attribute => $value) {
|
||||
foreach ($tag as $value) {
|
||||
if (!is_scalar($value)) {
|
||||
throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s" in %s.', $id, $name, $file));
|
||||
throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s" in %s. Check your YAML syntax.', $id, $name, $file));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,7 +309,7 @@ class YamlFileLoader extends FileLoader
|
|||
}
|
||||
|
||||
if (!is_array($content)) {
|
||||
throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file));
|
||||
throw new InvalidArgumentException(sprintf('The service file "%s" is not valid. It should contain an array. Check your YAML syntax.', $file));
|
||||
}
|
||||
|
||||
foreach (array_keys($content) as $namespace) {
|
||||
|
@ -305,9 +335,9 @@ class YamlFileLoader extends FileLoader
|
|||
/**
|
||||
* Resolves services.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string|array $value
|
||||
*
|
||||
* @return Reference
|
||||
* @return array|string|Reference
|
||||
*/
|
||||
private function resolveServices($value)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
services:
|
||||
method_call1:
|
||||
class: FooClass
|
||||
calls: foo
|
|
@ -0,0 +1,2 @@
|
|||
imports:
|
||||
- foo.yml
|
|
@ -0,0 +1,2 @@
|
|||
imports:
|
||||
foo:bar
|
|
@ -0,0 +1,2 @@
|
|||
parameters:
|
||||
foo:bar
|
|
@ -0,0 +1,2 @@
|
|||
services:
|
||||
foo: bar
|
|
@ -0,0 +1 @@
|
|||
services: foo
|
|
@ -0,0 +1,6 @@
|
|||
services:
|
||||
foo_service:
|
||||
class: FooClass
|
||||
tags:
|
||||
# tag is not an array
|
||||
- foo
|
|
@ -13,7 +13,6 @@ namespace Symfony\Component\DependencyInjection\Tests\Loader;
|
|||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\Config\Loader\Loader;
|
||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
||||
|
@ -80,6 +79,29 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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'),
|
||||
);
|
||||
}
|
||||
|
||||
public function testLoadParameters()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
@ -179,7 +201,7 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||
$this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
|
||||
}
|
||||
|
||||
public function testNonArrayTagThrowsException()
|
||||
public function testNonArrayTagsThrowsException()
|
||||
{
|
||||
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
|
||||
try {
|
||||
|
@ -191,6 +213,16 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
||||
* @expectedExceptionMessage A "tags" entry must be an array for service
|
||||
*/
|
||||
public function testNonArrayTagThrowsException()
|
||||
{
|
||||
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
|
||||
$loader->load('badtag4.yml');
|
||||
}
|
||||
|
||||
public function testTagWithoutNameThrowsException()
|
||||
{
|
||||
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
|
||||
|
|
Reference in New Issue