From 41df5123497be20155b615e44edbbb08c4f14129 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 16 Oct 2017 20:25:51 -0400 Subject: [PATCH] Adding a new debug:autowiring command --- .../Command/DebugAutowiringCommand.php | 97 +++++++++++++++++++ .../Resources/config/console.xml | 4 + .../Functional/DebugAutowiringCommandTest.php | 63 ++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php new file mode 100644 index 000000000000..23d688495db7 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php @@ -0,0 +1,97 @@ + + * + * 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\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * A console command for autowiring information. + * + * @author Ryan Weaver + * + * @internal + */ +class DebugAutowiringCommand extends ContainerDebugCommand +{ + protected static $defaultName = 'debug:autowiring'; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition(array( + new InputArgument('search', InputArgument::OPTIONAL, 'A search filter'), + )) + ->setDescription('Lists classes/interfaces you can use for autowiring') + ->setHelp(<<<'EOF' +The %command.name% command displays all classes and interfaces that +you can use as type-hints for autowiring: + + php %command.full_name% + +You can also pass a search term to filter the list: + + php %command.full_name% log + +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $io = new SymfonyStyle($input, $output); + $errorIo = $io->getErrorStyle(); + + $builder = $this->getContainerBuilder(); + $serviceIds = $builder->getServiceIds(); + $serviceIds = array_filter($serviceIds, array($this, 'filterToServiceTypes')); + + if ($search = $input->getArgument('search')) { + $serviceIds = array_filter($serviceIds, function ($serviceId) use ($search) { + return false !== stripos($serviceId, $search); + }); + + if (empty($serviceIds)) { + $errorIo->error(sprintf('No autowirable classes or interfaces found matching "%s"', $search)); + + return 1; + } + } + + asort($serviceIds); + + $io->title('Autowirable Services'); + $io->text('The following classes & interfaces can be used as type-hints when autowiring:'); + if ($search) { + $io->text(sprintf('(only showing classes/interfaces matching %s)', $search)); + } + $io->newLine(); + $tableRows = array(); + foreach ($serviceIds as $serviceId) { + $tableRows[] = array(sprintf('%s', $serviceId)); + if ($builder->hasAlias($serviceId)) { + $tableRows[] = array(sprintf(' alias to %s', $builder->getAlias($serviceId))); + } + } + + $io->table(array(), $tableRows); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml index 7dc4ea6d2fba..cebf6014f046 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml @@ -55,6 +55,10 @@ + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php new file mode 100644 index 000000000000..0b7f9290a50b --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; + +use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Component\Console\Tester\ApplicationTester; + +/** + * @group functional + */ +class DebugAutowiringCommandTest extends WebTestCase +{ + public function testBasicFunctionality() + { + static::bootKernel(array('test_case' => 'ContainerDebug', 'root_config' => 'config.yml')); + + $application = new Application(static::$kernel); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'debug:autowiring')); + + $this->assertContains('Symfony\Component\HttpKernel\HttpKernelInterface', $tester->getDisplay()); + $this->assertContains('alias to http_kernel', $tester->getDisplay()); + } + + public function testSearchArgument() + { + static::bootKernel(array('test_case' => 'ContainerDebug', 'root_config' => 'config.yml')); + + $application = new Application(static::$kernel); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'debug:autowiring', 'search' => 'kern')); + + $this->assertContains('Symfony\Component\HttpKernel\HttpKernelInterface', $tester->getDisplay()); + $this->assertNotContains('Symfony\Component\Routing\RouterInterface', $tester->getDisplay()); + } + + public function testSearchNoResults() + { + static::bootKernel(array('test_case' => 'ContainerDebug', 'root_config' => 'config.yml')); + + $application = new Application(static::$kernel); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'debug:autowiring', 'search' => 'foo_fake'), array('capture_stderr_separately' => true)); + + $this->assertContains('No autowirable classes or interfaces found matching "foo_fake"', $tester->getErrorOutput()); + $this->assertEquals(1, $tester->getStatusCode()); + } +}