Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 73f0ee2

Browse filesBrowse 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
Copy full SHA for 73f0ee2

File tree

Expand file treeCollapse file tree

16 files changed

+305
-2
lines changed
Filter options
Expand file treeCollapse file tree

16 files changed

+305
-2
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
+6Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/composer.json
+1-1Lines 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",
+60Lines 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 <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\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 <seb@wemakecustom.com>
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+
}
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
imports:
2+
- { resource: ../recurse/ }
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[parameters]
2+
ini = ini
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
parameters:
2+
yaml: yaml
+3Lines 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');
+85Lines 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 <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\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

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/Kernel.php
+2Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/composer.json
+1-1Lines 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",
+58Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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\Routing\Loader;
13+
14+
use Symfony\Component\Config\Loader\FileLoader;
15+
use Symfony\Component\Routing\RouteCollection;
16+
use Symfony\Component\Config\Resource\DirectoryResource;
17+
18+
class DirectoryLoader extends FileLoader
19+
{
20+
/**
21+
* {@inheritdoc}
22+
*/
23+
public function load($file, $type = null)
24+
{
25+
$path = $this->locator->locate($file);
26+
27+
$collection = new RouteCollection();
28+
$collection->addResource(new DirectoryResource($path));
29+
30+
foreach (scandir($path) as $dir) {
31+
if ($dir[0] !== '.') {
32+
$this->setCurrentDir($path);
33+
$subPath = $path.'/'.$dir;
34+
$subType = null;
35+
36+
if (is_dir($subPath)) {
37+
$subPath .= '/';
38+
$subType = 'directory';
39+
}
40+
41+
$subCollection = $this->import($subPath, $subType, false, $path);
42+
$collection->addCollection($subCollection);
43+
}
44+
}
45+
46+
return $collection;
47+
}
48+
49+
/**
50+
* {@inheritdoc}
51+
*/
52+
public function supports($resource, $type = null)
53+
{
54+
// only when type is forced to directory, not to conflict with AnnotationLoader
55+
56+
return 'directory' === $type;
57+
}
58+
}
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
route1:
2+
path: /route/1
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
route2:
2+
path: /route/2
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
route3:
2+
path: /route/3
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
_directory:
2+
resource: "../directory"
3+
type: directory
+74Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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\Routing\Tests\Loader;
13+
14+
use Symfony\Component\Routing\Loader\DirectoryLoader;
15+
use Symfony\Component\Routing\Loader\YamlFileLoader;
16+
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
17+
use Symfony\Component\Config\Loader\LoaderResolver;
18+
use Symfony\Component\Config\FileLocator;
19+
use Symfony\Component\Routing\RouteCollection;
20+
21+
class DirectoryLoaderTest extends AbstractAnnotationLoaderTest
22+
{
23+
private $loader;
24+
private $reader;
25+
26+
protected function setUp()
27+
{
28+
parent::setUp();
29+
30+
$locator = new FileLocator();
31+
$this->reader = $this->getReader();
32+
$this->loader = new DirectoryLoader($locator);
33+
$resolver = new LoaderResolver(array(
34+
new YamlFileLoader($locator),
35+
new AnnotationFileLoader($locator, $this->getClassLoader($this->reader)),
36+
$this->loader,
37+
));
38+
$this->loader->setResolver($resolver);
39+
}
40+
41+
public function testLoadDirectory()
42+
{
43+
$collection = $this->loader->load(__DIR__.'/../Fixtures/directory', 'directory');
44+
$this->verifyCollection($collection);
45+
}
46+
47+
public function testImportDirectory()
48+
{
49+
$collection = $this->loader->load(__DIR__.'/../Fixtures/directory_import', 'directory');
50+
$this->verifyCollection($collection);
51+
}
52+
53+
private function verifyCollection(RouteCollection $collection)
54+
{
55+
$routes = $collection->all();
56+
57+
$this->assertCount(3, $routes, 'Three routes are loaded');
58+
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
59+
60+
for ($i = 1; $i <= 3; $i++) {
61+
$this->assertSame('/route/'.$i, $routes["route".$i]->getPath());
62+
}
63+
}
64+
65+
public function testSupports()
66+
{
67+
$fixturesDir = __DIR__.'/../Fixtures';
68+
69+
$this->assertFalse($this->loader->supports($fixturesDir), '->supports(*) returns false');
70+
71+
$this->assertTrue($this->loader->supports($fixturesDir, 'directory'), '->supports(*, "directory") returns true');
72+
$this->assertFalse($this->loader->supports($fixturesDir, 'foo'), '->supports(*, "foo") returns false');
73+
}
74+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.