Skip to content

[FrameworkBundle][Command] print registered event-listeners + event-subscribers #8234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\Command;

use Symfony\Component\Console\Helper\TableHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\Config\FileLocator;

/**
* A console command for retrieving information about events
*
* @author Florian Semm <floriansemm@googlemail.com>
*/
class EventDispatcherDebugCommand extends ContainerAwareCommand
{
protected function configure()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add

/**
 * {@inheritdoc}
 */

{
$this
->setName('event_dispatcher:debug')
->addArgument('event', InputArgument::OPTIONAL, 'Show listeners for a event', '')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for an event

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can leave the '' last argument as it is defaulting to null also

->setDescription('Displays current event-listeners and event-subscribers for an application');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for an application can be left out i think

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

provide a help as all the other commands in the same folder

}

protected function execute(InputInterface $input, OutputInterface $output)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add docblock

{
$containerBuilder = $this->getContainerBuilder();

$listeners = $this->getListeners($containerBuilder);
$listeners = $this->getEventSubscriber($containerBuilder, $listeners);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the name is plural here as indicated above, however i see that it return a misleading $listener variable

i think it would be nicer if we can split the two groups but in the same table, bet it will be fun to do a table divisor 👶 👍
and put first listeners and then subscriber


$event = $input->getArgument('event');
if ($event != '') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be:

if ($input->hasArgument('event')) {
    $event = $input->getArgument('event');

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried it out and it seem to be that the "event" argument is always set but empty

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably because you set default value of argument to '' instead of default null.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have removed the default option '' and set it null

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't see that in the code, i made a note

if (!isset($listeners[$event])) {
throw new \InvalidArgumentException(sprintf('The event %s does not exist', $event));
}

$listeners = $listeners[$event];

$output->writeln(sprintf('<info>[event_dispatcher]</info> Information for event <info>%s</info>', $event));
} else {
ksort($listeners);
$listeners = array_reduce($listeners, function($result, $elements){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leave a space between ) and {

foreach ($elements as $element) {
$result[] = $element;
}

return $result;
});

$output->writeln('<info>[event_dispatcher]</info> Listeners');
}

$table = $this->getHelperSet()->get('table');
$table
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use Symfony\Component\Console\Helper\TableHelper;
// (...)
$table->setLayout(TableHelper::LAYOUT_BORDERLESS);

->setHeaders(array('Class', 'Event'))
->setLayout(TableHelper::LAYOUT_BORDERLESS)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not using default layout?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table should look like the "container:debug" command

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it does not, does it?

I opened #8292 to fix that.

->setRows($listeners)
->render($output);
}

/**
* @param ContainerBuilder $containerBuilder
* @return array
*/
private function getListeners(ContainerBuilder $containerBuilder)
{
$definitions = $containerBuilder->findTaggedServiceIds('kernel.event_listener');

$listeners = array();
foreach ($definitions as $id => $definition) {
$event = $definition[0]['event'];

$class = $containerBuilder->getDefinition($id)->getClass();

$listeners[$event][] = array($class, $event);
}

return $listeners;
}

/**
* @param ContainerBuilder $containerBuilder
* @return array
*/
private function getEventSubscriber(ContainerBuilder $containerBuilder, array $listeners)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this should be getEventSubscribers no?

{
$interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
foreach ($containerBuilder->findTaggedServiceIds('kernel.event_subscriber') as $id => $attributes) {
$class = $containerBuilder->getDefinition($id)->getClass();

$refClass = new \ReflectionClass($class);
if (!$refClass->implementsInterface($interface)) {
continue;
}

$subscribedEvents = $class::getSubscribedEvents();
$events = array_keys($subscribedEvents);

foreach ($events as $event) {
$listeners[$event][] = array($class, $event);
}
}

return $listeners;
}

/**
* Loads the ContainerBuilder from the cache.
*
* @return ContainerBuilder
*/
protected function getContainerBuilder()
{
if (!$this->getApplication()->getKernel()->isDebug()) {
throw new \LogicException(sprintf('Debug information about the EventDispatcher is only available in debug mode.'));
}

if (!is_file($cachedFile = $this->getContainer()->getParameter('debug.container.dump'))) {
throw new \LogicException(sprintf('Debug information about the EventDispatcher could not be found. Please clear the cache and try again.'));
}

$container = new ContainerBuilder();

$loader = new XmlFileLoader($container, new FileLocator());
$loader->load($cachedFile);

return $container;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run php-cs-fixer