From 2da347fb33c999af8feaa0c16db4885091a67500 Mon Sep 17 00:00:00 2001 From: Gawain Lynch Date: Tue, 4 Apr 2017 20:08:18 +0200 Subject: [PATCH 1/6] Rename DebugServiceRegistration to DebugServiceProviders --- src/Nut/DebugServiceProviders.php | 70 ++++++++++++++++++++++++++++ src/Nut/DebugServiceRegistration.php | 58 ----------------------- src/Provider/NutServiceProvider.php | 2 +- 3 files changed, 71 insertions(+), 59 deletions(-) create mode 100644 src/Nut/DebugServiceProviders.php delete mode 100644 src/Nut/DebugServiceRegistration.php diff --git a/src/Nut/DebugServiceProviders.php b/src/Nut/DebugServiceProviders.php new file mode 100644 index 00000000000..262d07acf42 --- /dev/null +++ b/src/Nut/DebugServiceProviders.php @@ -0,0 +1,70 @@ + + */ +class DebugServiceProviders extends BaseCommand +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('debug:service-providers') + ->setAliases(['debug:providers']) + ->setDescription('Service provider registration order debug dumper.') + ->addOption('sort-class', null, InputOption::VALUE_NONE, 'Sort by provider class names.') + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $table = new Table($output); + $rightAligned = new TableStyle(); + $rightAligned->setPadType(STR_PAD_LEFT); + + $table->setHeaders([ + [new TableCell('Service Providers', ['colspan' => 2])], + ['Provider Class Name', 'Order'] + ]); + $table->setColumnStyle(1, $rightAligned); + + $reflect = new \ReflectionProperty(Application::class, 'providers'); + $reflect->setAccessible(true); + $registrations = $reflect->getValue($this->app); + + if ($input->getOption('sort-class')) { + uasort($registrations, function ($a, $b) { + $a = get_class($a); + $b = get_class($b); + if ($a === $b) { + return 0; + } + + return ($a < $b) ? -1 : 1; + }); + } + + foreach ($registrations as $index => $registration) { + $table->addRow([get_class($registration), $index + 1]); + } + + $table->render(); + } +} diff --git a/src/Nut/DebugServiceRegistration.php b/src/Nut/DebugServiceRegistration.php deleted file mode 100644 index e58921f7157..00000000000 --- a/src/Nut/DebugServiceRegistration.php +++ /dev/null @@ -1,58 +0,0 @@ - - */ -class DebugServiceRegistration extends BaseCommand -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setName('debug:services') - ->setDescription('System service provider registration boot order debug dumper.') - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->displayRegistration($output); - } - - /** - * @param OutputInterface $output - */ - private function displayRegistration(OutputInterface $output) - { - $table = new Table($output); - $table->setHeaders([ - '#', - 'Provider', - ]); - - $reflect = new \ReflectionProperty(Application::class, 'providers'); - $reflect->setAccessible(true); - $registrations = $reflect->getValue($this->app); - - $i = 1; - foreach ($registrations as $registration) { - $table->addRow([$i++, get_class($registration)]); - } - - $table->render(); - } -} diff --git a/src/Provider/NutServiceProvider.php b/src/Provider/NutServiceProvider.php index bac04242a28..79ae590285d 100644 --- a/src/Provider/NutServiceProvider.php +++ b/src/Provider/NutServiceProvider.php @@ -61,7 +61,7 @@ function ($app) { new Nut\UserRoleAdd($app), new Nut\UserRoleRemove($app), new Nut\DebugEvents($app), - new Nut\DebugServiceRegistration($app), + new Nut\DebugServiceProviders($app), new Nut\DebugRoutes($app), ]; } From dca3f42b8f9ed41d83809faced7f6c4ab7baa5b1 Mon Sep 17 00:00:00 2001 From: Gawain Lynch Date: Tue, 4 Apr 2017 20:09:19 +0200 Subject: [PATCH 2/6] Add sorting options to DebugEvents --- src/Nut/DebugEvents.php | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/Nut/DebugEvents.php b/src/Nut/DebugEvents.php index 309dc103275..cd4a5d7398d 100644 --- a/src/Nut/DebugEvents.php +++ b/src/Nut/DebugEvents.php @@ -3,7 +3,9 @@ namespace Bolt\Nut; use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** @@ -20,7 +22,8 @@ protected function configure() { $this ->setName('debug:events') - ->setDescription('System events, and target callable debug dumper.') + ->setDescription('Events, and target callable, debug dumper.') + ->addOption('sort-callable', null, InputOption::VALUE_NONE, 'Sort events in order of callable name.') ; } @@ -28,34 +31,34 @@ protected function configure() * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) - { - $this->displayListeners($output); - } - - /** - * Output a table of listeners, and their callbacks. - * - * @param OutputInterface $output - */ - private function displayListeners(OutputInterface $output) { $table = new Table($output); - $table->setHeaders(array( - 'Event Name', - 'Priority', - 'Listener', - )); + $table->setHeaders([ + [new TableCell('Events, and target callable', ['colspan' => 3])], + ['Event Name', 'Priority', 'Callable'], + ]); $dispatcher = $this->app['dispatcher']; $listeners = $dispatcher->getListeners(); foreach ($listeners as $eventName => $eventListeners) { + if ($input->getOption('sort-callable')) { + uasort($eventListeners, function ($a, $b) { + $a = is_array($a) ? get_class($a[0]) : get_class($a); + $b = is_array($b) ? get_class($b[0]) : get_class($b); + if ($a === $b) { + return 0; + } + + return ($a < $b) ? -1 : 1; + }); + } foreach ($eventListeners as $callable) { $priority = $dispatcher->getListenerPriority($eventName, $callable); if (is_array($callable)) { $table->addRow([ $eventName, $priority, - sprintf('%s::%s', get_class($callable[0]), $callable[1]), + sprintf('%s::%s()', get_class($callable[0]), $callable[1]), ]); } else { $table->addRow([$eventName, $priority, get_class($callable)]); From 173d85282e0f48fef73db4f3a5436ff071ac7e6b Mon Sep 17 00:00:00 2001 From: Gawain Lynch Date: Tue, 4 Apr 2017 20:11:52 +0200 Subject: [PATCH 3/6] Rename columns and sorting options in DebugRoutes --- src/Nut/DebugRoutes.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Nut/DebugRoutes.php b/src/Nut/DebugRoutes.php index 23d86c815b0..ad6d24403b2 100644 --- a/src/Nut/DebugRoutes.php +++ b/src/Nut/DebugRoutes.php @@ -4,6 +4,7 @@ use Silex\Route; use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -23,9 +24,9 @@ protected function configure() $this ->setName('debug:routes') ->setDescription('System route debug dumper.') - ->addOption('sort-bind', null, InputOption::VALUE_NONE, 'Sort in order of bind name (default).') + ->addOption('sort-route', null, InputOption::VALUE_NONE, 'Sort in order of route name (default).') ->addOption('sort-pattern', null, InputOption::VALUE_NONE, 'Sort in order of URI patterns.') - ->addOption('sort-methods', null, InputOption::VALUE_NONE, 'Sort in order of HTTP method grouping allowed.') + ->addOption('sort-method', null, InputOption::VALUE_NONE, 'Sort in order of HTTP method grouping allowed.') ; } @@ -36,19 +37,18 @@ protected function execute(InputInterface $input, OutputInterface $output) { $table = new Table($output); $table->setHeaders([ - 'Bind name', - 'Path matching parameter', - 'Method(s)', + [new TableCell('System routes', ['colspan' => 3])], + ['Route Name', 'Path', 'Method(s)'] ]); $routes = (array) $this->app['routes']->getIterator(); - if ($input->getOption('sort-bind')) { - $routes = $this->sortBind($routes); + if ($input->getOption('sort-route')) { + $routes = $this->sortRotues($routes); } if ($input->getOption('sort-pattern')) { $routes = $this->sortPattern($routes); } - if ($input->getOption('sort-methods')) { + if ($input->getOption('sort-method')) { $routes = $this->sortMethods($routes); } @@ -64,13 +64,13 @@ protected function execute(InputInterface $input, OutputInterface $output) } /** - * Sort routes by their binding name. + * Sort routes by their route binding name. * * @param Route[] $routes * * @return Route[] */ - private function sortBind(array $routes) + private function sortRotues(array $routes) { ksort($routes); From 263867448967262131f7cd0eceb94cad917051d2 Mon Sep 17 00:00:00 2001 From: Gawain Lynch Date: Tue, 4 Apr 2017 20:26:10 +0200 Subject: [PATCH 4/6] Naming and phrasing updates --- src/Nut/DebugEvents.php | 14 +++++++++----- src/Nut/DebugRoutes.php | 2 +- src/Nut/DebugServiceProviders.php | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Nut/DebugEvents.php b/src/Nut/DebugEvents.php index cd4a5d7398d..00b5eaaf4d8 100644 --- a/src/Nut/DebugEvents.php +++ b/src/Nut/DebugEvents.php @@ -4,6 +4,7 @@ use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableCell; +use Symfony\Component\Console\Helper\TableStyle; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -22,7 +23,7 @@ protected function configure() { $this ->setName('debug:events') - ->setDescription('Events, and target callable, debug dumper.') + ->setDescription('Dumps event listeners.') ->addOption('sort-callable', null, InputOption::VALUE_NONE, 'Sort events in order of callable name.') ; } @@ -33,10 +34,13 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $table = new Table($output); + $rightAligned = new TableStyle(); + $rightAligned->setPadType(STR_PAD_LEFT); $table->setHeaders([ - [new TableCell('Events, and target callable', ['colspan' => 3])], - ['Event Name', 'Priority', 'Callable'], + [new TableCell('Event names, target callable listeners, and their priority', ['colspan' => 3])], + ['Event Name', 'Callable', 'Priority'], ]); + $table->setColumnStyle(2, $rightAligned); $dispatcher = $this->app['dispatcher']; $listeners = $dispatcher->getListeners(); @@ -57,11 +61,11 @@ protected function execute(InputInterface $input, OutputInterface $output) if (is_array($callable)) { $table->addRow([ $eventName, - $priority, sprintf('%s::%s()', get_class($callable[0]), $callable[1]), + $priority, ]); } else { - $table->addRow([$eventName, $priority, get_class($callable)]); + $table->addRow([$eventName, get_class($callable), $priority]); } } } diff --git a/src/Nut/DebugRoutes.php b/src/Nut/DebugRoutes.php index ad6d24403b2..1dc2a277e6e 100644 --- a/src/Nut/DebugRoutes.php +++ b/src/Nut/DebugRoutes.php @@ -37,7 +37,7 @@ protected function execute(InputInterface $input, OutputInterface $output) { $table = new Table($output); $table->setHeaders([ - [new TableCell('System routes', ['colspan' => 3])], + [new TableCell('Routes', ['colspan' => 3])], ['Route Name', 'Path', 'Method(s)'] ]); $routes = (array) $this->app['routes']->getIterator(); diff --git a/src/Nut/DebugServiceProviders.php b/src/Nut/DebugServiceProviders.php index 262d07acf42..7bcdf4a234a 100644 --- a/src/Nut/DebugServiceProviders.php +++ b/src/Nut/DebugServiceProviders.php @@ -25,7 +25,7 @@ protected function configure() $this ->setName('debug:service-providers') ->setAliases(['debug:providers']) - ->setDescription('Service provider registration order debug dumper.') + ->setDescription('Dumps service providers and their order.') ->addOption('sort-class', null, InputOption::VALUE_NONE, 'Sort by provider class names.') ; } From b79112f0f8998c41ecc82587d8d7943aa3bef4f7 Mon Sep 17 00:00:00 2001 From: Gawain Lynch Date: Thu, 6 Apr 2017 08:55:21 +0200 Subject: [PATCH 5/6] Remove table headers --- src/Nut/DebugEvents.php | 8 +++----- src/Nut/DebugRoutes.php | 2 -- src/Nut/DebugServiceProviders.php | 2 -- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Nut/DebugEvents.php b/src/Nut/DebugEvents.php index 00b5eaaf4d8..f543e3f40bc 100644 --- a/src/Nut/DebugEvents.php +++ b/src/Nut/DebugEvents.php @@ -3,7 +3,6 @@ namespace Bolt\Nut; use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Helper\TableStyle; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -24,7 +23,7 @@ protected function configure() $this ->setName('debug:events') ->setDescription('Dumps event listeners.') - ->addOption('sort-callable', null, InputOption::VALUE_NONE, 'Sort events in order of callable name.') + ->addOption('sort-listener', null, InputOption::VALUE_NONE, 'Sort events in order of callable name.') ; } @@ -37,15 +36,14 @@ protected function execute(InputInterface $input, OutputInterface $output) $rightAligned = new TableStyle(); $rightAligned->setPadType(STR_PAD_LEFT); $table->setHeaders([ - [new TableCell('Event names, target callable listeners, and their priority', ['colspan' => 3])], - ['Event Name', 'Callable', 'Priority'], + ['Event Name', 'Listener', 'Priority'], ]); $table->setColumnStyle(2, $rightAligned); $dispatcher = $this->app['dispatcher']; $listeners = $dispatcher->getListeners(); foreach ($listeners as $eventName => $eventListeners) { - if ($input->getOption('sort-callable')) { + if ($input->getOption('sort-listener')) { uasort($eventListeners, function ($a, $b) { $a = is_array($a) ? get_class($a[0]) : get_class($a); $b = is_array($b) ? get_class($b[0]) : get_class($b); diff --git a/src/Nut/DebugRoutes.php b/src/Nut/DebugRoutes.php index 1dc2a277e6e..4add921bded 100644 --- a/src/Nut/DebugRoutes.php +++ b/src/Nut/DebugRoutes.php @@ -4,7 +4,6 @@ use Silex\Route; use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -37,7 +36,6 @@ protected function execute(InputInterface $input, OutputInterface $output) { $table = new Table($output); $table->setHeaders([ - [new TableCell('Routes', ['colspan' => 3])], ['Route Name', 'Path', 'Method(s)'] ]); $routes = (array) $this->app['routes']->getIterator(); diff --git a/src/Nut/DebugServiceProviders.php b/src/Nut/DebugServiceProviders.php index 7bcdf4a234a..4a847bea126 100644 --- a/src/Nut/DebugServiceProviders.php +++ b/src/Nut/DebugServiceProviders.php @@ -4,7 +4,6 @@ use Silex\Application; use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Helper\TableStyle; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -40,7 +39,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $rightAligned->setPadType(STR_PAD_LEFT); $table->setHeaders([ - [new TableCell('Service Providers', ['colspan' => 2])], ['Provider Class Name', 'Order'] ]); $table->setColumnStyle(1, $rightAligned); From 7d4bb7a99898cc0b4b8db195cd2ded4423724266 Mon Sep 17 00:00:00 2001 From: Gawain Lynch Date: Thu, 6 Apr 2017 13:11:48 +0200 Subject: [PATCH 6/6] [Tests] coverage for Nut debug:* commands --- tests/phpunit/unit/Nut/DebugEventsTest.php | 59 ++++++++++++++ tests/phpunit/unit/Nut/DebugRoutesTest.php | 79 +++++++++++++++++++ .../unit/Nut/DebugServiceProvidersTest.php | 56 +++++++++++++ tests/phpunit/unit/Nut/TableHelperTrait.php | 37 +++++++++ 4 files changed, 231 insertions(+) create mode 100644 tests/phpunit/unit/Nut/DebugEventsTest.php create mode 100644 tests/phpunit/unit/Nut/DebugRoutesTest.php create mode 100644 tests/phpunit/unit/Nut/DebugServiceProvidersTest.php create mode 100644 tests/phpunit/unit/Nut/TableHelperTrait.php diff --git a/tests/phpunit/unit/Nut/DebugEventsTest.php b/tests/phpunit/unit/Nut/DebugEventsTest.php new file mode 100644 index 00000000000..68a80105e72 --- /dev/null +++ b/tests/phpunit/unit/Nut/DebugEventsTest.php @@ -0,0 +1,59 @@ + + */ +class DebugEventsTest extends BoltUnitTest +{ + use TableHelperTrait; + + protected $regexExpectedA = '/(kernel\.request).+(Symfony.Component.HttpKernel.EventListener.RouterListener::onKernelRequest).+(32)/'; + protected $regexExpectedB = '/(Bolt.Routing.Canonical::onRequest).+(31)/'; + + public function testRunNormal() + { + $tester = $this->getCommandTester(); + + $tester->execute([]); + $result = $tester->getDisplay(); + + $this->assertRegExp($this->regexExpectedA, $result); + $this->assertRegExp($this->regexExpectedB, $result); + } + + public function testSortListener() + { + $tester = $this->getCommandTester(); + + $expectedOutput = $this->getNormalOuput(); + $expectedA = $this->getMatchingLineNumber($this->regexExpectedA, $expectedOutput); + $expectedB = $this->getMatchingLineNumber($this->regexExpectedB, $expectedOutput); + $this->assertGreaterThan($expectedA, $expectedB); + + $tester->execute(['--sort-listener' => true]); + $result = $tester->getDisplay(); + + $expectedA = $this->getMatchingLineNumber($this->regexExpectedA, $result); + $expectedB = $this->getMatchingLineNumber($this->regexExpectedB, $result); + $this->assertLessThan($expectedA, $expectedB); + } + + /** + * @return CommandTester + */ + protected function getCommandTester() + { + $app = $this->getApp(); + $command = new DebugEvents($app); + + return new CommandTester($command); + } +} diff --git a/tests/phpunit/unit/Nut/DebugRoutesTest.php b/tests/phpunit/unit/Nut/DebugRoutesTest.php new file mode 100644 index 00000000000..ca97f573050 --- /dev/null +++ b/tests/phpunit/unit/Nut/DebugRoutesTest.php @@ -0,0 +1,79 @@ + + */ +class DebugRoutesTest extends BoltUnitTest +{ + use TableHelperTrait; + + protected $regexExpectedA = '/(preview).+(\/{contenttypeslug}).+(ALL)/'; + protected $regexExpectedB = '/(contentaction).+(\/async\/content\/action).+(POST)/'; + + public function testRunNormal() + { + $tester = $this->getCommandTester(); + + $tester->execute([]); + $result = $tester->getDisplay(); + + $this->assertRegExp($this->regexExpectedA, $result); + $this->assertRegExp($this->regexExpectedB, $result); + + $expectedA = $this->getMatchingLineNumber($this->regexExpectedA, $result); + $expectedB = $this->getMatchingLineNumber($this->regexExpectedB, $result); + $this->assertLessThan($expectedA, $expectedB); + } + + public function testSortRoute() + { + $tester = $this->getCommandTester(); + $tester->execute(['--sort-route' => true]); + $result = $tester->getDisplay(); + + $expectedA = $this->getMatchingLineNumber($this->regexExpectedA, $result); + $expectedB = $this->getMatchingLineNumber($this->regexExpectedB, $result); + $this->assertLessThan($expectedA, $expectedB); + } + + public function testSortPattern() + { + $tester = $this->getCommandTester(); + $tester->execute(['--sort-pattern' => true]); + $result = $tester->getDisplay(); + + $expectedA = $this->getMatchingLineNumber($this->regexExpectedA, $result); + $expectedB = $this->getMatchingLineNumber($this->regexExpectedB, $result); + $this->assertLessThan($expectedA, $expectedB); + } + + public function testSortMethod() + { + $tester = $this->getCommandTester(); + $tester->execute(['--sort-method' => true]); + $result = $tester->getDisplay(); + + $expectedA = $this->getMatchingLineNumber($this->regexExpectedA, $result); + $expectedB = $this->getMatchingLineNumber($this->regexExpectedB, $result); + $this->assertGreaterThan($expectedA, $expectedB); + } + + /** + * @return CommandTester + */ + protected function getCommandTester() + { + $app = $this->getApp(); + $command = new DebugRoutes($app); + + return new CommandTester($command); + } +} diff --git a/tests/phpunit/unit/Nut/DebugServiceProvidersTest.php b/tests/phpunit/unit/Nut/DebugServiceProvidersTest.php new file mode 100644 index 00000000000..3bcbf127d3a --- /dev/null +++ b/tests/phpunit/unit/Nut/DebugServiceProvidersTest.php @@ -0,0 +1,56 @@ + + */ +class DebugServiceProvidersTest extends BoltUnitTest +{ + use TableHelperTrait; + + protected $regexExpectedA = '/(Silex.Provider.DoctrineServiceProvider).+(\d+)/'; + protected $regexExpectedB = '/(Bolt.Provider.AssetServiceProvider).+(\d+)/'; + + public function testRunNormal() + { + $result = $this->getNormalOuput(); + + $this->assertRegExp($this->regexExpectedA, $result); + $this->assertRegExp($this->regexExpectedB, $result); + } + + public function testSortClass() + { + $tester = $this->getCommandTester(); + + $expectedOutput = $this->getNormalOuput(); + $expectedA = $this->getMatchingLineNumber($this->regexExpectedA, $expectedOutput); + $expectedB = $this->getMatchingLineNumber($this->regexExpectedB, $expectedOutput); + $this->assertGreaterThan($expectedA, $expectedB); + + $tester->execute(['--sort-class' => true]); + $result = $tester->getDisplay(); + + $expectedA = $this->getMatchingLineNumber($this->regexExpectedA, $result); + $expectedB = $this->getMatchingLineNumber($this->regexExpectedB, $result); + $this->assertLessThan($expectedA, $expectedB); + } + + /** + * @return CommandTester + */ + protected function getCommandTester() + { + $app = $this->getApp(); + $command = new DebugServiceProviders($app); + + return new CommandTester($command); + } +} diff --git a/tests/phpunit/unit/Nut/TableHelperTrait.php b/tests/phpunit/unit/Nut/TableHelperTrait.php new file mode 100644 index 00000000000..cbab763de3c --- /dev/null +++ b/tests/phpunit/unit/Nut/TableHelperTrait.php @@ -0,0 +1,37 @@ + + */ +trait TableHelperTrait +{ + protected function getNormalOuput() + { + $tester = $this->getCommandTester(); + + $tester->execute([]); + + return $tester->getDisplay(); + } + + protected function getMatchingLineNumber($pattern, $display) + { + if (is_string($display)) { + $display = explode("\n", $display); + } + $linesFound = preg_grep($pattern, $display); + + return key($linesFound); + } + + /** + * @return CommandTester + */ + abstract protected function getCommandTester(); +}