Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fbbcf9f

Browse files
committed
added support for glob loaders in Config
1 parent c5bdfc5 commit fbbcf9f

File tree

6 files changed

+160
-94
lines changed

6 files changed

+160
-94
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@
3636
<argument type="service" id="file_locator" />
3737
</service>
3838

39+
<service id="routing.loader.glob" class="Symfony\Component\Config\Loader\GlobFileLoader" public="false">
40+
<tag name="routing.loader" />
41+
<argument type="service" id="file_locator" />
42+
</service>
43+
3944
<service id="routing.loader.directory" class="Symfony\Component\Routing\Loader\DirectoryLoader" public="false">
4045
<tag name="routing.loader" />
4146
<argument type="service" id="file_locator" />

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

Lines changed: 83 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,85 @@ 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 : $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+
yield $resource => new \SplFileInfo($resource);
103+
104+
return;
105+
}
106+
$prefix = $resource;
107+
$resource = '';
108+
} elseif (0 === $i) {
109+
$prefix = '.';
110+
$resource = '/'.$resource;
111+
} else {
112+
$prefix = dirname(substr($resource, 0, 1 + $i));
113+
$resource = substr($resource, strlen($prefix));
114+
}
115+
116+
try {
117+
$prefix = $this->locator->locate($prefix, $this->currentDir, true);
118+
} catch (FileLocatorFileNotFoundException $e) {
119+
if (!$ignoreErrors) {
120+
throw $e;
121+
}
122+
123+
return;
124+
}
125+
$prefix = realpath($prefix) ?: $prefix;
126+
127+
if (false === strpos($resource, '/**/') && (defined('GLOB_BRACE') || false === strpos($resource, '{'))) {
128+
foreach (glob($prefix.$resource, defined('GLOB_BRACE') ? GLOB_BRACE : 0) as $path) {
129+
if ($recursive && is_dir($path)) {
130+
$flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS;
131+
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, $flags)) as $path => $info) {
132+
if ($info->isFile()) {
133+
yield $path => $info;
134+
}
135+
}
136+
} elseif (is_file($path)) {
137+
yield $path => new \SplFileInfo($path);
138+
}
139+
}
140+
141+
return;
142+
}
143+
144+
if (!class_exists(Finder::class)) {
145+
throw new LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.', $resource));
146+
}
147+
148+
$finder = new Finder();
149+
$regex = Glob::toRegex($resource);
150+
if ($recursive) {
151+
$regex = substr_replace($regex, '(/|$)', -2, 1);
152+
}
153+
154+
$prefixLen = strlen($prefix);
155+
foreach ($finder->followLinks()->in($prefix) as $path => $info) {
156+
if (preg_match($regex, substr($path, $prefixLen)) && $info->isFile()) {
157+
yield $path => $info;
158+
}
159+
}
160+
}
161+
162+
private function doImport($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
81163
{
82164
try {
83165
$loader = $this->resolve($resource, $type);
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+
}

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

Lines changed: 9 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,11 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Loader;
1313

14-
use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
1514
use Symfony\Component\DependencyInjection\ContainerBuilder;
1615
use Symfony\Component\DependencyInjection\Definition;
1716
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
18-
use Symfony\Component\DependencyInjection\Exception\LogicException;
1917
use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader;
2018
use Symfony\Component\Config\FileLocatorInterface;
21-
use Symfony\Component\Finder\Finder;
22-
use Symfony\Component\Finder\Glob;
2319

2420
/**
2521
* FileLoader is the abstract class used by all built-in loaders that are file based.
@@ -41,22 +37,6 @@ public function __construct(ContainerBuilder $container, FileLocatorInterface $l
4137
parent::__construct($locator);
4238
}
4339

44-
/**
45-
* {@inheritdoc}
46-
*/
47-
public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
48-
{
49-
try {
50-
foreach ($this->glob($resource, false) as $path => $info) {
51-
parent::import($path, $type, $ignoreErrors, $sourceResource);
52-
}
53-
} catch (FileLocatorFileNotFoundException $e) {
54-
if (!$ignoreErrors) {
55-
throw $e;
56-
}
57-
}
58-
}
59-
6040
/**
6141
* Registers a set of classes as services using PSR-4 for discovery.
6242
*
@@ -88,8 +68,12 @@ private function findClasses($namespace, $resource)
8868
{
8969
$classes = array();
9070
$extRegexp = defined('HHVM_VERSION') ? '/\\.(?:php|hh)$/' : '/\\.php$/';
71+
$prefixLen = null;
72+
foreach ($this->glob($resource, true, $prefix) as $path => $info) {
73+
if (null === $prefixLen) {
74+
$prefixLen = strlen($prefix);
75+
}
9176

92-
foreach ($this->glob($resource, true, $prefixLen) as $path => $info) {
9377
if (!preg_match($extRegexp, $path, $m) || !$info->isReadable()) {
9478
continue;
9579
}
@@ -106,65 +90,11 @@ private function findClasses($namespace, $resource)
10690
}
10791
}
10892

109-
return $classes;
110-
}
111-
112-
private function glob($resource, $recursive, &$prefixLen = null)
113-
{
114-
if (strlen($resource) === $i = strcspn($resource, '*?{[')) {
115-
if (!$recursive) {
116-
yield $resource => new \SplFileInfo($resource);
117-
118-
return;
119-
}
120-
$resourcePrefix = $resource;
121-
$resource = '';
122-
} elseif (0 === $i) {
123-
$resourcePrefix = '.';
124-
$resource = '/'.$resource;
125-
} else {
126-
$resourcePrefix = dirname(substr($resource, 0, 1 + $i));
127-
$resource = substr($resource, strlen($resourcePrefix));
128-
}
129-
130-
$resourcePrefix = $this->locator->locate($resourcePrefix, $this->currentDir, true);
131-
$resourcePrefix = realpath($resourcePrefix) ?: $resourcePrefix;
132-
$prefixLen = strlen($resourcePrefix);
133-
134-
// track directories only for new & removed files
135-
$this->container->fileExists($resourcePrefix, '/^$/');
136-
137-
if (false === strpos($resource, '/**/') && (defined('GLOB_BRACE') || false === strpos($resource, '{'))) {
138-
foreach (glob($resourcePrefix.$resource, defined('GLOB_BRACE') ? GLOB_BRACE : 0) as $path) {
139-
if ($recursive && is_dir($path)) {
140-
$flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS;
141-
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, $flags)) as $path => $info) {
142-
if ($info->isFile()) {
143-
yield $path => $info;
144-
}
145-
}
146-
} elseif (is_file($path)) {
147-
yield $path => new \SplFileInfo($path);
148-
}
149-
}
150-
151-
return;
152-
}
153-
154-
if (!class_exists(Finder::class)) {
155-
throw new LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.', $resource));
156-
}
157-
158-
$finder = new Finder();
159-
$regex = Glob::toRegex($resource);
160-
if ($recursive) {
161-
$regex = substr_replace($regex, '(/|$)', -2, 1);
93+
if (null !== $prefix) {
94+
// track directories only for new & removed files
95+
$this->container->fileExists($prefix, '/^$/');
16296
}
16397

164-
foreach ($finder->followLinks()->in($resourcePrefix) as $path => $info) {
165-
if (preg_match($regex, substr($path, $prefixLen)) && $info->isFile()) {
166-
yield $path => $info;
167-
}
168-
}
98+
return $classes;
16999
}
170100
}

