From c1f0ccb45b30bd6c46d0995a8c7e66594948ca32 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sat, 22 Oct 2022 15:27:14 +0200 Subject: [PATCH] Fix delegating to PSR-4 loader from subdirectory --- .../Loader/DirectoryAwareLoaderInterface.php | 22 +++++++++++++ .../Component/Config/Loader/FileLoader.php | 6 ++-- .../Routing/Loader/Psr4DirectoryLoader.php | 31 +++++++++++++++++-- .../Fixtures/psr4-controllers-redirection.xml | 8 +++++ .../psr4-controllers-redirection.yaml | 2 ++ .../psr4-attributes.xml | 10 ++++++ .../psr4-attributes.yaml | 6 ++++ .../Tests/Loader/XmlFileLoaderTest.php | 15 +++++++-- .../Tests/Loader/YamlFileLoaderTest.php | 15 +++++++-- 9 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 src/Symfony/Component/Config/Loader/DirectoryAwareLoaderInterface.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection.yaml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection/psr4-attributes.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection/psr4-attributes.yaml diff --git a/src/Symfony/Component/Config/Loader/DirectoryAwareLoaderInterface.php b/src/Symfony/Component/Config/Loader/DirectoryAwareLoaderInterface.php new file mode 100644 index 0000000000000..87559cba90c4b --- /dev/null +++ b/src/Symfony/Component/Config/Loader/DirectoryAwareLoaderInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Loader; + +/** + * A loader that can be scoped to a given filesystem directory. + * + * @author Alexander M. Turek + */ +interface DirectoryAwareLoaderInterface +{ + public function forDirectory(string $currentDirectory): static; +} diff --git a/src/Symfony/Component/Config/Loader/FileLoader.php b/src/Symfony/Component/Config/Loader/FileLoader.php index bdf0eada6a6d8..30034e55a58c9 100644 --- a/src/Symfony/Component/Config/Loader/FileLoader.php +++ b/src/Symfony/Component/Config/Loader/FileLoader.php @@ -62,8 +62,6 @@ public function getLocator(): FileLocatorInterface * @param string|null $sourceResource The original resource importing the new resource * @param string|string[]|null $exclude Glob patterns to exclude from the import * - * @return mixed - * * @throws LoaderLoadException * @throws FileLoaderImportCircularReferenceException * @throws FileLocatorFileNotFoundException @@ -136,6 +134,10 @@ private function doImport(mixed $resource, string $type = null, bool $ignoreErro try { $loader = $this->resolve($resource, $type); + if ($loader instanceof DirectoryAwareLoaderInterface) { + $loader = $loader->forDirectory($this->currentDir); + } + if (!$loader instanceof self) { return $loader->load($resource, $type); } diff --git a/src/Symfony/Component/Routing/Loader/Psr4DirectoryLoader.php b/src/Symfony/Component/Routing/Loader/Psr4DirectoryLoader.php index 0493cea15c258..7ae68249ba2a2 100644 --- a/src/Symfony/Component/Routing/Loader/Psr4DirectoryLoader.php +++ b/src/Symfony/Component/Routing/Loader/Psr4DirectoryLoader.php @@ -12,7 +12,9 @@ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\FileLocatorInterface; +use Symfony\Component\Config\Loader\DirectoryAwareLoaderInterface; use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\Config\Resource\DirectoryResource; use Symfony\Component\Routing\RouteCollection; /** @@ -20,8 +22,10 @@ * * @author Alexander M. Turek */ -final class Psr4DirectoryLoader extends Loader +final class Psr4DirectoryLoader extends Loader implements DirectoryAwareLoaderInterface { + private ?string $currentDirectory = null; + public function __construct( private readonly FileLocatorInterface $locator, ) { @@ -34,7 +38,7 @@ public function __construct( */ public function load(mixed $resource, string $type = null): ?RouteCollection { - $path = $this->locator->locate($resource['path']); + $path = $this->locator->locate($resource['path'], $this->currentDirectory); if (!is_dir($path)) { return new RouteCollection(); } @@ -47,12 +51,33 @@ public function supports(mixed $resource, string $type = null): bool return ('attribute' === $type || 'annotation' === $type) && \is_array($resource) && isset($resource['path'], $resource['namespace']); } + public function forDirectory(string $currentDirectory): static + { + $loader = clone $this; + $loader->currentDirectory = $currentDirectory; + + return $loader; + } + private function loadFromDirectory(string $directory, string $psr4Prefix): RouteCollection { $collection = new RouteCollection(); + $collection->addResource(new DirectoryResource($directory, '/\.php$/')); + $files = iterator_to_array(new \RecursiveIteratorIterator( + new \RecursiveCallbackFilterIterator( + new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), + function (\SplFileInfo $current) { + return !str_starts_with($current->getBasename(), '.'); + } + ), + \RecursiveIteratorIterator::LEAVES_ONLY + )); + usort($files, function (\SplFileInfo $a, \SplFileInfo $b) { + return (string) $a > (string) $b ? 1 : -1; + }); /** @var \SplFileInfo $file */ - foreach (new \FilesystemIterator($directory) as $file) { + foreach ($files as $file) { if ($file->isDir()) { $collection->addCollection($this->loadFromDirectory($file->getPathname(), $psr4Prefix.'\\'.$file->getFilename())); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection.xml b/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection.xml new file mode 100644 index 0000000000000..1de9a27067366 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection.yaml b/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection.yaml new file mode 100644 index 0000000000000..16b622f6978d2 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection.yaml @@ -0,0 +1,2 @@ +controllers: + resource: psr4-controllers-redirection/psr4-attributes.yaml diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection/psr4-attributes.xml b/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection/psr4-attributes.xml new file mode 100644 index 0000000000000..170bb664b5b4d --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection/psr4-attributes.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection/psr4-attributes.yaml b/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection/psr4-attributes.yaml new file mode 100644 index 0000000000000..79770db6a6260 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/psr4-controllers-redirection/psr4-attributes.yaml @@ -0,0 +1,6 @@ +my_controllers: + resource: + path: ../Psr4Controllers + namespace: Symfony\Component\Routing\Tests\Fixtures\Psr4Controllers + type: attribute + prefix: /my-prefix diff --git a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php index e52e96673acd3..8963d49850a2f 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php @@ -597,7 +597,10 @@ public function testImportingAliases() $this->assertEquals($expectedRoutes('xml'), $routes); } - public function testImportAttributesWithPsr4Prefix() + /** + * @dataProvider providePsr4ConfigFiles + */ + public function testImportAttributesWithPsr4Prefix(string $configFile) { $locator = new FileLocator(\dirname(__DIR__).'/Fixtures'); new LoaderResolver([ @@ -611,11 +614,19 @@ protected function configureRoute(Route $route, \ReflectionClass $class, \Reflec }, ]); - $route = $loader->load('psr4-attributes.xml')->get('my_route'); + $route = $loader->load($configFile)->get('my_route'); $this->assertSame('/my-prefix/my/route', $route->getPath()); $this->assertSame(MyController::class.'::__invoke', $route->getDefault('_controller')); } + public function providePsr4ConfigFiles(): array + { + return [ + ['psr4-attributes.xml'], + ['psr4-controllers-redirection.xml'], + ]; + } + public function testImportAttributesFromClass() { new LoaderResolver([ diff --git a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php index a9944946ccde2..c7fe9a48a5ba7 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php @@ -463,7 +463,10 @@ public function testImportingAliases() $this->assertEquals($expectedRoutes('yaml'), $routes); } - public function testImportAttributesWithPsr4Prefix() + /** + * @dataProvider providePsr4ConfigFiles + */ + public function testImportAttributesWithPsr4Prefix(string $configFile) { $locator = new FileLocator(\dirname(__DIR__).'/Fixtures'); new LoaderResolver([ @@ -477,11 +480,19 @@ protected function configureRoute(Route $route, \ReflectionClass $class, \Reflec }, ]); - $route = $loader->load('psr4-attributes.yaml')->get('my_route'); + $route = $loader->load($configFile)->get('my_route'); $this->assertSame('/my-prefix/my/route', $route->getPath()); $this->assertSame(MyController::class.'::__invoke', $route->getDefault('_controller')); } + public function providePsr4ConfigFiles(): array + { + return [ + ['psr4-attributes.yaml'], + ['psr4-controllers-redirection.yaml'], + ]; + } + public function testImportAttributesFromClass() { new LoaderResolver([ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy