4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Config\Loader;
14 use Symfony\Component\Config\FileLocatorInterface;
15 use Symfony\Component\Config\Exception\FileLoaderLoadException;
16 use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException;
17 use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
18 use Symfony\Component\Config\Resource\FileExistenceResource;
19 use Symfony\Component\Config\Resource\GlobResource;
22 * FileLoader is the abstract class used by all built-in loaders that are file based.
24 * @author Fabien Potencier <fabien@symfony.com>
26 abstract class FileLoader extends Loader
28 protected static $loading = array();
34 public function __construct(FileLocatorInterface $locator)
36 $this->locator = $locator;
40 * Sets the current directory.
44 public function setCurrentDir($dir)
46 $this->currentDir = $dir;
50 * Returns the file locator used by this loader.
52 * @return FileLocatorInterface
54 public function getLocator()
56 return $this->locator;
62 * @param mixed $resource A Resource
63 * @param string|null $type The resource type or null if unknown
64 * @param bool $ignoreErrors Whether to ignore import errors or not
65 * @param string|null $sourceResource The original resource importing the new resource
69 * @throws FileLoaderLoadException
70 * @throws FileLoaderImportCircularReferenceException
71 * @throws FileLocatorFileNotFoundException
73 public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
75 if (is_string($resource) && strlen($resource) !== $i = strcspn($resource, '*?{[')) {
77 $isSubpath = 0 !== $i && false !== strpos(substr($resource, 0, $i), '/');
78 foreach ($this->glob($resource, false, $_, $ignoreErrors || !$isSubpath) as $path => $info) {
79 if (null !== $res = $this->doImport($path, $type, $ignoreErrors, $sourceResource)) {
86 return isset($ret[1]) ? $ret : (isset($ret[0]) ? $ret[0] : null);
90 return $this->doImport($resource, $type, $ignoreErrors, $sourceResource);
96 protected function glob($pattern, $recursive, &$resource = null, $ignoreErrors = false)
98 if (strlen($pattern) === $i = strcspn($pattern, '*?{[')) {
101 } elseif (0 === $i || false === strpos(substr($pattern, 0, $i), '/')) {
103 $pattern = '/'.$pattern;
105 $prefix = dirname(substr($pattern, 0, 1 + $i));
106 $pattern = substr($pattern, strlen($prefix));
110 $prefix = $this->locator->locate($prefix, $this->currentDir, true);
111 } catch (FileLocatorFileNotFoundException $e) {
112 if (!$ignoreErrors) {
117 foreach ($e->getPaths() as $path) {
118 $resource[] = new FileExistenceResource($path);
123 $resource = new GlobResource($prefix, $pattern, $recursive);
125 foreach ($resource as $path => $info) {
126 yield $path => $info;
130 private function doImport($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
133 $loader = $this->resolve($resource, $type);
135 if ($loader instanceof self && null !== $this->currentDir) {
136 $resource = $loader->getLocator()->locate($resource, $this->currentDir, false);
139 $resources = is_array($resource) ? $resource : array($resource);
140 for ($i = 0; $i < $resourcesCount = count($resources); ++$i) {
141 if (isset(self::$loading[$resources[$i]])) {
142 if ($i == $resourcesCount - 1) {
143 throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading));
146 $resource = $resources[$i];
150 self::$loading[$resource] = true;
153 $ret = $loader->load($resource, $type);
155 unset(self::$loading[$resource]);
159 } catch (FileLoaderImportCircularReferenceException $e) {
161 } catch (\Exception $e) {
162 if (!$ignoreErrors) {
163 // prevent embedded imports from nesting multiple exceptions
164 if ($e instanceof FileLoaderLoadException) {
168 throw new FileLoaderLoadException($resource, $sourceResource, null, $e, $type);