From b20386e61e3f72c76c68a6aa0aa605d614c5af49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Escandell?= Date: Sat, 16 Mar 2013 02:07:49 +0100 Subject: [PATCH] [Config] Add possibility to get "parent bundle resource file" in import file loading process --- .../Component/Config/Loader/FileLoader.php | 14 ++- .../Config/Tests/Loader/FileLoaderTest.php | 85 +++++++++++++++++++ 2 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php diff --git a/src/Symfony/Component/Config/Loader/FileLoader.php b/src/Symfony/Component/Config/Loader/FileLoader.php index 972f54f566..d96d236442 100644 --- a/src/Symfony/Component/Config/Loader/FileLoader.php +++ b/src/Symfony/Component/Config/Loader/FileLoader.php @@ -67,11 +67,19 @@ abstract class FileLoader extends Loader $loader = $this->resolve($resource, $type); if ($loader instanceof FileLoader && null !== $this->currentDir) { - $resource = $this->locator->locate($resource, $this->currentDir); + $resource = $this->locator->locate($resource, $this->currentDir, false); } - if (isset(self::$loading[$resource])) { - throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading)); + $resources = is_array($resource) ? $resource : array($resource); + for ($i = 0; $i < $resourcesCount = count($resources); $i++ ) { + if (isset(self::$loading[$resources[$i]])) { + if ($i == $resourcesCount-1) { + throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading)); + } + } else { + $resource = $resources[$i]; + break; + } } self::$loading[$resource] = true; diff --git a/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php b/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php new file mode 100644 index 0000000000..7e064e8618 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php @@ -0,0 +1,85 @@ +getMock('Symfony\Component\Config\FileLocatorInterface'); + $locatorMock->expects($this->any())->method('locate')->will($this->onConsecutiveCalls( + array('path/to/file1'), // Default + array('path/to/file1', 'path/to/file2'), // First is imported + array('path/to/file1', 'path/to/file2'), // Second is imported + array('path/to/file1'), // Exception + array('path/to/file1', 'path/to/file2') // Exception + )); + + $fileLoader = new TestFileLoader($locatorMock); + $fileLoader->setCurrentDir('.'); + $fileLoader->setResolver($loaderResolver = new LoaderResolver(array($fileLoader))); + + // Default case + $this->assertSame('path/to/file1', $fileLoader->import('my_resource')); + + // Check first file is imported if not already loading + $this->assertSame('path/to/file1', $fileLoader->import('my_resource')); + + // Check second file is imported if first is already loading + $fileLoader->addLoading('path/to/file1'); + $this->assertSame('path/to/file2', $fileLoader->import('my_resource')); + + // Check exception throws if first (and only available) file is already loading + try { + $fileLoader->import('my_resource'); + $this->fail('->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException', $e, '->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading'); + } + + // Check exception throws if all files are already loading + try { + $fileLoader->addLoading('path/to/file2'); + $fileLoader->import('my_resource'); + $this->fail('->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException', $e, '->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading'); + } + } +} + +class TestFileLoader extends FileLoader +{ + public function load($resource, $type = null) + { + return $resource; + } + + public function supports($resource, $type = null) + { + return true; + } + + public function addLoading($resource) + { + self::$loading[$resource] = true; + } + + public function removeLoading($resource) + { + unset(self::$loading[$resource]); + } + + public function clearLoading() + { + self::$loading = array(); + } +}