Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 37e4e80

Browse filesBrowse files
committed
[FrameworkBundle] Add file links to named controllers in debug:router
1 parent 3987914 commit 37e4e80
Copy full SHA for 37e4e80

File tree

5 files changed

+96
-42
lines changed
Filter options

5 files changed

+96
-42
lines changed

‎src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
5.1.0
55
-----
66

7+
* Added link to source for controllers registered as named services
78
* Added link to source on controller on `router:match`/`debug:router` (when `framework.ide` is configured)
89
* Added `Routing\Loader` and `Routing\Loader\Configurator` namespaces to ease defining routes with default controllers
910
* Added the `framework.router.context` configuration node to configure the `RequestContext`
+56Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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\Bundle\FrameworkBundle\Command;
13+
14+
use Symfony\Component\Config\ConfigCache;
15+
use Symfony\Component\Config\FileLocator;
16+
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
17+
use Symfony\Component\DependencyInjection\ContainerBuilder;
18+
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
19+
20+
/**
21+
* @internal
22+
*
23+
* @author Robin Chalas <robin.chalas@gmail.com>
24+
*/
25+
trait BuildDebugContainerTrait
26+
{
27+
protected $containerBuilder;
28+
29+
/**
30+
* Loads the ContainerBuilder from the cache.
31+
*
32+
* @throws \LogicException
33+
*/
34+
protected function getContainerBuilder(): ContainerBuilder
35+
{
36+
if ($this->containerBuilder) {
37+
return $this->containerBuilder;
38+
}
39+
40+
$kernel = $this->getApplication()->getKernel();
41+
42+
if (!$kernel->isDebug() || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) {
43+
$buildContainer = \Closure::bind(function () { return $this->buildContainer(); }, $kernel, \get_class($kernel));
44+
$container = $buildContainer();
45+
$container->getCompilerPassConfig()->setRemovingPasses([]);
46+
$container->getCompilerPassConfig()->setAfterRemovingPasses([]);
47+
$container->compile();
48+
} else {
49+
(new XmlFileLoader($container = new ContainerBuilder(), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump'));
50+
$locatorPass = new ServiceLocatorTagPass();
51+
$locatorPass->process($container);
52+
}
53+
54+
return $this->containerBuilder = $container;
55+
}
56+
}

‎src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php
+2-37Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,15 @@
1212
namespace Symfony\Bundle\FrameworkBundle\Command;
1313

1414
use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
15-
use Symfony\Component\Config\ConfigCache;
16-
use Symfony\Component\Config\FileLocator;
1715
use Symfony\Component\Console\Command\Command;
1816
use Symfony\Component\Console\Exception\InvalidArgumentException;
1917
use Symfony\Component\Console\Input\InputArgument;
2018
use Symfony\Component\Console\Input\InputInterface;
2119
use Symfony\Component\Console\Input\InputOption;
2220
use Symfony\Component\Console\Output\OutputInterface;
2321
use Symfony\Component\Console\Style\SymfonyStyle;
24-
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
2522
use Symfony\Component\DependencyInjection\ContainerBuilder;
2623
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
27-
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
2824
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
2925

3026
/**
@@ -36,12 +32,9 @@
3632
*/
3733
class ContainerDebugCommand extends Command
3834
{
39-
protected static $defaultName = 'debug:container';
35+
use BuildDebugContainerTrait;
4036

41-
/**
42-
* @var ContainerBuilder|null
43-
*/
44-
protected $containerBuilder;
37+
protected static $defaultName = 'debug:container';
4538

4639
/**
4740
* {@inheritdoc}
@@ -219,34 +212,6 @@ protected function validateInput(InputInterface $input)
219212
}
220213
}
221214

222-
/**
223-
* Loads the ContainerBuilder from the cache.
224-
*
225-
* @throws \LogicException
226-
*/
227-
protected function getContainerBuilder(): ContainerBuilder
228-
{
229-
if ($this->containerBuilder) {
230-
return $this->containerBuilder;
231-
}
232-
233-
$kernel = $this->getApplication()->getKernel();
234-
235-
if (!$kernel->isDebug() || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) {
236-
$buildContainer = \Closure::bind(function () { return $this->buildContainer(); }, $kernel, \get_class($kernel));
237-
$container = $buildContainer();
238-
$container->getCompilerPassConfig()->setRemovingPasses([]);
239-
$container->getCompilerPassConfig()->setAfterRemovingPasses([]);
240-
$container->compile();
241-
} else {
242-
(new XmlFileLoader($container = new ContainerBuilder(), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump'));
243-
$locatorPass = new ServiceLocatorTagPass();
244-
$locatorPass->process($container);
245-
}
246-
247-
return $this->containerBuilder = $container;
248-
}
249-
250215
private function findProperServiceName(InputInterface $input, SymfonyStyle $io, ContainerBuilder $builder, string $name, bool $showHidden): string
251216
{
252217
$name = ltrim($name, '\\');

‎src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\Console\Input\InputOption;
2020
use Symfony\Component\Console\Output\OutputInterface;
2121
use Symfony\Component\Console\Style\SymfonyStyle;
22+
use Symfony\Component\DependencyInjection\ContainerBuilder;
2223
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
2324
use Symfony\Component\Routing\RouteCollection;
2425
use Symfony\Component\Routing\RouterInterface;
@@ -33,6 +34,8 @@
3334
*/
3435
class RouterDebugCommand extends Command
3536
{
37+
use BuildDebugContainerTrait;
38+
3639
protected static $defaultName = 'debug:router';
3740
private $router;
3841
private $fileLinkFormatter;
@@ -79,6 +82,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7982
$name = $input->getArgument('name');
8083
$helper = new DescriptorHelper($this->fileLinkFormatter);
8184
$routes = $this->router->getRouteCollection();
85+
$container = $this->fileLinkFormatter ? function (): ContainerBuilder { return $this->getContainerBuilder(); }
86+
: null;
8287

8388
if ($name) {
8489
if (!($route = $routes->get($name)) && $matchingRoutes = $this->findRouteNameContaining($name, $routes)) {
@@ -96,13 +101,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int
96101
'raw_text' => $input->getOption('raw'),
97102
'name' => $name,
98103
'output' => $io,
104+
'container' => $container,
99105
]);
100106
} else {
101107
$helper->describe($io, $routes, [
102108
'format' => $input->getOption('format'),
103109
'raw_text' => $input->getOption('raw'),
104110
'show_controllers' => $input->getOption('show-controllers'),
105111
'output' => $io,
112+
'container' => $container,
106113
]);
107114
}
108115

‎src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
+30-5Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ protected function describeRouteCollection(RouteCollection $routes, array $optio
6161
$route->getMethods() ? implode('|', $route->getMethods()) : 'ANY',
6262
$route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY',
6363
'' !== $route->getHost() ? $route->getHost() : 'ANY',
64-
$this->formatControllerLink($controller, $route->getPath()),
64+
$this->formatControllerLink($controller, $route->getPath(), $options['container'] ?? null),
6565
];
6666

6767
if ($showControllers) {
68-
$row[] = $controller ? $this->formatControllerLink($controller, $this->formatCallable($controller)) : '';
68+
$row[] = $controller ? $this->formatControllerLink($controller, $this->formatCallable($controller), $options['container'] ?? null) : '';
6969
}
7070

7171
$tableRows[] = $row;
@@ -84,7 +84,7 @@ protected function describeRoute(Route $route, array $options = [])
8484
{
8585
$defaults = $route->getDefaults();
8686
if (isset($defaults['_controller'])) {
87-
$defaults['_controller'] = $this->formatControllerLink($defaults['_controller'], $this->formatCallable($defaults['_controller']));
87+
$defaults['_controller'] = $this->formatControllerLink($defaults['_controller'], $this->formatCallable($defaults['_controller']), $options['container'] ?? null);
8888
}
8989

9090
$tableHeaders = ['Property', 'Value'];
@@ -528,7 +528,7 @@ private function formatRouterConfig(array $config): string
528528
return trim($configAsString);
529529
}
530530

531-
private function formatControllerLink($controller, string $anchorText): string
531+
private function formatControllerLink($controller, string $anchorText, callable $getContainer = null): string
532532
{
533533
if (null === $this->fileLinkFormatter) {
534534
return $anchorText;
@@ -549,7 +549,32 @@ private function formatControllerLink($controller, string $anchorText): string
549549
$r = new \ReflectionFunction($controller);
550550
}
551551
} catch (\ReflectionException $e) {
552-
return $anchorText;
552+
$id = $controller;
553+
$method = '__invoke';
554+
555+
if ($pos = strpos($controller, '::')) {
556+
$id = substr($controller, 0, $pos);
557+
$method = substr($controller, $pos + 2, \strlen($controller));
558+
}
559+
560+
if ($getContainer && ($container = $getContainer()) && $container->has($id)) {
561+
try {
562+
$definition = $container->findDefinition($id);
563+
$factory = $definition->getFactory();
564+
if (($factory[1] ?? null) && !$factory[0] instanceof Definition) {
565+
$r = new \ReflectionMethod($factory[0], $factory[1]);
566+
} elseif (\is_string($factory)) {
567+
$r = new \ReflectionFunction($factory);
568+
} elseif (($class = $definition->getClass()) && method_exists($class, $method)) {
569+
$r = new \ReflectionMethod($class, $method);
570+
}
571+
} catch (\ReflectionException $e) {
572+
}
573+
}
574+
575+
if (!($r ?? null)) {
576+
return $anchorText;
577+
}
553578
}
554579

555580
$fileLink = $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine());

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.