src/Symfony/Component/HttpKernel/Kernel.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use Symfony\Component\HttpKernel\Config\FileLocator;
3030
use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
3131
use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass;
32+
use Symfony\Component\Config\Loader\GlobFileLoader;
3233
use Symfony\Component\Config\Loader\LoaderResolver;
3334
use Symfony\Component\Config\Loader\DelegatingLoader;
3435
use Symfony\Component\Config\ConfigCache;
@@ -686,6 +687,7 @@ protected function getContainerLoader(ContainerInterface $container)
686687
new YamlFileLoader($container, $locator),
687688
new IniFileLoader($container, $locator),
688689
new PhpFileLoader($container, $locator),
690+
new GlobFileLoader($locator),
689691
new DirectoryLoader($container, $locator),
690692
new ClosureLoader($container),
691693
));

src/Symfony/Component/Routing/RouteCollectionBuilder.php

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,28 @@ public function __construct(LoaderInterface $loader = null)
6161
*/
6262
public function import($resource, $prefix = '/', $type = null)
6363
{
64-
/** @var RouteCollection $collection */
65-
$collection = $this->load($resource, $type);
64+
/** @var RouteCollection[] $collection */
65+
$collections = $this->load($resource, $type);
6666

6767
// create a builder from the RouteCollection
6868
$builder = $this->createBuilder();
69-
foreach ($collection->all() as $name => $route) {
70-
$builder->addRoute($route, $name);
71-
}
7269

73-
foreach ($collection->getResources() as $resource) {
74-
$builder->addResource($resource);
75-
}
70+
foreach ($collections as $collection) {
71+
if (null === $collection) {
72+
continue;
73+
}
7674

77-
// mount into this builder
78-
$this->mount($prefix, $builder);
75+
foreach ($collection->all() as $name => $route) {
76+
$builder->addRoute($route, $name);
77+
}
78+
79+
foreach ($collection->getResources() as $resource) {
80+
$builder->addResource($resource);
81+
}
82+
83+
// mount into this builder
84+
$this->mount($prefix, $builder);
85+
}
7986

8087
return $builder;
8188
}
@@ -201,7 +208,7 @@ public function setRequirement($key, $regex)
201208
}
202209

203210
/**
204-
* Sets an opiton that will be added to all embedded routes (unless that
211+
* Sets an option that will be added to all embedded routes (unless that
205212
* option is already set).
206213
*
207214
* @param string $key
@@ -345,7 +352,7 @@ private function generateRouteName(Route $route)
345352
* @param mixed $resource A resource
346353
* @param string|null $type The resource type or null if unknown
347354
*
348-
* @return RouteCollection
355+
* @return RouteCollection[]
349356
*
350357
* @throws FileLoaderLoadException If no loader is found
351358
*/
@@ -356,7 +363,9 @@ private function load($resource, $type = null)
356363
}
357364

358365
if ($this->loader->supports($resource, $type)) {
359-
return $this->loader->load($resource, $type);
366+
$collections = $this->loader->load($resource, $type);
367+
368+
return is_array($collections) ? $collections : array($collections);
360369
}
361370

362371
if (null === $resolver = $this->loader->getResolver()) {
@@ -367,6 +376,8 @@ private function load($resource, $type = null)
367376
throw new FileLoaderLoadException($resource);
368377
}
369378

370-
return $loader->load($resource, $type);
379+
$collections = $loader->load($resource, $type);
380+
381+
return is_array($collections) ? $collections : array($collections);
371382
}
372383
}

0 commit comments

Comments
 (0)