diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
index 6050686d6c3c5..1ce967ad712ee 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
@@ -36,6 +36,11 @@
+
+
+
+
+
diff --git a/src/Symfony/Component/Config/Loader/FileLoader.php b/src/Symfony/Component/Config/Loader/FileLoader.php
index f0896a3b7b53e..5259cdb3bcab3 100644
--- a/src/Symfony/Component/Config/Loader/FileLoader.php
+++ b/src/Symfony/Component/Config/Loader/FileLoader.php
@@ -14,6 +14,9 @@
use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Config\Exception\FileLoaderLoadException;
use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException;
+use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Finder\Glob;
/**
* FileLoader is the abstract class used by all built-in loaders that are file based.
@@ -32,7 +35,7 @@ abstract class FileLoader extends Loader
*/
protected $locator;
- protected $currentDir;
+ private $currentDir;
/**
* Constructor.
@@ -78,6 +81,87 @@ public function getLocator()
* @throws FileLoaderImportCircularReferenceException
*/
public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
+ {
+ $ret = array();
+ $ct = 0;
+ foreach ($this->glob($resource, false, $_, $ignoreErrors) as $resource => $info) {
+ ++$ct;
+ $ret[] = $this->doImport($resource, $type, $ignoreErrors, $sourceResource);
+ }
+
+ return $ct > 1 ? $ret : isset($ret[0]) ? $ret[0] : null;
+ }
+
+ /**
+ * @internal
+ */
+ protected function glob($resource, $recursive, &$prefix = null, $ignoreErrors = false)
+ {
+ if (strlen($resource) === $i = strcspn($resource, '*?{[')) {
+ if (!$recursive) {
+ $prefix = null;
+
+ yield $resource => new \SplFileInfo($resource);
+
+ return;
+ }
+ $prefix = $resource;
+ $resource = '';
+ } elseif (0 === $i) {
+ $prefix = '.';
+ $resource = '/'.$resource;
+ } else {
+ $prefix = dirname(substr($resource, 0, 1 + $i));
+ $resource = substr($resource, strlen($prefix));
+ }
+
+ try {
+ $prefix = $this->locator->locate($prefix, $this->currentDir, true);
+ } catch (FileLocatorFileNotFoundException $e) {
+ if (!$ignoreErrors) {
+ throw $e;
+ }
+
+ return;
+ }
+ $prefix = realpath($prefix) ?: $prefix;
+
+ if (false === strpos($resource, '/**/') && (defined('GLOB_BRACE') || false === strpos($resource, '{'))) {
+ foreach (glob($prefix.$resource, defined('GLOB_BRACE') ? GLOB_BRACE : 0) as $path) {
+ if ($recursive && is_dir($path)) {
+ $flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS;
+ foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, $flags)) as $path => $info) {
+ if ($info->isFile()) {
+ yield $path => $info;
+ }
+ }
+ } elseif (is_file($path)) {
+ yield $path => new \SplFileInfo($path);
+ }
+ }
+
+ return;
+ }
+
+ if (!class_exists(Finder::class)) {
+ throw new LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.', $resource));
+ }
+
+ $finder = new Finder();
+ $regex = Glob::toRegex($resource);
+ if ($recursive) {
+ $regex = substr_replace($regex, '(/|$)', -2, 1);
+ }
+
+ $prefixLen = strlen($prefix);
+ foreach ($finder->followLinks()->in($prefix) as $path => $info) {
+ if (preg_match($regex, substr($path, $prefixLen)) && $info->isFile()) {
+ yield $path => $info;
+ }
+ }
+ }
+
+ private function doImport($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
{
try {
$loader = $this->resolve($resource, $type);
diff --git a/src/Symfony/Component/Config/Loader/GlobFileLoader.php b/src/Symfony/Component/Config/Loader/GlobFileLoader.php
new file mode 100644
index 0000000000000..8b0c2401e9ff8
--- /dev/null
+++ b/src/Symfony/Component/Config/Loader/GlobFileLoader.php
@@ -0,0 +1,36 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Config\Loader;
+
+/**
+ * GlobFileLoader loads files from a glob pattern.
+ *
+ * @author Fabien Potencier
+ */
+class GlobFileLoader extends FileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, $type = null)
+ {
+ return $this->import($resource, null, true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function supports($resource, $type = null)
+ {
+ return 'glob' === $type;
+ }
+}
diff --git a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
index ba0b77f0f5bf0..bb9dc214e6a50 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php
@@ -11,16 +11,12 @@
namespace Symfony\Component\DependencyInjection\Loader;
-use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
-use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader;
use Symfony\Component\Config\FileLocatorInterface;
-use Symfony\Component\Finder\Finder;
-use Symfony\Component\Finder\Glob;
/**
* FileLoader is the abstract class used by all built-in loaders that are file based.
@@ -44,22 +40,6 @@ public function __construct(ContainerBuilder $container, FileLocatorInterface $l
parent::__construct($locator);
}
- /**
- * {@inheritdoc}
- */
- public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
- {
- try {
- foreach ($this->glob($resource, false) as $path => $info) {
- parent::import($path, $type, $ignoreErrors, $sourceResource);
- }
- } catch (FileLocatorFileNotFoundException $e) {
- if (!$ignoreErrors) {
- throw $e;
- }
- }
- }
-
/**
* Registers a set of classes as services using PSR-4 for discovery.
*
@@ -106,8 +86,12 @@ private function findClasses($namespace, $resource)
{
$classes = array();
$extRegexp = defined('HHVM_VERSION') ? '/\\.(?:php|hh)$/' : '/\\.php$/';
+ $prefixLen = null;
+ foreach ($this->glob($resource, true, $prefix) as $path => $info) {
+ if (null === $prefixLen) {
+ $prefixLen = strlen($prefix);
+ }
- foreach ($this->glob($resource, true, $prefixLen) as $path => $info) {
if (!preg_match($extRegexp, $path, $m) || !$info->isReadable()) {
continue;
}
@@ -124,65 +108,11 @@ private function findClasses($namespace, $resource)
}
}
- return $classes;
- }
-
- private function glob($resource, $recursive, &$prefixLen = null)
- {
- if (strlen($resource) === $i = strcspn($resource, '*?{[')) {
- if (!$recursive) {
- yield $resource => new \SplFileInfo($resource);
-
- return;
- }
- $resourcePrefix = $resource;
- $resource = '';
- } elseif (0 === $i) {
- $resourcePrefix = '.';
- $resource = '/'.$resource;
- } else {
- $resourcePrefix = dirname(substr($resource, 0, 1 + $i));
- $resource = substr($resource, strlen($resourcePrefix));
- }
-
- $resourcePrefix = $this->locator->locate($resourcePrefix, $this->currentDir, true);
- $resourcePrefix = realpath($resourcePrefix) ?: $resourcePrefix;
- $prefixLen = strlen($resourcePrefix);
-
- // track directories only for new & removed files
- $this->container->fileExists($resourcePrefix, '/^$/');
-
- if (false === strpos($resource, '/**/') && (defined('GLOB_BRACE') || false === strpos($resource, '{'))) {
- foreach (glob($resourcePrefix.$resource, defined('GLOB_BRACE') ? GLOB_BRACE : 0) as $path) {
- if ($recursive && is_dir($path)) {
- $flags = \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS;
- foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, $flags)) as $path => $info) {
- if ($info->isFile()) {
- yield $path => $info;
- }
- }
- } elseif (is_file($path)) {
- yield $path => new \SplFileInfo($path);
- }
- }
-
- return;
+ if (null !== $prefix) {
+ // track directories only for new & removed files
+ $this->container->fileExists($prefix, '/^$/');
}
- if (!class_exists(Finder::class)) {
- throw new LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.', $resource));
- }
-
- $finder = new Finder();
- $regex = Glob::toRegex($resource);
- if ($recursive) {
- $regex = substr_replace($regex, '(/|$)', -2, 1);
- }
-
- foreach ($finder->followLinks()->in($resourcePrefix) as $path => $info) {
- if (preg_match($regex, substr($path, $prefixLen)) && $info->isFile()) {
- yield $path => $info;
- }
- }
+ return $classes;
}
}
diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php
index e83fd248d9c28..9523b7a3ca997 100644
--- a/src/Symfony/Component/HttpKernel/Kernel.php
+++ b/src/Symfony/Component/HttpKernel/Kernel.php
@@ -29,6 +29,7 @@
use Symfony\Component\HttpKernel\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass;
+use Symfony\Component\Config\Loader\GlobFileLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\ConfigCache;
@@ -686,6 +687,7 @@ protected function getContainerLoader(ContainerInterface $container)
new YamlFileLoader($container, $locator),
new IniFileLoader($container, $locator),
new PhpFileLoader($container, $locator),
+ new GlobFileLoader($locator),
new DirectoryLoader($container, $locator),
new ClosureLoader($container),
));
diff --git a/src/Symfony/Component/Routing/RouteCollectionBuilder.php b/src/Symfony/Component/Routing/RouteCollectionBuilder.php
index 726dfa9022cfb..89b426266b84e 100644
--- a/src/Symfony/Component/Routing/RouteCollectionBuilder.php
+++ b/src/Symfony/Component/Routing/RouteCollectionBuilder.php
@@ -61,21 +61,28 @@ public function __construct(LoaderInterface $loader = null)
*/
public function import($resource, $prefix = '/', $type = null)
{
- /** @var RouteCollection $collection */
- $collection = $this->load($resource, $type);
+ /** @var RouteCollection[] $collection */
+ $collections = $this->load($resource, $type);
// create a builder from the RouteCollection
$builder = $this->createBuilder();
- foreach ($collection->all() as $name => $route) {
- $builder->addRoute($route, $name);
- }
- foreach ($collection->getResources() as $resource) {
- $builder->addResource($resource);
- }
+ foreach ($collections as $collection) {
+ if (null === $collection) {
+ continue;
+ }
- // mount into this builder
- $this->mount($prefix, $builder);
+ foreach ($collection->all() as $name => $route) {
+ $builder->addRoute($route, $name);
+ }
+
+ foreach ($collection->getResources() as $resource) {
+ $builder->addResource($resource);
+ }
+
+ // mount into this builder
+ $this->mount($prefix, $builder);
+ }
return $builder;
}
@@ -201,7 +208,7 @@ public function setRequirement($key, $regex)
}
/**
- * Sets an opiton that will be added to all embedded routes (unless that
+ * Sets an option that will be added to all embedded routes (unless that
* option is already set).
*
* @param string $key
@@ -345,7 +352,7 @@ private function generateRouteName(Route $route)
* @param mixed $resource A resource
* @param string|null $type The resource type or null if unknown
*
- * @return RouteCollection
+ * @return RouteCollection[]
*
* @throws FileLoaderLoadException If no loader is found
*/
@@ -356,7 +363,9 @@ private function load($resource, $type = null)
}
if ($this->loader->supports($resource, $type)) {
- return $this->loader->load($resource, $type);
+ $collections = $this->loader->load($resource, $type);
+
+ return is_array($collections) ? $collections : array($collections);
}
if (null === $resolver = $this->loader->getResolver()) {
@@ -367,6 +376,8 @@ private function load($resource, $type = null)
throw new FileLoaderLoadException($resource);
}
- return $loader->load($resource, $type);
+ $collections = $loader->load($resource, $type);
+
+ return is_array($collections) ? $collections : array($collections);
}
}