Skip to content

Commit 6a89d98

Browse files
Bert ter Heidefabpot
authored andcommitted
[FrameworkBundle] Add "Usages" to debug:container output
1 parent 4a3cf42 commit 6a89d98

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+182
-67
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ CHANGELOG
99
* Deprecate the `Symfony\Component\Serializer\Normalizer\ObjectNormalizer` and
1010
`Symfony\Component\Serializer\Normalizer\PropertyNormalizer` autowiring aliases, type-hint against
1111
`Symfony\Component\Serializer\Normalizer\NormalizerInterface` or implement `NormalizerAwareInterface` instead
12+
* Add service usages list to the `debug:container` command output
1213

1314
6.1
1415
---

Console/Descriptor/Descriptor.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515
use Symfony\Component\Console\Descriptor\DescriptorInterface;
1616
use Symfony\Component\Console\Output\OutputInterface;
1717
use Symfony\Component\DependencyInjection\Alias;
18+
use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
19+
use Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraphEdge;
1820
use Symfony\Component\DependencyInjection\ContainerBuilder;
1921
use Symfony\Component\DependencyInjection\ContainerInterface;
2022
use Symfony\Component\DependencyInjection\Definition;
23+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
2124
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
2225
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
2326
use Symfony\Component\Routing\Route;
@@ -42,6 +45,10 @@ public function describe(OutputInterface $output, mixed $object, array $options
4245
{
4346
$this->output = $output;
4447

48+
if ($object instanceof ContainerBuilder) {
49+
(new AnalyzeServiceReferencesPass(false, false))->process($object);
50+
}
51+
4552
switch (true) {
4653
case $object instanceof RouteCollection:
4754
$this->describeRouteCollection($object, $options);
@@ -85,6 +92,10 @@ public function describe(OutputInterface $output, mixed $object, array $options
8592
default:
8693
throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_debug_type($object)));
8794
}
95+
96+
if ($object instanceof ContainerBuilder) {
97+
$object->getCompiler()->getServiceReferenceGraph()->clear();
98+
}
8899
}
89100

90101
protected function getOutput(): OutputInterface
@@ -125,7 +136,7 @@ abstract protected function describeContainerServices(ContainerBuilder $builder,
125136

126137
abstract protected function describeContainerDeprecations(ContainerBuilder $builder, array $options = []): void;
127138

128-
abstract protected function describeContainerDefinition(Definition $definition, array $options = []);
139+
abstract protected function describeContainerDefinition(Definition $definition, array $options = [], ContainerBuilder $builder = null);
129140

130141
abstract protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null);
131142

@@ -358,4 +369,15 @@ private function getContainerEnvVars(ContainerBuilder $container): array
358369

359370
return array_values($envs);
360371
}
372+
373+
protected function getServiceEdges(ContainerBuilder $builder, string $serviceId): array
374+
{
375+
try {
376+
return array_map(function (ServiceReferenceGraphEdge $edge) {
377+
return $edge->getSourceNode()->getId();
378+
}, $builder->getCompiler()->getServiceReferenceGraph()->getNode($serviceId)->getInEdges());
379+
} catch (InvalidArgumentException $exception) {
380+
return [];
381+
}
382+
}
361383
}

Console/Descriptor/JsonDescriptor.php

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ protected function describeContainerTags(ContainerBuilder $builder, array $optio
6060
foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) {
6161
$data[$tag] = [];
6262
foreach ($definitions as $definition) {
63-
$data[$tag][] = $this->getContainerDefinitionData($definition, true);
63+
$data[$tag][] = $this->getContainerDefinitionData($definition, true, false, $builder, $options['id'] ?? null);
6464
}
6565
}
6666

