Skip to content

Commit 02cfd59

Browse files
committed
added support for glob loaders in Config
1 parent f0adc7e commit 02cfd59

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

Loader/FileLoader.php

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
use Symfony\Component\Config\FileLocatorInterface;
1515
use Symfony\Component\Config\Exception\FileLoaderLoadException;
1616
use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException;
17+
use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
18+
use Symfony\Component\Finder\Finder;
19+
use Symfony\Component\Finder\Glob;
1720

1821
/**
1922
* FileLoader is the abstract class used by all built-in loaders that are file based.
@@ -32,7 +35,7 @@ abstract class FileLoader extends Loader
3235
*/
3336
protected $locator;
3437

35-
protected $currentDir;
38+
private $currentDir;
3639

3740
/**
3841
* Constructor.
@@ -78,6 +81,87 @@ public function getLocator()
7881
* @throws FileLoaderImportCircularReferenceException
7982
*/
8083
public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
84+
{
85+
$ret = array();
86+
$ct = 0;
87+
foreach ($this->glob($resource, false, $_, $ignoreErrors) as $resource => $info) {
88+
++$ct;
89+
$ret[] = $this->doImport($resource, $type, $ignoreErrors, $sourceResource);
90+
}
91+
92+
return $ct > 1 ? $ret : isset($ret[0]) ? $ret[0] : null;
93+
}
94+
95+
/**
96+
* @internal
97+
*/
98+
protected function glob($resource, $recursive, &$prefix = null, $ignoreErrors = false)
99+
{
100+
if (strlen($resource) === $i = strcspn($resource, '*?{[')) {
101+
if (!$recursive) {
102+
$prefix = null;
103+
104+
yield $resource => new \SplFileInfo($resource);
105+
106+
return;
107+
}
108+
$prefix = $resource;
109+
$resource = '';
110+
} elseif (0 === $i) {
111+
$prefix = '.';
112+
$resource = '/'.$resource;
113+
} else {
114+
$prefix = dirname(substr($resource, 0, 1 + $i));
115+
$resource = substr($resource, strlen($prefix));
116+
}
117+
118+
try {
119+
$prefix = $this->locator->locate($prefix, $this->currentDir, true);
120+
} catch (FileLocatorFileNotFoundException $e) {
121+
if (!$ignoreErrors) {
122+
throw $e;
123+
}
124+
125+
return;
126+
}
127+
$prefix = realpath($prefix) ?: $prefix;
128+
129+
if (false === strpos($resource, '/**/') && (defined('GLOB_BRACE') || false === strpos($resource, '{'))) {
130+
foreach (glob($prefix.$resource, defined('GLOB_BRACE') ? GLOB_BRACE : 0) as $path) {
131+
if ($recursive && is_dir($path)) {
132+
$flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS;
133+
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, $flags)) as $path => $info) {
134+
if ($info->isFile()) {
135+
yield $path => $info;
136+
}
137+
}
138+
} elseif (is_file($path)) {
139+
yield $path => new \SplFileInfo($path);
140+
}
141+
}
142+
143+
return;
144+
}
145+
146+
if (!class_exists(Finder::class)) {
147+
throw new LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.', $resource));
148+
}
149+
150+
$finder = new Finder();
151+
$regex = Glob::toRegex($resource);
152+
if ($recursive) {
153+
$regex = substr_replace($regex, '(/|$)', -2, 1);
154+
}
155+
156+
$prefixLen = strlen($prefix);
157+
foreach ($finder->followLinks()->in($prefix) as $path => $info) {
158+
if (preg_match($regex, substr($path, $prefixLen)) && $info->isFile()) {
159+
yield $path => $info;
160+
}
161+
}
162+
}
163+
164+
private function doImport($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
81165
{
82166
try {
83167
$loader = $this->resolve($resource, $type);

Loader/GlobFileLoader.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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\Config\Loader;
13+
14+
/**
15+
* GlobFileLoader loads files from a glob pattern.
16+
*
17+
* @author Fabien Potencier <[email protected]>
18+
*/
19+
class GlobFileLoader extends FileLoader
20+
{
21+
/**
22+
* {@inheritdoc}
23+
*/
24+
public function load($resource, $type = null)
25+
{
26+
return $this->import($resource, null, true);
27+
}
28+
29+
/**
30+
* {@inheritdoc}
31+
*/
32+
public function supports($resource, $type = null)
33+
{
34+
return 'glob' === $type;
35+
}
36+
}

0 commit comments

Comments
 (0)