Browse Source

show route collision in routes command

Kevin Pfeifer 4 years ago
parent
commit
12bf3db07f
2 changed files with 77 additions and 1 deletions
  1. 33 1
      src/Command/RoutesCommand.php
  2. 44 0
      tests/TestCase/Command/RoutesCommandTest.php

+ 33 - 1
src/Command/RoutesCommand.php

@@ -40,7 +40,7 @@ class RoutesCommand extends Command
             $header[] = 'Defaults';
         }
 
-        $output = [];
+        $output = $duplicateRoutesCounter = [];
 
         foreach (Router::routes() as $route) {
             $methods = $route->defaults['_method'] ?? '';
@@ -61,6 +61,12 @@ class RoutesCommand extends Command
             }
 
             $output[] = $item;
+
+            // Count route templates
+            if (!array_key_exists($route->template, $duplicateRoutesCounter)) {
+                $duplicateRoutesCounter[$route->template] = 0;
+            }
+            $duplicateRoutesCounter[$route->template]++;
         }
 
         if ($args->getOption('sort')) {
@@ -74,6 +80,32 @@ class RoutesCommand extends Command
         $io->helper('table')->output($output);
         $io->out();
 
+        $duplicateRoutes = [];
+
+        // Check duplicate routes
+        foreach (Router::routes() as $route) {
+            if ($duplicateRoutesCounter[$route->template] > 1) {
+                $methods = $route->defaults['_method'] ?? '';
+
+                $duplicateRoutes[] = [
+                    $route->options['_name'] ?? $route->getName(),
+                    $route->template,
+                    $route->defaults['plugin'] ?? '',
+                    $route->defaults['prefix'] ?? '',
+                    $route->defaults['controller'] ?? '',
+                    $route->defaults['action'] ?? '',
+                    is_string($methods) ? $methods : implode(', ', $route->defaults['_method']),
+                ];
+            }
+        }
+
+        if (!empty($duplicateRoutes)) {
+            array_unshift($duplicateRoutes, $header);
+            $io->warning('The following route collisions were being detected');
+            $io->helper('table')->output($duplicateRoutes);
+            $io->out();
+        }
+
         return static::CODE_SUCCESS;
     }
 

+ 44 - 0
tests/TestCase/Command/RoutesCommandTest.php

@@ -285,4 +285,48 @@ class RoutesCommandTest extends TestCase
         $this->assertExitCode(Command::CODE_ERROR);
         $this->assertErrorContains('do not match');
     }
+
+    /**
+     * Test routes duplicate warning
+     */
+    public function testRouteDuplicateWarning(): void
+    {
+        $builder = Router::createRouteBuilder('/');
+        $builder->connect(
+            new Route('/unique-path', [], ['_name' => '_aRoute'])
+        );
+        $builder->connect(
+            new Route('/unique-path', [], ['_name' => '_bRoute'])
+        );
+
+        $this->exec('routes');
+        $this->assertExitCode(Command::CODE_SUCCESS);
+        $this->assertOutputContainsRow([
+            '<info>Route name</info>',
+            '<info>URI template</info>',
+            '<info>Plugin</info>',
+            '<info>Prefix</info>',
+            '<info>Controller</info>',
+            '<info>Action</info>',
+            '<info>Method(s)</info>',
+        ]);
+        $this->assertOutputContainsRow([
+            '_aRoute',
+            '/unique-path',
+            '',
+            '',
+            '',
+            '',
+            '',
+        ]);
+        $this->assertOutputContainsRow([
+            '_bRoute',
+            '/unique-path',
+            '',
+            '',
+            '',
+            '',
+            '',
+        ]);
+    }
 }