Browse Source

Don't display duplicate route errors when a route class is missing.

Previously if an application's routes used a route class that didn't
exist, Router::$initialized would not be set, so the error page
rendering would re-load the routes, and if the routes defined *before*
the missing route class were also named routes, a duplicate route error
would be displayed instead of the original error.

By initializing Router we avoid that issue.

Refs #11876
Mark Story 8 years ago
parent
commit
ce147b8f01
2 changed files with 27 additions and 1 deletions
  1. 2 1
      src/Http/BaseApplication.php
  2. 25 0
      tests/TestCase/Http/BaseApplicationTest.php

+ 2 - 1
src/Http/BaseApplication.php

@@ -71,9 +71,10 @@ abstract class BaseApplication implements ConsoleApplicationInterface, HttpAppli
     public function routes($routes)
     {
         if (!Router::$initialized) {
-            require $this->configDir . '/routes.php';
             // Prevent routes from being loaded again
             Router::$initialized = true;
+
+            require $this->configDir . '/routes.php';
         }
     }
 

+ 25 - 0
tests/TestCase/Http/BaseApplicationTest.php

@@ -3,6 +3,7 @@ namespace Cake\Test\TestCase;
 
 use Cake\Http\Response;
 use Cake\Http\ServerRequestFactory;
+use Cake\Routing\Router;
 use Cake\TestSuite\TestCase;
 
 /**
@@ -46,4 +47,28 @@ class BaseApplicationTest extends TestCase
         $this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $result);
         $this->assertEquals('Hello Jane', '' . $result->getBody());
     }
+
+    /**
+     * Ensure that Router::$initialized is toggled even if the routes
+     * file fails. This prevents the routes file from being re-parsed
+     * during the error handling process.
+     *
+     * @return void
+     */
+    public function testRouteHookInitializesRouterOnError()
+    {
+        $app = $this->getMockForAbstractClass(
+            'Cake\Http\BaseApplication',
+            [TEST_APP . 'invalid_routes' . DS]
+        );
+        $builder = Router::createRouteBuilder('/');
+        try {
+            $app->routes($builder);
+
+            $this->fail('invalid_routes/routes.php file should raise an error.');
+        } catch (\InvalidArgumentException $e) {
+            $this->assertTrue(Router::$initialized, 'Should be toggled to prevent duplicate route errors');
+            $this->assertContains('route class', $e->getMessage());
+        }
+    }
 }