@@ -76,7 +76,7 @@ protected function describeContainerService(object $service, array $options = []
7676
if ($service instanceof Alias) {
7777
$this->describeContainerAlias($service, $options, $builder);
7878
} elseif ($service instanceof Definition) {
79-
$this->writeData($this->getContainerDefinitionData($service, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments']), $options);
79+
$this->writeData($this->getContainerDefinitionData($service, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'], $builder, $options['id']), $options);
8080
} else {
8181
$this->writeData(\get_class($service), $options);
8282
}
@@ -106,7 +106,7 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
106106
if ($service instanceof Alias) {
107107
$data['aliases'][$serviceId] = $this->getContainerAliasData($service);
108108
} elseif ($service instanceof Definition) {
109-
$data['definitions'][$serviceId] = $this->getContainerDefinitionData($service, $omitTags, $showArguments);
109+
$data['definitions'][$serviceId] = $this->getContainerDefinitionData($service, $omitTags, $showArguments, $builder, $serviceId);
110110
} else {
111111
$data['services'][$serviceId] = \get_class($service);
112112
}
@@ -115,9 +115,9 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
115115
$this->writeData($data, $options);
116116
}
117117

118-
protected function describeContainerDefinition(Definition $definition, array $options = [])
118+
protected function describeContainerDefinition(Definition $definition, array $options = [], ContainerBuilder $builder = null)
119119
{
120-
$this->writeData($this->getContainerDefinitionData($definition, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments']), $options);
120+
$this->writeData($this->getContainerDefinitionData($definition, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'], $builder, $options['id'] ?? null), $options);
121121
}
122122

123123
protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null)
@@ -129,7 +129,7 @@ protected function describeContainerAlias(Alias $alias, array $options = [], Con
129129
}
130130

131131
$this->writeData(
132-
[$this->getContainerAliasData($alias), $this->getContainerDefinitionData($builder->getDefinition((string) $alias), isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'])],
132+
[$this->getContainerAliasData($alias), $this->getContainerDefinitionData($builder->getDefinition((string) $alias), isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'], $builder, (string) $alias)],
133133
array_merge($options, ['id' => (string) $alias])
134134
);
135135
}
@@ -217,7 +217,7 @@ protected function getRouteData(Route $route): array
217217
return $data;
218218
}
219219

220-
private function getContainerDefinitionData(Definition $definition, bool $omitTags = false, bool $showArguments = false): array
220+
private function getContainerDefinitionData(Definition $definition, bool $omitTags = false, bool $showArguments = false, ContainerBuilder $builder = null, string $id = null): array
221221
{
222222
$data = [
223223
'class' => (string) $definition->getClass(),
@@ -235,7 +235,7 @@ private function getContainerDefinitionData(Definition $definition, bool $omitTa
235235
}
236236

237237
if ($showArguments) {
238-
$data['arguments'] = $this->describeValue($definition->getArguments(), $omitTags, $showArguments);
238+
$data['arguments'] = $this->describeValue($definition->getArguments(), $omitTags, $showArguments, $builder, $id);
239239
}
240240

241241
$data['file'] = $definition->getFile();
@@ -272,6 +272,8 @@ private function getContainerDefinitionData(Definition $definition, bool $omitTa
272272
}
273273
}
274274

275+
$data['usages'] = null !== $builder && null !== $id ? $this->getServiceEdges($builder, $id) : [];
276+
275277
return $data;
276278
}
277279

@@ -381,12 +383,12 @@ private function getCallableData(mixed $callable): array
381383
throw new \InvalidArgumentException('Callable is not describable.');
382384
}
383385

384-
private function describeValue(mixed $value, bool $omitTags, bool $showArguments): mixed
386+
private function describeValue($value, bool $omitTags, bool $showArguments, ContainerBuilder $builder = null, string $id = null): mixed
385387
{
386388
if (\is_array($value)) {
387389
$data = [];
388390
foreach ($value as $k => $v) {
389-
$data[$k] = $this->describeValue($v, $omitTags, $showArguments);
391+
$data[$k] = $this->describeValue($v, $omitTags, $showArguments, $builder, $id);
390392
}
391393

392394
return $data;
@@ -408,11 +410,11 @@ private function describeValue(mixed $value, bool $omitTags, bool $showArguments
408410
}
409411

410412
if ($value instanceof ArgumentInterface) {
411-
return $this->describeValue($value->getValues(), $omitTags, $showArguments);
413+
return $this->describeValue($value->getValues(), $omitTags, $showArguments, $builder, $id);
412414
}
413415

414416
if ($value instanceof Definition) {
415-
return $this->getContainerDefinitionData($value, $omitTags, $showArguments);
417+
return $this->getContainerDefinitionData($value, $omitTags, $showArguments, $builder, $id);
416418
}
417419

418420
return $value;

Console/Descriptor/MarkdownDescriptor.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ protected function describeContainerTags(ContainerBuilder $builder, array $optio
8383
$this->write("\n\n".$tag."\n".str_repeat('-', \strlen($tag)));
8484
foreach ($definitions as $serviceId => $definition) {
8585
$this->write("\n\n");
86-
$this->describeContainerDefinition($definition, ['omit_tags' => true, 'id' => $serviceId]);
86+
$this->describeContainerDefinition($definition, ['omit_tags' => true, 'id' => $serviceId], $builder);
8787
}
8888
}
8989
}
@@ -99,7 +99,7 @@ protected function describeContainerService(object $service, array $options = []
9999
if ($service instanceof Alias) {
100100
$this->describeContainerAlias($service, $childOptions, $builder);
101101
} elseif ($service instanceof Definition) {
102-
$this->describeContainerDefinition($service, $childOptions);
102+
$this->describeContainerDefinition($service, $childOptions, $builder);
103103
} else {
104104
$this->write(sprintf('**`%s`:** `%s`', $options['id'], \get_class($service)));
105105
}
@@ -172,7 +172,7 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
172172
$this->write("\n\nDefinitions\n-----------\n");
173173
foreach ($services['definitions'] as $id => $service) {
174174
$this->write("\n");
175-
$this->describeContainerDefinition($service, ['id' => $id, 'show_arguments' => $showArguments]);
175+
$this->describeContainerDefinition($service, ['id' => $id, 'show_arguments' => $showArguments], $builder);
176176
}
177177
}
178178

@@ -193,7 +193,7 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
193193
}
194194
}
195195

196-
protected function describeContainerDefinition(Definition $definition, array $options = [])
196+
protected function describeContainerDefinition(Definition $definition, array $options = [], ContainerBuilder $builder = null)
197197
{
198198
$output = '';
199199

@@ -250,6 +250,9 @@ protected function describeContainerDefinition(Definition $definition, array $op
250250
}
251251
}
252252

253+
$inEdges = null !== $builder && isset($options['id']) ? $this->getServiceEdges($builder, $options['id']) : [];
254+
$output .= "\n".'- Usages: '.($inEdges ? implode(', ', $inEdges) : 'none');
255+
253256
$this->write(isset($options['id']) ? sprintf("### %s\n\n%s\n", $options['id'], $output) : $output);
254257
}
255258

@@ -271,7 +274,7 @@ protected function describeContainerAlias(Alias $alias, array $options = [], Con
271274
}
272275

273276
$this->write("\n");
274-
$this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias]));
277+
$this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias]), $builder);
275278
}
276279

