Skip to content

Commit ed9f714

Browse files
committed
Use glob pattern to load config file
1 parent 136a5ff commit ed9f714

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed

src/Symfony/Component/DependencyInjection/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ CHANGELOG
1414
* using the `PhpDumper` with an uncompiled `ContainerBuilder` is deprecated and
1515
will not be supported anymore in 4.0
1616
* deprecated the `DefinitionDecorator` class in favor of `ChildDefinition`
17+
* allow config files to be loaded using a glob pattern
1718

1819
3.2.0
1920
-----

src/Symfony/Component/DependencyInjection/Loader/FileLoader.php

+59
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
use Symfony\Component\DependencyInjection\ContainerBuilder;
1515
use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader;
1616
use Symfony\Component\Config\FileLocatorInterface;
17+
use Symfony\Component\Config\Exception\FileLoaderLoadException;
18+
use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
19+
use Symfony\Component\Config\Resource\DirectoryResource;
20+
use Symfony\Component\Config\Resource\FileResource;
1721

1822
/**
1923
* FileLoader is the abstract class used by all built-in loaders that are file based.
@@ -24,6 +28,17 @@ abstract class FileLoader extends BaseFileLoader
2428
{
2529
protected $container;
2630

31+
private $currentDir;
32+
33+
/**
34+
* {@inheritdoc}
35+
*/
36+
public function setCurrentDir($dir)
37+
{
38+
$this->currentDir = $dir;
39+
parent::setCurrentDir($dir);
40+
}
41+
2742
/**
2843
* @param ContainerBuilder $container A ContainerBuilder instance
2944
* @param FileLocatorInterface $locator A FileLocator instance
@@ -34,4 +49,48 @@ public function __construct(ContainerBuilder $container, FileLocatorInterface $l
3449

3550
parent::__construct($locator);
3651
}
52+
53+
/**
54+
* {@inheritdoc}
55+
*/
56+
public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
57+
{
58+
if (strlen($resource) === $i = strcspn($resource, '*?{[')) {
59+
$directoryPrefix = $resource;
60+
$directoryGlob = '';
61+
} else {
62+
$directoryPrefix = dirname(substr($resource, 0, 1 + $i));
63+
$directoryGlob = substr($resource, strlen($directoryPrefix));
64+
}
65+
66+
try {
67+
$directoryPrefix = $this->locator->locate($directoryPrefix, $this->currentDir, true);
68+
69+
$directoryPrefix = realpath($directoryPrefix) ?: $directoryPrefix;
70+
$directoryGlob = $directoryPrefix.$directoryGlob;
71+
} catch (FileLocatorFileNotFoundException $e) {
72+
if (!$ignoreErrors) {
73+
// prevent embedded imports from nesting multiple exceptions
74+
if ($e instanceof FileLoaderLoadException) {
75+
throw $e;
76+
}
77+
78+
throw new FileLoaderLoadException($resource, $sourceResource);
79+
}
80+
}
81+
82+
if (!$files = glob($directoryGlob, defined('GLOB_BRACE') ? GLOB_BRACE : 0)) {
83+
throw new FileLoaderLoadException($directoryGlob, $sourceResource);
84+
}
85+
86+
foreach ($files as $file) {
87+
if (is_dir($file)) {
88+
$this->container->addResource(new DirectoryResource($file, '/^$/'));
89+
parent::import($file, 'directory', $ignoreErrors, $sourceResource);
90+
} else {
91+
$this->container->addResource(new FileResource($file));
92+
parent::import($file, $type, $ignoreErrors, $sourceResource);
93+
}
94+
}
95+
}
3796
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests\Loader;
13+
14+
use Symfony\Component\Config\FileLocator;
15+
use Symfony\Component\Config\Loader\LoaderResolver;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Loader\FileLoader;
18+
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
19+
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
20+
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
21+
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
22+
use Symfony\Component\DependencyInjection\Reference;
23+
24+
class FileLoaderTest extends \PHPUnit_Framework_TestCase
25+
{
26+
protected static $fixturesPath;
27+
28+
public static function setUpBeforeClass()
29+
{
30+
self::$fixturesPath = realpath(__DIR__.'/../');
31+
}
32+
33+
public function testImportWithGlobPattern()
34+
{
35+
$container = new ContainerBuilder();
36+
$loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath));
37+
38+
$resolver = new LoaderResolver(array(
39+
new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/ini')),
40+
new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
41+
new PhpFileLoader($container, new FileLocator(self::$fixturesPath.'/php')),
42+
new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')),
43+
));
44+
45+
$loader->setResolver($resolver);
46+
$loader->import('Fixtures/{xml,yaml}/services2.{yml,xml}');
47+
48+
$actual = $container->getParameterBag()->all();
49+
$expected = array(
50+
'a string',
51+
'foo' => 'bar',
52+
'values' => array(
53+
0,
54+
'integer' => 4,
55+
100 => null,
56+
'true',
57+
true,
58+
false,
59+
'on',
60+
'off',
61+
'float' => 1.3,
62+
1000.3,
63+
'a string',
64+
array('foo', 'bar'),
65+
),
66+
'mixedcase' => array('MixedCaseKey' => 'value'),
67+
'constant' => PHP_EOL,
68+
'bar' => '%foo%',
69+
'escape' => '@escapeme',
70+
'foo_bar' => new Reference('foo_bar'),
71+
);
72+
73+
$this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files');
74+
}
75+
}
76+
77+
class TestFileLoader extends FileLoader
78+
{
79+
public function load($resource, $type = null)
80+
{
81+
return $resource;
82+
}
83+
84+
public function supports($resource, $type = null)
85+
{
86+
return false;
87+
}
88+
}

0 commit comments

Comments
 (0)