[FrameworkBundle] Added option to specify the event dispatcher in debug:event-dispatcher

This commit is contained in:
Timo Bakx 2020-12-01 21:35:43 +01:00 committed by Alexander M. Turek
parent e6eef9b5b7
commit 62398b525e
9 changed files with 51 additions and 12 deletions

View File

@ -5,6 +5,8 @@ CHANGELOG
-----
* Added support for configuring PHP error level to log levels
* Added the `dispatcher` option to `debug:event-dispatcher`
* Added the `event_dispatcher.dispatcher` tag
5.2.0
-----

View File

@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
use Psr\Container\ContainerInterface;
use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
@ -29,14 +30,16 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
*/
class EventDispatcherDebugCommand extends Command
{
protected static $defaultName = 'debug:event-dispatcher';
private $dispatcher;
private const DEFAULT_DISPATCHER = 'event_dispatcher';
public function __construct(EventDispatcherInterface $dispatcher)
protected static $defaultName = 'debug:event-dispatcher';
private $dispatchers;
public function __construct(ContainerInterface $dispatchers)
{
parent::__construct();
$this->dispatcher = $dispatcher;
$this->dispatchers = $dispatchers;
}
/**
@ -47,6 +50,7 @@ class EventDispatcherDebugCommand extends Command
$this
->setDefinition([
new InputArgument('event', InputArgument::OPTIONAL, 'An event name or a part of the event name'),
new InputOption('dispatcher', null, InputOption::VALUE_REQUIRED, 'To view events of a specific event dispatcher', self::DEFAULT_DISPATCHER),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'),
])
@ -74,12 +78,21 @@ EOF
$io = new SymfonyStyle($input, $output);
$options = [];
$dispatcherServiceName = $input->getOption('dispatcher');
if (!$this->dispatchers->has($dispatcherServiceName)) {
$io->getErrorStyle()->error(sprintf('Event dispatcher "%s" is not available.', $dispatcherServiceName));
return 1;
}
$dispatcher = $this->dispatchers->get($dispatcherServiceName);
if ($event = $input->getArgument('event')) {
if ($this->dispatcher->hasListeners($event)) {
if ($dispatcher->hasListeners($event)) {
$options = ['event' => $event];
} else {
// if there is no direct match, try find partial matches
$events = $this->searchForEvent($this->dispatcher, $event);
$events = $this->searchForEvent($dispatcher, $event);
if (0 === \count($events)) {
$io->getErrorStyle()->warning(sprintf('The event "%s" does not have any registered listeners.', $event));
@ -93,10 +106,15 @@ EOF
}
$helper = new DescriptorHelper();
if (self::DEFAULT_DISPATCHER !== $dispatcherServiceName) {
$options['dispatcher_service_name'] = $dispatcherServiceName;
}
$options['format'] = $input->getOption('format');
$options['raw_text'] = $input->getOption('raw');
$options['output'] = $io;
$helper->describe($io, $this->dispatcher, $options);
$helper->describe($io, $dispatcher, $options);
return 0;
}

View File

@ -287,8 +287,14 @@ class MarkdownDescriptor extends Descriptor
protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = [])
{
$event = \array_key_exists('event', $options) ? $options['event'] : null;
$dispatcherServiceName = $options['dispatcher_service_name'] ?? null;
$title = 'Registered listeners';
if (null !== $dispatcherServiceName) {
$title .= sprintf(' of event dispatcher "%s"', $dispatcherServiceName);
}
if (null !== $event) {
$title .= sprintf(' for event `%s` ordered by descending priority', $event);
$registeredListeners = $eventDispatcher->getListeners($event);

View File

@ -474,12 +474,19 @@ class TextDescriptor extends Descriptor
protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = [])
{
$event = \array_key_exists('event', $options) ? $options['event'] : null;
$dispatcherServiceName = $options['dispatcher_service_name'] ?? null;
$title = 'Registered Listeners';
if (null !== $dispatcherServiceName) {
$title .= sprintf(' of Event Dispatcher "%s"', $dispatcherServiceName);
}
if (null !== $event) {
$title = sprintf('Registered Listeners for "%s" Event', $event);
$title .= sprintf(' for "%s" Event', $event);
$registeredListeners = $eventDispatcher->getListeners($event);
} else {
$title = 'Registered Listeners Grouped by Event';
$title .= ' Grouped by Event';
// Try to see if "events" exists
$registeredListeners = \array_key_exists('events', $options) ? array_combine($options['events'], array_map(function ($event) use ($eventDispatcher) { return $eventDispatcher->getListeners($event); }, $options['events'])) : $eventDispatcher->getListeners();
}

View File

@ -43,6 +43,7 @@ class UnusedTagsPass implements CompilerPassInterface
'controller.argument_value_resolver',
'controller.service_arguments',
'data_collector',
'event_dispatcher.dispatcher',
'form.type',
'form.type_extension',
'form.type_guesser',
@ -72,9 +73,9 @@ class UnusedTagsPass implements CompilerPassInterface
'routing.expression_language_provider',
'routing.loader',
'routing.route_loader',
'security.authenticator.login_linker',
'security.expression_language_provider',
'security.remember_me_aware',
'security.authenticator.login_linker',
'security.voter',
'serializer.encoder',
'serializer.normalizer',

View File

@ -160,6 +160,7 @@ use Symfony\Component\Yaml\Yaml;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\CallbackInterface;
use Symfony\Contracts\Cache\TagAwareCacheInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\Service\ResetInterface;
use Symfony\Contracts\Service\ServiceSubscriberInterface;
@ -479,6 +480,8 @@ class FrameworkExtension extends Extension
->addTag('kernel.cache_clearer');
$container->registerForAutoconfiguration(CacheWarmerInterface::class)
->addTag('kernel.cache_warmer');
$container->registerForAutoconfiguration(EventDispatcherInterface::class)
->addTag('event_dispatcher.dispatcher');
$container->registerForAutoconfiguration(EventSubscriberInterface::class)
->addTag('kernel.event_subscriber');
$container->registerForAutoconfiguration(LocaleAwareInterface::class)

View File

@ -129,7 +129,7 @@ return static function (ContainerConfigurator $container) {
->set('console.command.event_dispatcher_debug', EventDispatcherDebugCommand::class)
->args([
service('event_dispatcher'),
tagged_locator('event_dispatcher.dispatcher'),
])
->tag('console.command', ['command' => 'debug:event-dispatcher'])

View File

@ -65,6 +65,7 @@ return static function (ContainerConfigurator $container) {
->set('event_dispatcher', EventDispatcher::class)
->public()
->tag('container.hot_path')
->tag('event_dispatcher.dispatcher')
->alias(EventDispatcherInterfaceComponentAlias::class, 'event_dispatcher')
->alias(EventDispatcherInterface::class, 'event_dispatcher')

View File

@ -358,7 +358,8 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
// Register Firewall-specific event dispatcher
$firewallEventDispatcherId = 'security.event_dispatcher.'.$id;
$container->register($firewallEventDispatcherId, EventDispatcher::class);
$container->register($firewallEventDispatcherId, EventDispatcher::class)
->addTag('event_dispatcher.dispatcher');
// Register listeners
$listeners = [];