Implemented changes requested by FuzeWorks\Application

- Added Priorities to the routes array. Routes can now be saved with priorities, making higher priority routes load before lower priorities
- Fixed bug where callable is not reset upon attempting routing a new route after another was not satisfied
This commit is contained in:
Abel Hoogeveen 2019-03-04 21:33:38 +01:00
parent be414aa2cd
commit f49c5dd882
No known key found for this signature in database
GPG Key ID: 96C2234920BF4292
2 changed files with 76 additions and 63 deletions

View File

@ -156,7 +156,14 @@ class Router
} }
} }
public function addRoute(string $route, $routeConfig = null, bool $prepend = true) /**
* Add a route to the Router
*
* @param string $route
* @param null $routeConfig
* @param int $priority
*/
public function addRoute(string $route, $routeConfig = null, int $priority = Priority::NORMAL)
{ {
// Set defaultCallable if no value provided // Set defaultCallable if no value provided
if (is_null($routeConfig)) if (is_null($routeConfig))
@ -165,23 +172,27 @@ class Router
// Convert wildcards to Regex // Convert wildcards to Regex
$route = str_replace([':any',':num'], ['[^/]+', '[0-9]+'], $route); $route = str_replace([':any',':num'], ['[^/]+', '[0-9]+'], $route);
if ($prepend) if (!isset($this->routes[$priority]))
$this->routes = [$route => $routeConfig] + $this->routes; $this->routes[$priority] = [];
else
$this->routes[$route] = $routeConfig;
Logger::log('Route added at '.($prepend ? 'top' : 'bottom').': "'.$route.'"'); if (!isset($this->routes[$priority][$route]))
$this->routes[$priority][$route] = $routeConfig;
Logger::log('Route added with ' . Priority::getPriority($priority) . ": '" . $route."'");
} }
/** /**
* Removes a route from the array based on the given route. * Removes a route from the array based on the given route.
* *
* @param $route string The route to remove * @param $route string The route to remove
* @param int $priority
*/ */
public function removeRoute(string $route) public function removeRoute(string $route, int $priority = Priority::NORMAL)
{ {
unset($this->routes[$route]); if (!isset($this->routes[$priority][$route]))
return;
unset($this->routes[$priority][$route]);
Logger::log('Route removed: '.$route); Logger::log('Route removed: '.$route);
} }
@ -194,17 +205,22 @@ class Router
*/ */
public function route(string $path) public function route(string $path)
{ {
// Check all the provided custom paths // Check all the provided custom paths, ordered by priority
foreach ($this->routes as $route => $routeConfig) for ($i=Priority::getHighestPriority(); $i<=Priority::getLowestPriority(); $i++) {
if (!isset($this->routes[$i]))
continue;
foreach ($this->routes[$i] as $route => $routeConfig)
{ {
// Match the path against the routes // Match the path against the routes
if (!preg_match('#^'.$route.'$#', $path, $matches)) if (!preg_match('#^'.$route.'$#', $path, $matches))
continue; continue;
// Save the matches // Save the matches
Logger::log('Route matched: '.$route); Logger::log("Route matched: '" . $route . "' with " . Priority::getPriority($i));
$this->matches = $matches; $this->matches = $matches;
$this->route = $route; $this->route = $route;
$this->callable = null;
// Call callable if routeConfig is callable, so routeConfig can be replaced // Call callable if routeConfig is callable, so routeConfig can be replaced
// This is an example of 'Dynamic Rewrite' // This is an example of 'Dynamic Rewrite'
@ -243,6 +259,7 @@ class Router
return $output; return $output;
} }
}
throw new NotFoundException("Could not load view. Router could not find matching route with satisfied callable."); throw new NotFoundException("Could not load view. Router could not find matching route with satisfied callable.");
} }
@ -387,12 +404,13 @@ class Router
/** /**
* Returns an array with all the routes. * Returns an array with all the routes.
* *
* @param int $priority
* @return array * @return array
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function getRoutes(): array public function getRoutes(int $priority = Priority::NORMAL): array
{ {
return $this->routes; return $this->routes[$priority];
} }
/** /**

View File

@ -120,19 +120,14 @@ class RouterTest extends MVCRTestAbstract
$testAppendRouteFunction = [function () { $testAppendRouteFunction = [function () {
}]; }];
$this->router->addRoute('testRoute', $testRouteFunction); $this->router->addRoute('testRoute', $testRouteFunction);
$this->router->addRoute('testAppendRoute', $testAppendRouteFunction, false); $this->router->addRoute('testAppendRoute', $testAppendRouteFunction, Priority::LOW);
// Test if the order is correct // Test if the order is correct
$this->assertSame( // First for Priority::NORMAL
['testRoute' => $testRouteFunction, 'testAppendRoute' => $testAppendRouteFunction], $this->assertSame(['testRoute' => $testRouteFunction], $this->router->getRoutes(Priority::NORMAL));
$this->router->getRoutes()
);
// Test if the order is not incorrect // Then for Priority::LOW
$this->assertNotSame( $this->assertSame(['testAppendRoute' => $testAppendRouteFunction], $this->router->getRoutes(Priority::LOW));
['testAppendRoute' => $testAppendRouteFunction, 'testRoute' => $testRouteFunction],
$this->router->getRoutes()
);
} }
/** /**