[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
|
// parameters
|
||||||
if (isset($content['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) {
|
foreach ($content['parameters'] as $key => $value) {
|
||||||
$this->container->setParameter($key, $this->resolveServices($value));
|
$this->container->setParameter($key, $this->resolveServices($value));
|
||||||
}
|
}
|
||||||
@ -92,7 +96,15 @@ class YamlFileLoader extends FileLoader
|
|||||||
return;
|
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) {
|
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->setCurrentDir(dirname($file));
|
||||||
$this->import($import['resource'], null, isset($import['ignore_errors']) ? (bool) $import['ignore_errors'] : false, $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;
|
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) {
|
foreach ($content['services'] as $id => $service) {
|
||||||
$this->parseDefinition($id, $service, $file);
|
$this->parseDefinition($id, $service, $file);
|
||||||
}
|
}
|
||||||
@ -130,7 +146,13 @@ class YamlFileLoader extends FileLoader
|
|||||||
$this->container->setAlias($id, substr($service, 1));
|
$this->container->setAlias($id, substr($service, 1));
|
||||||
|
|
||||||
return;
|
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'];
|
$public = !array_key_exists('public', $service) || (bool) $service['public'];
|
||||||
$this->container->setAlias($id, new Alias($service['alias'], $public));
|
$this->container->setAlias($id, new Alias($service['alias'], $public));
|
||||||
|
|
||||||
@ -204,6 +226,10 @@ class YamlFileLoader extends FileLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isset($service['calls'])) {
|
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) {
|
foreach ($service['calls'] as $call) {
|
||||||
$args = isset($call[1]) ? $this->resolveServices($call[1]) : array();
|
$args = isset($call[1]) ? $this->resolveServices($call[1]) : array();
|
||||||
$definition->addMethodCall($call[0], $args);
|
$definition->addMethodCall($call[0], $args);
|
||||||
@ -212,10 +238,14 @@ class YamlFileLoader extends FileLoader
|
|||||||
|
|
||||||
if (isset($service['tags'])) {
|
if (isset($service['tags'])) {
|
||||||
if (!is_array($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) {
|
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'])) {
|
if (!isset($tag['name'])) {
|
||||||
throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in %s.', $id, $file));
|
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'];
|
$name = $tag['name'];
|
||||||
unset($tag['name']);
|
unset($tag['name']);
|
||||||
|
|
||||||
foreach ($tag as $attribute => $value) {
|
foreach ($tag as $value) {
|
||||||
if (!is_scalar($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)) {
|
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) {
|
foreach (array_keys($content) as $namespace) {
|
||||||
@ -305,9 +335,9 @@ class YamlFileLoader extends FileLoader
|
|||||||
/**
|
/**
|
||||||
* Resolves services.
|
* Resolves services.
|
||||||
*
|
*
|
||||||
* @param string $value
|
* @param string|array $value
|
||||||
*
|
*
|
||||||
* @return Reference
|
* @return array|string|Reference
|
||||||
*/
|
*/
|
||||||
private function resolveServices($value)
|
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\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
|
||||||
use Symfony\Component\Config\Loader\Loader;
|
use Symfony\Component\Config\Loader\Loader;
|
||||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||||
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
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()
|
public function testLoadParameters()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$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');
|
$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'));
|
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
|
||||||
try {
|
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()
|
public function testTagWithoutNameThrowsException()
|
||||||
{
|
{
|
||||||
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
|
$loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
|
||||||
|
Reference in New Issue
Block a user