Skip to content

Commit 02f589b

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 90a7527 commit 02f589b

File tree

6 files changed

+154
-0
lines changed

6 files changed

+154
-0
lines changed

Loader/DirectoryLoader.php

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 <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+
}
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

Tests/Fixtures/directory/simple.php

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');

Tests/Loader/DirectoryLoaderTest.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 <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+
}

0 commit comments

Comments
 (0)