diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 57c1517854..859515b3ca 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -11,7 +11,7 @@
Replace this notice by a short README for your feature/bugfix. This will help people
understand your PR and can be used as a start for the documentation.
-Additionally (see https://symfony.com/roadmap):
+Additionally (see https://symfony.com/releases):
- Always add tests and ensure they pass.
- Never break backward compatibility (see https://symfony.com/bc).
- Bug fixes must be submitted against the lowest maintained branch where they apply
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig
index c085303213..4e4a59d1b3 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig
@@ -153,7 +153,7 @@
{{ collector.symfonyeom }} |
{{ collector.symfonyeol }} |
- View roadmap
+ View roadmap
|
diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php
index 3de7a04d52..26d8d92b65 100644
--- a/src/Symfony/Component/Console/Application.php
+++ b/src/Symfony/Component/Console/Application.php
@@ -647,7 +647,15 @@ class Application implements ResetInterface
// filter out aliases for commands which are already on the list
if (\count($commands) > 1) {
$commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
- $commands = array_unique(array_filter($commands, function ($nameOrAlias) use (&$commandList, $commands, &$aliases) {
+
+ if (isset($commandList[$name])) {
+ return $this->get($name);
+ }
+
+ foreach ($commands as $k => $nameOrAlias) {
+ if ($nameOrAlias === $name) {
+ return $this->get($nameOrAlias);
+ }
if (!$commandList[$nameOrAlias] instanceof Command) {
$commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias);
}
@@ -656,8 +664,14 @@ class Application implements ResetInterface
$aliases[$nameOrAlias] = $commandName;
- return $commandName === $nameOrAlias || !\in_array($commandName, $commands);
- }));
+ if ($commandName === $nameOrAlias || !\in_array($commandName, $commands)) {
+ continue;
+ }
+
+ unset($commands[$k]);
+ }
+
+ $commands = array_unique($commands);
}
if (\count($commands) > 1) {
diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php
index df8d8e46fe..cd8904ea72 100644
--- a/src/Symfony/Component/Console/Tests/ApplicationTest.php
+++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php
@@ -1692,6 +1692,31 @@ class ApplicationTest extends TestCase
$this->assertArrayNotHasKey('disabled', $application->all());
}
+ public function testFindAlternativesDoesNotLoadSameNamespaceCommandsOnExactMatch()
+ {
+ $application = new Application();
+ $application->setAutoExit(false);
+
+ $loaded = [];
+
+ $application->setCommandLoader(new FactoryCommandLoader([
+ 'foo:bar' => function () use (&$loaded) {
+ $loaded['foo:bar'] = true;
+
+ return (new Command('foo:bar'))->setCode(function () {});
+ },
+ 'foo' => function () use (&$loaded) {
+ $loaded['foo'] = true;
+
+ return (new Command('foo'))->setCode(function () {});
+ },
+ ]));
+
+ $application->run(new ArrayInput(['command' => 'foo']), new NullOutput());
+
+ $this->assertSame(['foo' => true], $loaded);
+ }
+
protected function getDispatcher($skipCommand = false)
{
$dispatcher = new EventDispatcher();
diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php
index da1c6ab7fd..e1bcea35d2 100644
--- a/src/Symfony/Component/Finder/Finder.php
+++ b/src/Symfony/Component/Finder/Finder.php
@@ -782,6 +782,10 @@ class Finder implements \IteratorAggregate, \Countable
*/
private function normalizeDir(string $dir): string
{
+ if ('/' === $dir) {
+ return $dir;
+ }
+
$dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) {
diff --git a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php
index 3facef58a0..7616b14a24 100644
--- a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php
+++ b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php
@@ -70,7 +70,11 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
}
$subPathname .= $this->getFilename();
- return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
+ if ('/' !== $basePath = $this->rootPath) {
+ $basePath .= $this->directorySeparator;
+ }
+
+ return new SplFileInfo($basePath.$subPathname, $this->subPath, $subPathname);
}
/**
diff --git a/src/Symfony/Component/HttpKernel/Event/ExceptionEvent.php b/src/Symfony/Component/HttpKernel/Event/ExceptionEvent.php
index a10741a84d..a18fbd31f4 100644
--- a/src/Symfony/Component/HttpKernel/Event/ExceptionEvent.php
+++ b/src/Symfony/Component/HttpKernel/Event/ExceptionEvent.php
@@ -21,7 +21,7 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
* current request. The propagation of this event is stopped as soon as a
* response is set.
*
- * You can also call setException() to replace the thrown exception. This
+ * You can also call setThrowable() to replace the thrown exception. This
* exception will be thrown if no response is set during processing of this
* event.
*