Compare commits

...

10 Commits

Author SHA1 Message Date
053d4f30b2 Fix false 405 by removing key in routes array 2023-03-08 15:51:18 -06:00
Sky Johnson
bf6da3b990 Fix processing the basePath, array mismatch issue with tokenize 2021-12-19 13:20:21 -06:00
Skylear
241d652283 🔧 One more namespace fix! 2021-07-22 13:09:33 -05:00
Skylear
6ecb416155 🔧 Fix package for Composer 2021-07-22 12:55:42 -05:00
Skylear
f85ca7666a
Merge pull request #11 from splashsky/fix-overlapping-constraint-bug
🚧 Fix overlap by making constraints route-specific
2021-07-16 13:03:42 -05:00
Skylear
ae61bee272 🚧 Attempt to fix overlap by making constraints route-specific 2021-07-16 12:51:23 -05:00
Skylear
bf56160b33
Merge pull request #10 from splashsky/add-route-group
🌊 Add prefix route group + fixes
2021-07-16 07:53:45 -05:00
Splashsky
227e5edc06 🧼 Clean up request handling by treating basePath similar to other routes 2021-07-16 07:20:58 -05:00
Splashsky
3dd5ddc83e 🧴 Make constraint definitions smoother via trim 2021-07-16 07:17:40 -05:00
Splashsky
d0bef18c59 🧼 Clean up routing behavior with new trim method 2021-07-16 07:14:33 -05:00
2 changed files with 32 additions and 20 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
.DS_Store .DS_Store
._* ._*
/vendor/ /vendor/
/src/Splashsky/test.php /test.php

View File

@ -5,11 +5,11 @@ namespace Splashsky;
class Router class Router
{ {
private static array $routes = []; private static array $routes = [];
private static array $constraints = [];
private static $pathNotFound; private static $pathNotFound;
private static $methodNotAllowed; private static $methodNotAllowed;
private static string $defaultConstraint = '([\w\-]+)'; private static string $defaultConstraint = '([\w\-]+)';
private static string $currentPrefix = ''; private static string $currentPrefix = '';
private static string $lastInsertedRoute = '';
/** /**
* A quick static function to register a route in the router. Used by the shorthand methods as well. * A quick static function to register a route in the router. Used by the shorthand methods as well.
@ -26,12 +26,17 @@ class Router
$route = self::$currentPrefix.$route; $route = self::$currentPrefix.$route;
} }
$trimmed = self::trimRoute($route);
self::$routes[] = [ self::$routes[] = [
'route' => $route, 'route' => $trimmed,
'action' => $action, 'action' => $action,
'methods' => $methods 'methods' => $methods,
'constraints' => []
]; ];
self::$lastInsertedRoute = $trimmed;
return new self; return new self;
} }
@ -102,6 +107,12 @@ class Router
self::$defaultConstraint = $constraint; self::$defaultConstraint = $constraint;
} }
private static function trimRoute(string $route): string
{
$route = trim(trim($route), '/');
return "/$route";
}
/** /**
* Accepts a callable that defines routes, and adds a prefix to them. * Accepts a callable that defines routes, and adds a prefix to them.
* *
@ -130,15 +141,17 @@ class Router
*/ */
public static function with(string|array $parameter, string $constraint = '') public static function with(string|array $parameter, string $constraint = '')
{ {
$last = self::$lastInsertedRoute;
if (is_array($parameter)) { if (is_array($parameter)) {
foreach ($parameter as $param => $constraint) { foreach ($parameter as $param => $constraint) {
self::$constraints[$param] = $constraint; self::$routes[$last]['constraints'][$param] = $constraint;
} }
return new self; return new self;
} }
self::$constraints[$parameter] = $constraint; self::$routes[$last]['constraints'][$parameter] = $constraint;
return new self; return new self;
} }
@ -149,9 +162,9 @@ class Router
* @param string $uri * @param string $uri
* @return string * @return string
*/ */
private static function tokenize(string $uri) private static function tokenize(string $uri, array $constraints)
{ {
$constraints = array_keys(self::$constraints); $constraintKeys = array_keys($constraints);
preg_match_all('/(?:{([\w\-]+)})+/', $uri, $matches); preg_match_all('/(?:{([\w\-]+)})+/', $uri, $matches);
$matches = $matches[1]; $matches = $matches[1];
@ -159,8 +172,11 @@ class Router
foreach ($matches as $match) { foreach ($matches as $match) {
$pattern = '{'.$match.'}'; $pattern = '{'.$match.'}';
if (in_array($match, $constraints)) { if (in_array($match, $constraintKeys)) {
$uri = str_replace($pattern, '('.self::$constraints[$match].')', $uri); // Do some voodoo to allow users to use parentheses in their constraints if they want
$constraint = '('.rtrim(ltrim(trim($constraints[$match]), '('), ')').')';
$uri = str_replace($pattern, $constraint, $uri);
} else { } else {
$uri = str_replace($pattern, self::$defaultConstraint, $uri); $uri = str_replace($pattern, self::$defaultConstraint, $uri);
} }
@ -179,27 +195,23 @@ class Router
*/ */
public static function run(string $basePath = '', bool $multimatch = false) public static function run(string $basePath = '', bool $multimatch = false)
{ {
$basePath = rtrim($basePath, '/'); $basePath = self::trimRoute($basePath);
$method = $_SERVER['REQUEST_METHOD']; $method = $_SERVER['REQUEST_METHOD'];
$uri = parse_url($_SERVER['REQUEST_URI'])['path']; $uri = parse_url($_SERVER['REQUEST_URI'])['path'];
$path = urldecode(rtrim($uri, '/')); $path = urldecode(self::trimRoute($uri));
// If the path is empty (no slash in URI) place one to satisfy the root route ('/')
if (empty($path)) {
$path = '/';
}
$pathMatchFound = false; $pathMatchFound = false;
$routeMatchFound = false; $routeMatchFound = false;
// Begin looking through routes // Begin looking through routes
foreach (self::$routes as $route) { foreach (self::$routes as $route) {
if ($basePath != '' && $basePath != '/') { // If the basePath isn't just "root"
$route['route'] = $basePath.$route['route']; if ($basePath != '/') {
$route['route'] = self::trimRoute($basePath.$route['route']);
} }
// Prepare route by tokenizing. // Prepare route by tokenizing.
$tokenized = '#^'.self::tokenize($route['route']).'$#u'; $tokenized = '#^'.self::tokenize($route['route'], $route['constraints']).'$#u';
// If the tokenized route matches the current path... // If the tokenized route matches the current path...
if (preg_match($tokenized, $path, $matches)) { if (preg_match($tokenized, $path, $matches)) {