diff --git a/src/Symfony/Component/Config/Loader/FileLoader.php b/src/Symfony/Component/Config/Loader/FileLoader.php
index 0ab6b648ab..828ac67212 100644
--- a/src/Symfony/Component/Config/Loader/FileLoader.php
+++ b/src/Symfony/Component/Config/Loader/FileLoader.php
@@ -73,7 +73,7 @@ abstract class FileLoader extends Loader
*/
public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null/*, $exclude = null*/)
{
- if (\func_num_args() < 5 && __CLASS__ !== \get_class($this) && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) {
+ if (\func_num_args() < 5 && __CLASS__ !== \get_class($this) && 0 !== strpos(\get_class($this), 'Symfony\Component\\') && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) {
@trigger_error(sprintf('The "%s()" method will have a new "$exclude = null" argument in version 5.0, not defining it is deprecated since Symfony 4.4.', __METHOD__), E_USER_DEPRECATED);
}
$exclude = \func_num_args() >= 5 ? func_get_arg(4) : null;
diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php
index 2fd74c0e33..b9cb8b6049 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php
@@ -60,7 +60,7 @@ class ContainerConfigurator extends AbstractConfigurator
$this->container->loadFromExtension($namespace, static::processValue($config));
}
- final public function import(string $resource, string $type = null, bool $ignoreErrors = false)
+ final public function import(string $resource, string $type = null, $ignoreErrors = false)
{
$this->loader->setCurrentDir(\dirname($this->path));
$this->loader->import($resource, $type, $ignoreErrors, $this->file);
diff --git a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
index 12c7e70948..3d0a076674 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
@@ -11,8 +11,11 @@
namespace Symfony\Component\DependencyInjection\Loader;
+use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
+use Symfony\Component\Config\Exception\LoaderLoadException;
use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader;
+use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Config\Resource\GlobResource;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -41,6 +44,42 @@ abstract class FileLoader extends BaseFileLoader
parent::__construct($locator);
}
+ /**
+ * {@inheritdoc}
+ *
+ * @param bool|string $ignoreErrors Whether errors should be ignored; pass "not_found" to ignore only when the loaded resource is not found
+ * @param string|string[]|null $exclude Glob patterns to exclude from the import
+ */
+ public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null/*, $exclude = null*/)
+ {
+ $args = \func_get_args();
+
+ if ($ignoreNotFound = 'not_found' === $ignoreErrors) {
+ $args[2] = false;
+ } elseif (!\is_bool($ignoreErrors)) {
+ @trigger_error(sprintf('Invalid argument $ignoreErrors provided to %s::import(): boolean or "not_found" expected, %s given.', \get_class($this), \gettype($ignoreErrors)), E_USER_DEPRECATED);
+ $args[2] = (bool) $ignoreErrors;
+ }
+
+ try {
+ parent::import(...$args);
+ } catch (LoaderLoadException $e) {
+ if (!$ignoreNotFound || !($prev = $e->getPrevious()) instanceof FileLocatorFileNotFoundException) {
+ throw $e;
+ }
+
+ foreach ($prev->getTrace() as $frame) {
+ if ('import' === ($frame['function'] ?? null) && is_a($frame['class'] ?? '', Loader::class, true)) {
+ break;
+ }
+ }
+
+ if ($args !== $frame['args']) {
+ throw $e;
+ }
+ }
+ }
+
/**
* Registers a set of classes as services using PSR-4 for discovery.
*
diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
index de770432b6..5733eb11ca 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
@@ -105,7 +105,7 @@ class XmlFileLoader extends FileLoader
$defaultDirectory = \dirname($file);
foreach ($imports as $import) {
$this->setCurrentDir($defaultDirectory);
- $this->import($import->getAttribute('resource'), XmlUtils::phpize($import->getAttribute('type')) ?: null, (bool) XmlUtils::phpize($import->getAttribute('ignore-errors')), $file);
+ $this->import($import->getAttribute('resource'), XmlUtils::phpize($import->getAttribute('type')) ?: null, XmlUtils::phpize($import->getAttribute('ignore-errors')) ?: false, $file);
}
}
diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
index 3290461c9f..18a44b9806 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
@@ -191,7 +191,7 @@ class YamlFileLoader extends FileLoader
}
$this->setCurrentDir($defaultDirectory);
- $this->import($import['resource'], isset($import['type']) ? $import['type'] : null, isset($import['ignore_errors']) ? (bool) $import['ignore_errors'] : false, $file);
+ $this->import($import['resource'], $import['type'] ?? null, $import['ignore_errors'] ?? false, $file);
}
}
diff --git a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd
index 4a71088a1c..4f85f41035 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd
+++ b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd
@@ -78,7 +78,7 @@
]]>
-
+
@@ -273,6 +273,12 @@
+
+
+
+
+
+
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import_file_not_found.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import_file_not_found.xml
new file mode 100644
index 0000000000..f3c6814b71
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import_file_not_found.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import_nonvalid.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import_nonvalid.xml
new file mode 100644
index 0000000000..9d026135cd
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import_nonvalid.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import_with_errors.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import_with_errors.xml
new file mode 100644
index 0000000000..8644f8bacb
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import_with_errors.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import_file_not_found.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import_file_not_found.yml
new file mode 100644
index 0000000000..d94e53c5a8
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import_file_not_found.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: foo_fake.yml, ignore_errors: not_found }
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import_nonvalid.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import_nonvalid.yml
new file mode 100644
index 0000000000..3ad1c2b630
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import_nonvalid.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: nonvalid2.yml, ignore_errors: not_found }
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import_with_errors.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import_with_errors.yml
new file mode 100644
index 0000000000..42bca4ca06
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import_with_errors.yml
@@ -0,0 +1,2 @@
+imports:
+ - { resource: foo_fake.yml }
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php
index b5a0296dad..2c5386572a 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php
@@ -183,6 +183,37 @@ class XmlFileLoaderTest extends TestCase
// Bad import throws no exception due to ignore_errors value.
$loader->load('services4_bad_import.xml');
+
+ // Bad import with nonexistent file throws no exception due to ignore_errors: not_found value.
+ $loader->load('services4_bad_import_file_not_found.xml');
+
+ try {
+ $loader->load('services4_bad_import_with_errors.xml');
+ $this->fail('->load() throws a LoaderLoadException if the imported xml file configuration does not exist');
+ } catch (\Exception $e) {
+ $this->assertInstanceOf('Symfony\\Component\\Config\\Exception\\LoaderLoadException', $e, '->load() throws a LoaderLoadException if the imported xml file configuration does not exist');
+ $this->assertRegExp(sprintf('#^The file "%1$s" does not exist \(in: .+\) in %1$s \(which is being imported from ".+%2$s"\)\.$#', 'foo_fake\.xml', 'services4_bad_import_with_errors\.xml'), $e->getMessage(), '->load() throws a LoaderLoadException if the imported xml file configuration does not exist');
+
+ $e = $e->getPrevious();
+ $this->assertInstanceOf('Symfony\\Component\\Config\\Exception\\FileLocatorFileNotFoundException', $e, '->load() throws a FileLocatorFileNotFoundException if the imported xml file configuration does not exist');
+ $this->assertRegExp(sprintf('#^The file "%s" does not exist \(in: .+\)\.$#', 'foo_fake\.xml'), $e->getMessage(), '->load() throws a FileLocatorFileNotFoundException if the imported xml file configuration does not exist');
+ }
+
+ try {
+ $loader->load('services4_bad_import_nonvalid.xml');
+ $this->fail('->load() throws an LoaderLoadException if the imported configuration does not validate the XSD');
+ } catch (\Exception $e) {
+ $this->assertInstanceOf('Symfony\\Component\\Config\\Exception\\LoaderLoadException', $e, '->load() throws a LoaderLoadException if the imported configuration does not validate the XSD');
+ $this->assertRegExp(sprintf('#^Unable to parse file ".+%s": .+.$#', 'nonvalid\.xml'), $e->getMessage(), '->load() throws a LoaderLoadException if the imported configuration does not validate the XSD');
+
+ $e = $e->getPrevious();
+ $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": .+.$#', 'nonvalid\.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
+
+ $e = $e->getPrevious();
+ $this->assertInstanceOf('Symfony\\Component\\Config\\Util\\Exception\\XmlParsingException', $e, '->load() throws a XmlParsingException if the configuration does not validate the XSD');
+ $this->assertStringStartsWith('[ERROR 1845] Element \'nonvalid\': No matching global declaration available for the validation root. (in', $e->getMessage(), '->load() throws a XmlParsingException if the loaded file does not validate the XSD');
+ }
}
public function testLoadAnonymousServices()
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
index 4e3a2bb38b..2010e36aba 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
@@ -135,6 +135,33 @@ class YamlFileLoaderTest extends TestCase
// Bad import throws no exception due to ignore_errors value.
$loader->load('services4_bad_import.yml');
+
+ // Bad import with nonexistent file throws no exception due to ignore_errors: not_found value.
+ $loader->load('services4_bad_import_file_not_found.yml');
+
+ try {
+ $loader->load('services4_bad_import_with_errors.yml');
+ $this->fail('->load() throws a LoaderLoadException if the imported yaml file does not exist');
+ } catch (\Exception $e) {
+ $this->assertInstanceOf('Symfony\\Component\\Config\\Exception\\LoaderLoadException', $e, '->load() throws a LoaderLoadException if the imported yaml file does not exist');
+ $this->assertRegExp(sprintf('#^The file "%1$s" does not exist \(in: .+\) in %1$s \(which is being imported from ".+%2$s"\)\.$#', 'foo_fake\.yml', 'services4_bad_import_with_errors\.yml'), $e->getMessage(), '->load() throws a LoaderLoadException if the imported yaml file does not exist');
+
+ $e = $e->getPrevious();
+ $this->assertInstanceOf('Symfony\\Component\\Config\\Exception\\FileLocatorFileNotFoundException', $e, '->load() throws a FileLocatorFileNotFoundException if the imported yaml file does not exist');
+ $this->assertRegExp(sprintf('#^The file "%s" does not exist \(in: .+\)\.$#', 'foo_fake\.yml'), $e->getMessage(), '->load() throws a FileLocatorFileNotFoundException if the imported yaml file does not exist');
+ }
+
+ try {
+ $loader->load('services4_bad_import_nonvalid.yml');
+ $this->fail('->load() throws a LoaderLoadException if the tag in the imported yaml file is not valid');
+ } catch (\Exception $e) {
+ $this->assertInstanceOf('Symfony\\Component\\Config\\Exception\\LoaderLoadException', $e, '->load() throws a LoaderLoadException if the tag in the imported yaml file is not valid');
+ $this->assertRegExp(sprintf('#^The service file ".+%1$s" is not valid\. It should contain an array\. Check your YAML syntax in .+%1$s \(which is being imported from ".+%2$s"\)\.$#', 'nonvalid2\.yml', 'services4_bad_import_nonvalid.yml'), $e->getMessage(), '->load() throws a LoaderLoadException if the tag in the imported yaml file is not valid');
+
+ $e = $e->getPrevious();
+ $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag in the imported yaml file is not valid');
+ $this->assertRegExp(sprintf('#^The service file ".+%s" is not valid\. It should contain an array\. Check your YAML syntax\.$#', 'nonvalid2\.yml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the tag in the imported yaml file is not valid');
+ }
}
public function testLoadServices()