Skip to content

Commit 73f0ee2

Browse files
lavoieslnicolas-grekas
authored andcommitted
[DI][Routing] recursive directory loading
Issue #11045 For now, the Routing DirectoryLoader requires the type `directory` to be specified so it does not conflict with `AnnotationDirectoryLoader`. However, this could be refactored.
1 parent 78cf382 commit 73f0ee2

File tree

16 files changed

+305
-2
lines changed

16 files changed

+305
-2
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<parameter key="routing.loader.xml.class">Symfony\Component\Routing\Loader\XmlFileLoader</parameter>
1313
<parameter key="routing.loader.yml.class">Symfony\Component\Routing\Loader\YamlFileLoader</parameter>
1414
<parameter key="routing.loader.php.class">Symfony\Component\Routing\Loader\PhpFileLoader</parameter>
15+
<parameter key="routing.loader.directory.class">Symfony\Component\Routing\Loader\DirectoryLoader</parameter>
1516
<parameter key="router.options.generator_class">Symfony\Component\Routing\Generator\UrlGenerator</parameter>
1617
<parameter key="router.options.generator_base_class">Symfony\Component\Routing\Generator\UrlGenerator</parameter>
1718
<parameter key="router.options.generator_dumper_class">Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper</parameter>
@@ -45,6 +46,11 @@
4546
<argument type="service" id="file_locator" />
4647
</service>
4748

