diff --git a/src/App.php b/src/App.php index 300f1b01..afb88192 100755 --- a/src/App.php +++ b/src/App.php @@ -298,6 +298,29 @@ public static function setMode(string $value): void self::$mode = $value; } + /** + * Get allow override + * + * + * @return bool + */ + public static function getAllowOverride(): bool + { + return Router::getAllowOverride(); + } + + /** + * Set Allow override + * + * + * @param bool $value + * @return void + */ + public static function setAllowOverride(bool $value): void + { + Router::setAllowOverride($value); + } + /** * If a resource has been created return it, otherwise create it and then return it * diff --git a/src/Router.php b/src/Router.php index d759a293..a2ad9b99 100644 --- a/src/Router.php +++ b/src/Router.php @@ -12,6 +12,8 @@ class Router public const PLACEHOLDER_TOKEN = ':::'; public const WILDCARD_TOKEN = '*'; + protected static bool $allowOverride = false; + /** * @var array */ @@ -40,6 +42,30 @@ public static function getRoutes(): array return self::$routes; } + /** + * Get allow override + * + * + * @return bool + */ + public static function getAllowOverride(): bool + { + return self::$allowOverride; + } + + /** + * Set Allow override + * + * + * @param bool $value + * @return void + */ + public static function setAllowOverride(bool $value): void + { + self::$allowOverride = $value; + } + + /** * Add route to router. * @@ -55,7 +81,7 @@ public static function addRoute(Route $route): void throw new Exception("Method ({$route->getMethod()}) not supported."); } - if (array_key_exists($path, self::$routes[$route->getMethod()])) { + if (array_key_exists($path, self::$routes[$route->getMethod()]) && !self::$allowOverride) { throw new Exception("Route for ({$route->getMethod()}:{$path}) already registered."); } @@ -77,7 +103,7 @@ public static function addRouteAlias(string $path, Route $route): void { [$alias] = self::preparePath($path); - if (array_key_exists($alias, self::$routes[$route->getMethod()])) { + if (array_key_exists($alias, self::$routes[$route->getMethod()]) && !self::$allowOverride) { throw new Exception("Route for ({$route->getMethod()}:{$alias}) already registered."); } diff --git a/tests/AppTest.php b/tests/AppTest.php index d3952185..a5fe1a27 100755 --- a/tests/AppTest.php +++ b/tests/AppTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\TestCase; use Utopia\Tests\UtopiaRequestTest; use Utopia\Validator\Text; +use Exception; class AppTest extends TestCase { @@ -315,6 +316,36 @@ public function testCanAddAndExecuteHooks() $this->assertEquals('x-def', $result); } + public function testAllowRouteOverrides() + { + App::setAllowOverride(false); + $this->assertFalse(App::getAllowOverride()); + App::get('/')->action(function () { + echo 'Hello first'; + }); + + try { + App::get('/')->action(function () { + echo 'Hello second'; + }); + $this->fail('Failed to throw exception'); + } catch (Exception $e) { + // Threw exception as expected + $this->assertEquals('Route for (GET:) already registered.', $e->getMessage()); + } + + // Test success + App::setAllowOverride(true); + $this->assertTrue(App::getAllowOverride()); + App::get('/')->action(function () { + echo 'Hello first'; + }); + + App::get('/')->action(function () { + echo 'Hello second'; + }); + } + public function testCanHookThrowExceptions() { $this->app