277280
protected function describeContainerParameter(mixed $parameter, array $options = [])

Console/Descriptor/TextDescriptor.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ protected function describeContainerService(object $service, array $options = []
150150
if ($service instanceof Alias) {
151151
$this->describeContainerAlias($service, $options, $builder);
152152
} elseif ($service instanceof Definition) {
153-
$this->describeContainerDefinition($service, $options);
153+
$this->describeContainerDefinition($service, $options, $builder);
154154
} else {
155155
$options['output']->title(sprintf('Information for Service "<info>%s</info>"', $options['id']));
156156
$options['output']->table(
@@ -251,7 +251,7 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
251251
$options['output']->table($tableHeaders, $tableRows);
252252
}
253253

254-
protected function describeContainerDefinition(Definition $definition, array $options = [])
254+
protected function describeContainerDefinition(Definition $definition, array $options = [], ContainerBuilder $builder = null)
255255
{
256256
if (isset($options['id'])) {
257257
$options['output']->title(sprintf('Information for Service "<info>%s</info>"', $options['id']));
@@ -360,6 +360,9 @@ protected function describeContainerDefinition(Definition $definition, array $op
360360
$tableRows[] = ['Arguments', implode("\n", $argumentsInformation)];
361361
}
362362

363+
$inEdges = null !== $builder && isset($options['id']) ? $this->getServiceEdges($builder, $options['id']) : [];
364+
$tableRows[] = ['Usages', $inEdges ? implode(', ', $inEdges) : 'none'];
365+
363366
$options['output']->table($tableHeaders, $tableRows);
364367
}
365368

@@ -401,7 +404,7 @@ protected function describeContainerAlias(Alias $alias, array $options = [], Con
401404
return;
402405
}
403406

404-
$this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias]));
407+
$this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias]), $builder);
405408
}
406409

407410
protected function describeContainerParameter(mixed $parameter, array $options = [])

0 commit comments

Comments
 (0)