diff --git a/src/Router/Route.php b/src/Router/Route.php index d08d37e..0308249 100755 --- a/src/Router/Route.php +++ b/src/Router/Route.php @@ -12,7 +12,6 @@ use Cube\Http\Response; use Cube\Http\AnonController; use Cube\Http\Model; -use Cube\Interfaces\RequestInterface; use Cube\Misc\ModelCollection; use Cube\Misc\PaginatedModelQueryResult; use Stringable; @@ -289,12 +288,17 @@ public function setEnableCors(bool $cors) * Set attributes found in route path * * @param string $name Attribute field name + * @param string $type Attribute field type * * @return void */ - public function setAttribute($name) + public function setAttribute($name, $type = null) { - $this->_attributes[] = $name; + $this->_attributes[] = (object) array( + 'name' => $name, + 'type' => $type + ); + return $this; } @@ -350,6 +354,12 @@ public function hasOptionalParameter() return $this->_has_optional_parameter; } + /** + * Handle request + * + * @param Request $request + * @return Response + */ public function handle(Request $request) { $embed_request = App::getConfig('view', 'embed_request') ?? false; diff --git a/src/Router/RouteCollection.php b/src/Router/RouteCollection.php index bd0ec8f..78de8ea 100755 --- a/src/Router/RouteCollection.php +++ b/src/Router/RouteCollection.php @@ -38,9 +38,7 @@ class RouteCollection * Class constructor * */ - public function __construct(protected RequestInterface $request) - { - } + public function __construct(protected RequestInterface $request) {} /** * Build all routes @@ -56,7 +54,7 @@ public function build() /** @var Route|null */ $matchedRoute = null; - $routePathAttributes = ''; + $routePathAttributes = []; foreach (static::$_attached_routes as $route) { @@ -87,10 +85,13 @@ public function build() $route_attributes = $route->getAttributes(); if ($routePathAttributes) { - array_walk($route_attributes, function ($attribute, $index) use ($route) { + array_walk($route_attributes, function ($attribute, $index) use ($route, $routePathAttributes) { - $name = $attribute; - $value = $path_attributes[$index] ?? null; + $name = $attribute->name; + $value = RouteParser::attributeCast( + $routePathAttributes[$index], + $attribute->type, + ); if ($route->hasOptionalParameter()) { $value = substr($value, 0, strlen($value) - 1); diff --git a/src/Router/RouteParser.php b/src/Router/RouteParser.php index 820bc33..b80d2d9 100755 --- a/src/Router/RouteParser.php +++ b/src/Router/RouteParser.php @@ -58,15 +58,16 @@ public function __construct(Route $route) */ public function regexp() { - $regexp_path = ''; $rawpath = $this->_route->getPath(); - $path = $this->compileRegularPath($rawpath); $path = $this->compileStrictPathParams($path); - return $this->_addRemoveTrailingSlash($path, $this->_route->hasOptionalParameter()); + return $this->_addRemoveTrailingSlash( + $path, + $this->_route->hasOptionalParameter() + ); } - + /** * Compile regular path conditions * @@ -79,16 +80,18 @@ private function compileRegularPath($path) #check for regular path conditions $regular_path = preg_match_all('#(\{(.*?)\})#', $path, $matches); - - if(!$regular_path) return $path; + + if (!$regular_path) { + return $path; + } $newpath = $path; - foreach($matches[1] as $index => $match) { + foreach ($matches[1] as $index => $match) { #remove brackets $regexps = static::$regex; - $match_without_brackets = str_replace(['{','}'], '', $match); + $match_without_brackets = str_replace(['{', '}'], '', $match); $last_char = substr($match_without_brackets, -1, 1); $is_optional = $last_char === '?'; @@ -96,11 +99,11 @@ private function compileRegularPath($path) $match_vars_count = count($match_vars); $isRegularPath = preg_match('/\:/', $match); - if(!$isRegularPath) { + if (!$isRegularPath) { continue; } - if($match_vars_count < 2 || $match_vars_count > 2) { + if ($match_vars_count < 2 || $match_vars_count > 2) { throw new InvalidArgumentException('Invalid route path for route "' . $path . '"'); } @@ -114,15 +117,15 @@ private function compileRegularPath($path) $is_optional = $last_char === '?'; #Specify attribute's index to route - $this->_route->setAttribute($parameter_name); + $this->_route->setAttribute($parameter_name, $parameter_raw_value); $this->_route->setHasOptionalParameter($is_optional); - if(array_key_exists($parameter_raw_value, $regexps)){ + if (array_key_exists($parameter_raw_value, $regexps)) { $regexp = $is_optional ? static::$regex_opt : $regexps; $parameter_value = $regexp[$parameter_raw_value] ?? null; } - if(!$parameter_value) { + if (!$parameter_value) { $parameter_value = '(' . $parameter_raw_value . ')'; } @@ -144,17 +147,17 @@ private function compileStrictPathParams($path) #check for strict parameters $strict_parameters = preg_match_all('#\{([^\/]+)\}#', $path, $matches); - if(!$strict_parameters) return $path; + if (!$strict_parameters) return $path; $newpath = $path; - foreach($matches[0] as $index => $match) { + foreach ($matches[0] as $index => $match) { $parameter_name = str_replace(['{', '}'], '', $match); $last_char = substr($parameter_name, -1, 1); $is_optional = $last_char === '?'; - if($is_optional) { + if ($is_optional) { $parameter_name = substr($parameter_name, 0, strlen($parameter_name) - 1); } @@ -176,7 +179,7 @@ private function compileStrictPathParams($path) */ private function _addRemoveTrailingSlash($path, $is_optional = false) { - if(!$is_optional) { + if (!$is_optional) { #Enforce trailing slash return (substr($path, -1, 1) === '/') ? $path : $path . '/'; } @@ -184,4 +187,13 @@ private function _addRemoveTrailingSlash($path, $is_optional = false) #Remove trailing slash return (substr($path, -1, 1) === '/') ? substr($path, 0, strlen($path) - 1) : $path; } -} \ No newline at end of file + + public static function attributeCast(string $value, ?string $type = null) + { + return match ($type) { + '*bool' => strtolower($value) === 'true', + '*int' => (int) $value, + default => (string) $value + }; + } +}