<?php
namespace dns\system;
use dns\system\cache\builder\ControllerCacheBuilder;
+use dns\system\route\Request;
+use dns\system\route\Segment;
+use Zend\Router\Http\RouteMatch;
+use Zend\Router\SimpleRouteStack;
/**
* @author Jan Altensen (Stricted)
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @copyright 2013-2015 Jan Altensen (Stricted)
+ * @copyright 2013-2016 Jan Altensen (Stricted)
*/
-class RequestHandler {
- protected $pattern = "";
- protected $routeData = array();
- protected $controllers = array();
+class RequestHandler extends SingletonFactory {
+ protected $router = null;
+ protected $apiModule = false;
/**
- * init RequestHandler
+ * init RequestHandler
*/
- public function __construct ($module = '') {
- $this->pattern = '~/?(?:(?P<controller>[A-Za-z0-9\-]+)(?:/(?P<id>\d+)(?:-(?P<title>[^/]+))?)?)?~x';
- $this->getControllers($module);
+ protected function init () {
+ $this->router = new SimpleRouteStack();
if (DNS::getSession()->username !== null) {
DNS::getTPL()->assign(array("username" => DNS::getSession()->username));
else {
DNS::getTPL()->assign(array("username" => ''));
}
-
- $className = "";
- if (!empty($_SERVER['QUERY_STRING'])) {
- $this->matches($_SERVER['QUERY_STRING']);
- $this->registerRouteData();
- }
- else {
- $className = '\\dns'.(empty($module) ? '' : '\\'.$module).'\\page\\IndexPage';
+ }
+
+ /**
+ * set the default rules
+ *
+ * @param string $module
+ **/
+ public function setRoutes($module='') {
+ if ($module == "api") {
+ $this->apiModule = true;
}
- if (isset($this->routeData['controller']) && !empty($this->routeData['controller'])) {
- $controller = strtolower($this->routeData['controller']);
- if (isset($this->controllers[$controller]) && !empty($this->controllers[$controller])) {
- $className = $this->controllers[$controller];
- }
- else {
- @header('HTTP/1.0 404 Not Found');
- DNS::getTPL()->assign(array("activeMenuItem" => '', "error" => 'The link you are trying to reach is no longer available or invalid.'));
- DNS::getTPL()->display('error.tpl');
- exit;
- }
- }
+ /* load the controllers from cache and build routes */
+ $controllers = ControllerCacheBuilder::getInstance()->getData(array('module' => $module));
+ $routes = [];
- if (!User::isLoggedIn() && $className != '\dns\page\LoginPage' && $className != '\dns\page\ApiPage') {
- DNS::getTPL()->display('login.tpl');
- exit;
+ foreach ($controllers as $name => $data) {
+ $routes[$name] = Segment::factory([ 'route' => '[/]' . $name . '[/][/:id[-:title]]', 'constraints' => [ 'id' => '[0-9]+', 'title' => '[a-zA-Z0-9_.-/]+' ], 'defaults' => [ 'controller' => $data ] ]);
}
- // handle offline mode
- if (defined('OFFLINE') && OFFLINE) {
- $admin = User::isAdmin();
- $available = false;
+ $this->router->setRoutes($routes);
+ }
+
+ /**
+ * @see \Zend\Mvc\Router\SimpleRouteStack::addRoute()
+ *
+ * @param string $name
+ * @param mixed $route
+ */
+ public function addRoute ($name, $route) {
+ $this->router->addRoute($name, $route);
+ }
+
+ /**
+ * @see \Zend\Mvc\Router\SimpleRouteStack::addRoutes()
+ *
+ * @param array|Traversable $routes
+ */
+ public function addRoutes ($routes) {
+ $this->router->addRoutes($routes);
+ }
+
+ /**
+ * Get the added routes
+ *
+ * @return Traversable list of all routes
+ */
+ public function getRoutes() {
+ return $this->router->getRoutes();
+ }
+
+ /**
+ * handle the request
+ */
+ public function handle () {
+ $match = $this->router->match(new Request());
+ if ($match !== null) {
+ $this->registerRouteData($match);
- if (defined($className . '::AVAILABLE_DURING_OFFLINE_MODE') && constant($className . '::AVAILABLE_DURING_OFFLINE_MODE')) {
- $available = true;
- }
+ $className = $match->getParam("controller");
- if (!$admin && !$available) {
- @header('HTTP/1.1 503 Service Unavailable');
- DNS::getTPL()->display('offline.tpl');
+ if (!User::isLoggedIn() && $this->apiModule == false && $className != 'dns\page\LoginPage' && $className != 'dns\page\ApiPage') {
+ DNS::getTPL()->display('login.tpl');
exit;
}
- }
-
- try {
- new $className();
- }
- catch (\Exception $e) {
- if ($e->getCode() == 404) {
- @header('HTTP/1.0 404 Not Found');
- }
- else if ($e->getCode() == 403) {
- @header('HTTP/1.0 403 Forbidden');
+
+ if (defined('OFFLINE') && OFFLINE) {
+ $admin = User::isAdmin();
+ $available = false;
+
+ if (defined($className . '::AVAILABLE_DURING_OFFLINE_MODE') && constant($className . '::AVAILABLE_DURING_OFFLINE_MODE')) {
+ $available = true;
+ }
+
+ if (!$admin && !$available) {
+ @header('HTTP/1.1 503 Service Unavailable');
+ DNS::getTPL()->display('offline.tpl');
+ exit;
+ }
}
- /* show error page */
- DNS::getTPL()->assign(array("activeMenuItem" => '', "error" => $e->getMessage()));
+ try {
+ new $className();
+ }
+ catch (\Exception $e) {
+ if ($e->getCode() == 404) {
+ @header('HTTP/1.0 404 Not Found');
+ }
+ else if ($e->getCode() == 403) {
+ @header('HTTP/1.0 403 Forbidden');
+ }
+
+ // show error page
+ DNS::getTPL()->assign(array("activeMenuItem" => '', "error" => $e->getMessage()));
+ DNS::getTPL()->display('error.tpl');
+ exit;
+ }
+ }
+ else {
+ @header('HTTP/1.0 404 Not Found');
+ DNS::getTPL()->assign(array("activeMenuItem" => '', "error" => 'The link you are trying to reach is no longer available or invalid.'));
DNS::getTPL()->display('error.tpl');
exit;
}
}
-
+
/**
* Registers route data within $_GET and $_REQUEST.
*/
- protected function registerRouteData() {
- foreach ($this->routeData as $key => $value) {
+ protected function registerRouteData(RouteMatch $route) {
+ foreach ($route->getParams() as $key => $value) {
$_GET[$key] = $value;
$_REQUEST[$key] = $value;
}
}
- public function getControllers ($module) {
+ public function getBaseUrl () {
+ $protocol = 'http://';
- $this->controllers = ControllerCacheBuilder::getInstance()->getData(array('module' => $module));
- /*
- $pages = glob(DNS_DIR.'/lib/'.(empty($module) ? '' : $module.'/').'page/*Page.class.php');
-
- foreach ($pages as $page) {
- $page = str_replace('Page.class.php', '', basename($page));
-
- $class = "\\dns".(empty($module) ? '' : "\\".$module)."\\page\\".$page."Page";
- if (class_exists($class) && is_subclass_of($class, '\\dns\\page\\AbstractPage')) {
- $this->controllers[strtolower($page)] = $class;
- }
+ if ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443 || (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) {
+ $protocol = 'https://';
}
- */
+
+ return $protocol . $_SERVER['HTTP_HOST'] . '/';
}
- public function matches($requestURL) {
- if (preg_match($this->pattern, $requestURL, $matches)) {
- foreach ($matches as $key => $value) {
- if (!is_numeric($key)) {
- $this->routeData[$key] = $value;
+ public function getLink (array $params = [], $query = '') {
+ $path_info = true; // TODO: add config constant for that
+
+ $url = $this->getBaseUrl() . 'index.php';
+ if ($path_info) {
+ $url .= '/';
+ }
+ else {
+ $url .= '?';
+ }
+
+ if (!empty($params['controller'])) {
+ $url .= $params['controller'];
+ }
+ else {
+ // TODO: InvalidArgumentException?
+ }
+
+ if (!empty($params['id'])) {
+ if (!empty($params['title'])) {
+ $url .= '/'.$params['id'].'-'.$params['title'];
+ }
+ else {
+ $url .= '/'.$params['id'];
+ }
+ }
+
+ if (!empty($query)) {
+ if ($path_info) {
+ if (strpos($query, '&') === 0) {
+ $query = '/' . substr($query, 1);
+ }
+ else if (strpos($query, '/') !== 0) {
+ $query = '/' . $query;
+ }
+ }
+ else {
+ if (strpos($query, '/') === 0) {
+ $query = '&' . substr($query, 1);
+ }
+ else if (strpos($query, '&') !== 0) {
+ $query = '&' . $query;
}
}
- return true;
+ $url .= $query;
}
- return false;
+ return $url;
}
}