routes; } /** * @param $middleware string */ public function addMiddleware($middleware) { $this->middleware[] = $middleware; } public function setup() { $routeCollector = new RouteCollector(new Std(), new DataGeneratorGroupCountBased()); foreach ($this->getRoutes() as $route) { $routeCollector->addRoute($route->getMethod(), $route->getUrl(), function() use($route) { $router = static::getInstance(); $router->execute($route); }); } $this->_dispatcher = new DispatcherGroupCountBased($routeCollector->getData()); } public function execute(LuRouteDbo $route) { $reflect = new \ReflectionMethod($route->getControllerClass(), $route->getControllerMethod()); $params = $reflect->getParameters(); $doc = new LuDocParser($reflect->getDocComment()); $doc->parse(); $args = array(); foreach ($params as $param) { try { if ($param->isOptional()) { $value = null; if (LuBusiness::hasParam([$param->getName()])) { $value = $this->getParam($param, LuBusiness::getParam($param->getName())); } else { $value = $param->getDefaultValue(); } $args[$param->getName()] = $value; } else { $args[$param->getName()] = $this->getParam($param, LuBusiness::checkParam($param->getName())); } if (array_key_exists($param->getName(), $doc->getParams())) { foreach ($doc->getParams()[$param->getName()]->getConstraints() as $constraint) { call_user_func_array([$args[$param->getName()], $constraint->getMethod()], $constraint->getArguments()); } } } catch (LuDboConstraintException $e) { $paramName = $param->getName(); LuBusiness::badInput("Invalid value for '${paramName}': " . $e->getMessage()); } } $controller = $route->getControllerClass(); $controllerInstance = new $controller(); $result = call_user_func_array(array($controllerInstance, $route->getControllerMethod()), $args); return LuOutputFormatter::formatSuccess($result); } public function dispatch(string $httpMethod, string $url) { $routeInfo = $this->_dispatcher->dispatch($httpMethod, $url); if ($routeInfo[0] == Dispatcher::NOT_FOUND) { throw new LuBusinessException("Route not found", 404); } else if ($routeInfo[0] == Dispatcher::METHOD_NOT_ALLOWED) { throw new LuBusinessException("Method not allowed", 405); } else { $handler = $routeInfo[1]; $vars = $routeInfo[2]; $handler($vars); } } private function getClassName(\ReflectionParameter $param) { preg_match('/\[\s\<\w+?>\s([\w]+)/s', $param->__toString(), $matches); return isset($matches[1]) ? $matches[1] : null; } private function getParam(\ReflectionParameter $param, $value) { $typedValue = null; $className = $this->getClassName($param); if (is_null($className)) { $typedValue = $value; } else { $class = $param->getClass(); try { $json = json_decode($value, true); if (is_null($json)) { $json = $value . ""; } $typedValue = call_user_func_array(array($class->getName(), "jsonDeserialize"), array($json)); } catch (LuDboDeserializeException $e) { throw $e; } catch (\Exception $e) { LuLog::log($e); LuBusiness::badInput("Unable to parse JSON value for '" . $param->getName() . "'"); } } return $typedValue; } public function addRoute(string $httpMethod, string $url, string $controller, string $method, $permissions = array(), $middlewares = array()) { if (!is_array($permissions)) { $permissions = array($permissions); } if (!is_array($middlewares)) { $middlewares = array($middlewares); } if (strpos($controller, "\\") === false) { $controller = "App\\Controller\\" . $controller . "Controller"; } $route = new LuRouteDbo(); $route->setUrl($url); $route->setControllerClass($controller); $route->setControllerMethod($method); $route->setMiddlewares($middlewares); $route->setPermissions($permissions); $route->setMethod($httpMethod); $this->routes[] = $route; } public function get(string $url, string $controller, string $method, $permissions = array(), $middleware = array()) { $this->addRoute("GET", $url, $controller, $method, $permissions, $middleware); } public function post(string $url, string $controller, string $method, $permissions = array(), $middleware = array()) { $this->addRoute("POST", $url, $controller, $method, $permissions, $middleware); } public function put(string $url, string $controller, string $method, $permissions = array(), $middleware = array()) { $this->addRoute("PUT", $url, $controller, $method, $permissions, $middleware); } public function delete(string $url, string $controller, string $method, $permissions = array(), $middleware = array()) { $this->addRoute("DELETE", $url, $controller, $method, $permissions, $middleware); } }