diff --git a/library/Respect/Rest/Router.php b/library/Respect/Rest/Router.php index 807900c..bd01fc4 100644 --- a/library/Respect/Rest/Router.php +++ b/library/Respect/Rest/Router.php @@ -174,6 +174,9 @@ public function __call($method, $args) } elseif ($routeTarget instanceof Routable) { return $this->instanceRoute($method, $path, $routeTarget); + } elseif ($routeTarget instanceof Router) { + return $this->instanceSubRouter($method, $path, $routeTarget); + //static returns the argument itself } elseif (!is_string($routeTarget)) { return $this->staticRoute($method, $path, $routeTarget); @@ -479,6 +482,24 @@ public function instanceRoute($method, $path, $instance) return $route; } + + /** + * Creates and returns an router-based route + * + * @param string $method The HTTP metod (GET, POST, etc) + * @param string $path The URI Path (/foo/bar...) + * @param string $intance An instance of Router + * + * @return Respect\Rest\Routes\SubRouter The route created + */ + public function instanceSubRouter($method, $path, $instance) + { + $route = new Routes\SubRouter($method, $path, $instance); + $this->appendRoute($route); + + return $route; + } + /** * Checks if request is a global OPTIONS (OPTIONS * HTTP/1.1) * @@ -756,20 +777,36 @@ protected function sortRoutesByComplexity() function ($a, $b) { $a = $a->pattern; $b = $b->pattern; - $pi = AbstractRoute::PARAM_IDENTIFIER; - - //Compare similarity and ocurrences of "/" - if (Router::compareRoutePatterns($a, $b, '/')) { - return 1; - - //Compare similarity and ocurrences of /* - } elseif (Router::compareRoutePatterns($a, $b, $pi)) { - return -1; - - //Hard fallback for consistency - } else { - return 1; - } + $elementsa = preg_split('#/#', $a, 0, PREG_SPLIT_NO_EMPTY); + $elementsb = preg_split('#/#', $b, 0, PREG_SPLIT_NO_EMPTY); + + if(end($elementsa) == '**' && end($elementsb) == '**') + return count($elementsa) < count($elementsb); + if(end($elementsa) == '**') + return 1; + if(end($elementsb) == '**') + return -1; + + if(count($elementsa) < count($elementsb)){ + return -1; + } + if(count($elementsa) > count($elementsb)){ + return 1; + } + $keysa = array_keys($elementsa, '*'); + $keysb = array_keys($elementsb, '*'); + if(count($keysa) < count($keysb)){ + return -1; + } + if(count($keysa) > count($keysb)){ + return 1; + } + + for($index=0; $index < count($keysa); $index++){ + if($keysa[$index] == $keysb[$index]) + continue; + return $keysa[$index]<$keysb[$index]; + } } ); } diff --git a/library/Respect/Rest/Routes/SubRouter.php b/library/Respect/Rest/Routes/SubRouter.php new file mode 100644 index 0000000..3c86bc1 --- /dev/null +++ b/library/Respect/Rest/Routes/SubRouter.php @@ -0,0 +1,60 @@ +instance = $instance; + parent::__construct($method, $pattern); + } + + public function getReflection($method) + { + if (empty($this->reflection)) { + $this->reflection = new ReflectionMethod( + $this, + 'runTarget' + ); + } + + return $this->reflection; + } + + public function match(Request $request, &$params = array()){ + #Store the request + $this->uri = $request->uri; + $params=array(); + if(preg_match("#^".$this->pattern."#", $request->uri)){ + $this->uri = preg_replace("#^".$this->pattern."#", '', $this->uri); + return true; + } + return false; + } + + public function runTarget($method, &$params) + { + if (!$this->instance instanceof Router) { + throw new InvalidArgumentException('Route target must be an instance of Respect\Rest\Router'); + } + + return (string)$this->instance->run(new Request($method, $this->uri)); + } +}