49+
<service id="routing.loader.directory" class="%routing.loader.directory.class%" public="false">
50+
<tag name="routing.loader" />
51+
<argument type="service" id="file_locator" />
52+
</service>
53+
4854
<service id="routing.loader" class="%routing.loader.class%">
4955
<tag name="monolog.logger" channel="router" />
5056
<argument type="service" id="controller_name_converter" />

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"require": {
1919
"php": ">=5.3.9",
2020
"symfony/asset": "~2.7|~3.0.0",
21-
"symfony/dependency-injection" : "~2.6,>=2.6.2",
21+
"symfony/dependency-injection" : "~2.8",
2222
"symfony/config" : "~2.4",
2323
"symfony/event-dispatcher": "~2.5|~3.0.0",
2424
"symfony/http-foundation": "~2.4.9|~2.5,>=2.5.4|~3.0.0",
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Loader;
13+
14+
use Symfony\Component\Config\Resource\DirectoryResource;
15+
16+
/**
17+
* DirectoryLoader is a recursive loader to go through directories
18+
*
19+
* @author Sebastien Lavoie <[email protected]>
20+
*/
21+
class DirectoryLoader extends FileLoader
22+
{
23+
/**
24+
* {@inheritdoc}
25+
*/
26+
public function load($file, $type = null)
27+
{
28+
$file = rtrim($file, '/');
29+
$path = $this->locator->locate($file);
30+
$this->container->addResource(new DirectoryResource($path));
31+
32+
foreach (scandir($path) as $dir) {
33+
if ($dir[0] !== '.') {
34+
if (is_dir($path.'/'.$dir)) {
35+
$dir .= '/'; // append / to allow recursion
36+
}
37+
38+
$this->setCurrentDir($path);
39+
40+
$this->import($dir, null, false, $path);
41+
}
42+
}
43+
}
44+
45+
/**
46+
* {@inheritdoc}
47+
*/
48+
public function supports($resource, $type = null)
49+
{
50+
if ('directory' === $type) {
51+
return true;
52+
}
53+
54+
if (null === $type) {
55+
return preg_match('/\/$/', $resource) === 1;
56+
}
57+
58+
return false;
59+
}
60+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
imports:
2+
- { resource: ../recurse/ }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[parameters]
2+
ini = ini
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
parameters:
2+
yaml: yaml
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
$container->setParameter('php', 'php');
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\DependencyInjection\ContainerBuilder;
15+
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
16+
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
17+
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
18+
use Symfony\Component\DependencyInjection\Loader\DirectoryLoader;
19+
use Symfony\Component\Config\Loader\LoaderResolver;
20+
use Symfony\Component\Config\FileLocator;
21+
22+
class DirectoryLoaderTest extends \PHPUnit_Framework_TestCase
23+
{
24+
private static $fixturesPath;
25+
26+
private $container;
27+
private $loader;
28+
29+
public static function setUpBeforeClass()
30+
{
31+
self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
32+
}
33+
34+
protected function setUp()
35+
{
36+
$locator = new FileLocator(self::$fixturesPath);
37+
$this->container = new ContainerBuilder();
38+
$this->loader = new DirectoryLoader($this->container, $locator);
39+
$resolver = new LoaderResolver(array(
40+
new PhpFileLoader($this->container, $locator),
41+
new IniFileLoader($this->container, $locator),
42+
new YamlFileLoader($this->container, $locator),
43+
$this->loader,
44+
));
45+
$this->loader->setResolver($resolver);
46+
}
47+
48+
public function testDirectoryCanBeLoadedRecursively()
49+
{
50+
$this->loader->load('directory/');
51+
$this->assertEquals(array('ini' => 'ini', 'yaml' => 'yaml', 'php' => 'php'), $this->container->getParameterBag()->all(), '->load() takes a single directory');
52+
}
53+
54+
public function testImports()
55+
{
56+
$this->loader->resolve('directory/import/import.yml')->load('directory/import/import.yml');
57+
$this->assertEquals(array('ini' => 'ini', 'yaml' => 'yaml'), $this->container->getParameterBag()->all(), '->load() takes a single file that imports a directory');
58+
}
59+
60+
/**
61+
* @covers Symfony\Component\DependencyInjection\Loader\DirectoryLoader::__construct
62+
* @covers Symfony\Component\DependencyInjection\Loader\DirectoryLoader::load
63+
*
64+
* @expectedException \InvalidArgumentException
65+
* @expectedExceptionMessage The file "foo" does not exist (in:
66+
*/
67+
public function testExceptionIsRaisedWhenDirectoryDoesNotExist()
68+
{
69+
$this->loader->load('foo/');
70+
}
71+
72+
/**
73+
* @covers Symfony\Component\DependencyInjection\Loader\DirectoryLoader::supports
74+
*/
75+
public function testSupports()
76+
{
77+
$loader = new DirectoryLoader(new ContainerBuilder(), new FileLocator());
78+
79+
$this->assertTrue($loader->supports('directory/'), '->supports("directory/") returns true');
80+
$this->assertTrue($loader->supports('directory/', 'directory'), '->supports("directory/", "directory") returns true');
81+
$this->assertFalse($loader->supports('directory'), '->supports("directory") returns false');
82+
$this->assertTrue($loader->supports('directory', 'directory'), '->supports("directory", "directory") returns true');
83+
$this->assertFalse($loader->supports('directory', 'foo'), '->supports("directory, "foo") returns false');
84+
}
85+
}

src/Symfony/Component/HttpKernel/Kernel.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
2222
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
2323
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
24+
use Symfony\Component\DependencyInjection\Loader\DirectoryLoader;
2425
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
2526
use Symfony\Component\HttpFoundation\Request;
2627
use Symfony\Component\HttpFoundation\Response;
@@ -721,6 +722,7 @@ protected function getContainerLoader(ContainerInterface $container)
721722
new YamlFileLoader($container, $locator),
722723
new IniFileLoader($container, $locator),
723724
new PhpFileLoader($container, $locator),
725+
new DirectoryLoader($container, $locator),
724726
new ClosureLoader($container),
725727
));
726728

src/Symfony/Component/HttpKernel/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"symfony/expression-language": "~2.4|~3.0.0",
3535
"symfony/finder": "~2.0,>=2.0.5|~3.0.0",
3636
"symfony/process": "~2.0,>=2.0.5|~3.0.0",
37-
"symfony/routing": "~2.2|~3.0.0",
37+
"symfony/routing": "~2.7|~3.0.0",
3838
"symfony/stopwatch": "~2.3|~3.0.0",
3939
"symfony/templating": "~2.2|~3.0.0",
4040
"symfony/translation": "~2.0,>=2.0.5|~3.0.0",

0 commit comments

Comments
 (0)