paths($paths); } if($base != null){ $this->base($base); } } public function __get($name){ switch($name){ case 'base': return $this->_base; break; case 'handled': return $this->_handled; break; case 'routes': $routes = []; $base = rtrim($this->_base, '/'); foreach($this->_paths as $path){ if(!isset($routes[$base.$path->path])){ $routes[$base.$path->path] = 0; } $routes[$base.$path->path] += count($path); } foreach($this->_routers as $router){ foreach($router->routes as $route => $count){ if(!isset($routes[$base.$route])){ $routes[$base.$route] = 0; } $routes[$base.$route] += $count; } } return $routes; break; } } public function __clone(){ // No cloning } public function __destruct(){ $this->_paths = []; } public function __toString(){ return "[Router]"; } public function base(string $base){ $this->_base = $base; return $this; } public static function url(string $url){ return preg_replace('/(\/+)/','/',$url); } public function prefix(string $prefix, callable $fn){ $found = false; foreach($this->_routers as $k => $router){ if($router->base == $prefix){ $found = true; $fn($router); break; } } if(!$found){ $router= new Router($prefix); $this->_routers[] = $router; $fn($router); } return $this; } public function path(string $path, callable $fn){ $obj = false; foreach($this->_paths as $k => $p){ if($p->path == $path){ $obj = $p; } } if(!$obj){ $obj = new Path($path); array_push($this->_paths, $obj); } $obj->handle($fn); return $this; } public function get(string $path, callable $fn){ return $this->path($path, function($req, $res, $args) use($fn){ if($req->verb === 'GET'){ return $fn($req, $res, $args); } }); } public function post(string $path, callable $fn){ return $this->path($path, function($req, $res, $args) use($fn){ if($req->verb === 'POST'){ return $fn($req, $res, $args); } }); } public function put(string $path, callable $fn){ return $this->path($path, function($req, $res, $args) use($fn){ if($req->verb === 'PUT'){ return $fn($req, $res, $args); } }); } public function delete(string $path, callable $fn){ return $this->path($path, function($req, $res, $args) use($fn){ if($req->verb === 'DELETE'){ return $fn($req, $res, $args); } }); } public function patch(string $path, callable $fn){ return $this->path($path, function($req, $res, $args) use($fn){ if($req->verb === 'PATCH'){ return $fn($req, $res, $args); } }); } public function paths(array $paths){ foreach($paths as $path => $fn){ $this->path($path, $fn); } return $this; } public function gets(array $paths){ foreach($paths as $path => $fn){ $this->get($path, $fn); } return $this; } public function posts(array $paths){ foreach($paths as $path => $fn){ $this->post($path, $fn); } return $this; } public function puts(array $paths){ foreach($paths as $path => $fn){ $this->put($path, $fn); } return $this; } public function deletes(array $paths){ foreach($paths as $path => $fn){ $this->delete($path, $fn); } return $this; } public function patches(array $paths){ foreach($paths as $path => $fn){ $this->patch($path, $fn); } return $this; } public function clear(){ $this->_paths = []; return $this; } public function handle(string $path, Request $req = null, Response $res = null, callable $fn = null, callable $onerror = null){ if(strpos($path, $this->base) === 0){ $path = substr($path, strlen($this->base)); if(strpos($path, '/') !== 0){ $path = "/{$path}"; } if(is_null($req)){ $req = new Request(Request::get_verb(), Request::get_url(), Request::get_headers(), Request::get_body()); } if(is_null($res)){ $res = new Response(); } if(!in_array($res,$this->responses)){ array_push($this->responses,$res); } $this->fire('handle', $req, $res); $handled = false; foreach($this->_routers as $prefix => $router){ $router->handle($path, $req, $res); $handled = $handled ||$router->handled; } ob_start(); foreach($this->_paths as $k => $p){ if($p->matches($path)){ $handled = true; try{ if($p($req, $res, $p->args($path)) === false){ $handled = false; } }catch(\Exception $e){ if(!is_null($onerror)){ $onerror($req, $res,$e); }else{ throw $e; } } } } $this->_handled = $handled; if(!$handled && !is_null($fn)){ $fn($req, $res); } $res->output .= ob_get_contents(); ob_end_clean(); $this->fire('afterhandle', $req, $res); } return $res; } } ?>