<?php
namespace Yesf\Http;
use Yesf\Yesf;
use Yesf\Http\Response;
class Router implements RouterInterface {
protected $prefix = '/';
protected $rewrite = [];
protected $regex = [];
protected $router = null;
protected $module = 'index';
public function __construct() {
$this->module = Yesf::app()->getConfig('index', Yesf::CONF_PROJECT);
$this->router = Yesf::app()->getConfig('router', Yesf::CONF_PROJECT);
}
public function setPrefix($prefix = '/') {
$this->prefix = $prefix;
}
public function parseMap(Request $request) {
$res = explode('/', $request->uri, 3);
if (count($res) === 3) {
$request->module = $res[0];
$request->controller = $res[1];
$request->action = $res[2];
} else {
$request->module = $this->module;
$request->controller = $res[0];
$request->action = $res[1];
}
return true;
}
public function parseRewrite(Request $request) {
foreach ($this->rewrite as $rewrite) {
if (preg_match($rewrite['regex'], $request->uri, $matches)) {
$param = [];
unset($matches[0]);
foreach ($rewrite['param'] as $k => $v) {
$param[$v] = $matches[$k + 1];
}
if (count($rewrite['param']) != count($matches)) {
end($matches);
$ext_param = explode('/', current($matches));
foreach ($ext_param as $k => $v) {
if ($k % 2 === 0) {
$param[$v] = $ext_param[$k + 1];
}
}
}
$dispatch = $rewrite['dispatch'];
break;
}
}
if (isset($param)) {
$request->param = $param;
$request->module = isset($dispatch['module']) ? $dispatch['module'] : $this->module;
$request->controller = $dispatch['controller'];
$request->action = $dispatch['action'];
return true;
} else {
return false;
}
}
public function addRewrite($rule, $dispatch) {
$param = [];
$regex = str_replace('/', '\\/', $rule);
$regex = preg_replace_callback('/:([a-zA-Z0-9_]+)/', function($matches) use (&$param) {
$param[] = $matches[1];
return '([^\/]+)';
}, $regex);
if (substr($regex, -1, 1) === '*') {
$regex = preg_replace('/\*$/', '(.*?)', $regex);
}
$regex = '/^' . $regex . '$/';
$this->rewrite[] = [
'regex' => $regex,
'rule' => $rule,
'param' => $param,
'dispatch' => $dispatch
];
}
public function parseRegex(Request $request) {
foreach ($this->regex as $regex) {
if (preg_match($regex['regex'], $request->uri, $matches)) {
$param = [];
unset($matches[0]);
foreach ($matches as $k => $v) {
$param[$regex['param'][$k]] = $v;
}
$dispatch = $regex['dispatch'];
break;
}
}
if (isset($param)) {
$request->param = $param;
$request->module = isset($dispatch['module']) ? $dispatch['module'] : $this->module;
$request->controller = $dispatch['controller'];
$request->action = $dispatch['action'];
return true;
} else {
return false;
}
}
public function addRegex($rule, $dispatch, $param) {
$this->regex[] = [
'regex' => $rule,
'param' => $param,
'dispatch' => $dispatch
];
}
public function parse(Request $request) {
$len = strlen($this->prefix);
$uri = $request->server['request_uri'];
if (strpos('?', $uri) !== false) {
$uri = substr($uri, 0, strpos($uri, '?'));
}
if (strpos($uri, $this->prefix) === 0) {
$uri = substr($uri, $len);
}
if (empty($uri)) {
$request->module = $this->module;
$request->controller = 'index';
$request->action = 'index';
return;
}
$request->uri = $uri;
if (Yesf::app()->getConfig('router.extension', Yesf::CONF_PROJECT)) {
$hasPoint = strrpos($uri, '.');
if ($hasPoint !== false) {
$request->extension = substr($uri, $hasPoint + 1);
$uri = substr($uri, 0, $hasPoint);
}
}
if ($this->parseRegex($request)) {
return;
}
if ($this->parseRewrite($request)) {
return;
}
$this->parseMap($request);
}
}