commit
0ca0c23cee
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 sheychen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "krutush/krutush",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "sheychen",
|
||||
"email": "contact@clementbois.fr"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Krutush\\": "src/"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace Krutush;
|
||||
|
||||
class App{
|
||||
/**
|
||||
* Current Router
|
||||
* @var Router
|
||||
*/
|
||||
protected $router;
|
||||
|
||||
/**
|
||||
* Get a copy of Router
|
||||
* @return Router
|
||||
*/
|
||||
public function getRouter(): Router{
|
||||
return clone $this->router;
|
||||
}
|
||||
|
||||
/**
|
||||
* Config storage
|
||||
* @var array
|
||||
*/
|
||||
protected $config = array(
|
||||
'namespace' => '',
|
||||
'controller' => 'Controller',
|
||||
'debug' => true
|
||||
);
|
||||
|
||||
/**
|
||||
* Needed config values
|
||||
* @var array
|
||||
*/
|
||||
protected static $configMap = array(
|
||||
'namespace' => true,
|
||||
'controller' => false,
|
||||
'debug' => false
|
||||
);
|
||||
|
||||
public function __construct(array $data = array()){
|
||||
foreach(static::$configMap as $var => $needed){
|
||||
if(isset($data['app'][$var])){
|
||||
$this->config[$var] = $data['app'][$var];
|
||||
}else{
|
||||
if($needed)
|
||||
trigger_error('app.'.$var.' must be define in your app');
|
||||
}
|
||||
}
|
||||
|
||||
//TODO error handler
|
||||
//if($this->config['debug'])
|
||||
|
||||
if(isset($data['path'])){
|
||||
Path::sets($data['path']);
|
||||
}else{
|
||||
trigger_error('path.root must be define in your app');
|
||||
}
|
||||
|
||||
$this->router = new Router(isset($data['router']) ? $data['router'] : Path::get('config').'/Routes.php');
|
||||
}
|
||||
|
||||
public function run($uri = null, array $filters = array()){
|
||||
$route = $this->router->run(($uri ?: $_SERVER['REQUEST_URI']), $filters);
|
||||
|
||||
if(!isset($route))
|
||||
$this->error(new HttpException(404, 'Not Found'));
|
||||
|
||||
try{
|
||||
$route->call($this, $this->config['namespace'], $this->config['controller']);
|
||||
}catch(HttpException $e){
|
||||
if(!$this->config['debug'])
|
||||
$e = new HttpException($e->getHttpCode(), 'Server internal error');
|
||||
$this->error($e);
|
||||
}catch(\Exception $e){
|
||||
$this->error(new HttpException(500, $this->config['debug'] ? $e->getMessage() : 'Server internal error'));
|
||||
}
|
||||
}
|
||||
|
||||
public function error(HttpException $e){
|
||||
http_response_code($e->getHttpCode());
|
||||
echo $e->getMessage();
|
||||
exit;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Krutush;
|
||||
|
||||
class Controller extends NeedApp{}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Krutush;
|
||||
|
||||
class HttpException extends \Exception{
|
||||
private $httpCode;
|
||||
|
||||
public function __construct($httpCode = 500, $message = null){
|
||||
$this->httpCode = $httpCode;
|
||||
parent::__construct($message);
|
||||
}
|
||||
|
||||
public function getHttpCode(){
|
||||
return $this->httpCode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace Krutush;
|
||||
|
||||
class NeedApp{
|
||||
protected $app;
|
||||
|
||||
public function __construct(App $app){ $this->app = $app; }
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
|
||||
namespace Krutush;
|
||||
|
||||
class Path {
|
||||
private static $paths = array();
|
||||
private static $strict = false;
|
||||
|
||||
public static function sets(array $data){
|
||||
foreach($data as $key => $value){
|
||||
static::set($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public static function get(string $key): string{
|
||||
$key = strtoupper($key);
|
||||
switch($key){
|
||||
case 'ROOT':
|
||||
if(isset(static::$paths['ROOT']))
|
||||
return static::$paths['ROOT'];
|
||||
|
||||
case 'WWW':
|
||||
case 'WEB':
|
||||
case 'PUBLIC':
|
||||
if(isset(static::$paths['WWW']))
|
||||
return static::$paths['WWW'];
|
||||
if(static::$strict == false)
|
||||
return static::get('ROOT').'/public';
|
||||
|
||||
case 'SRC':
|
||||
if(isset(static::$paths['SRC']))
|
||||
return static::$paths['SRC'];
|
||||
if(static::$strict == false)
|
||||
return static::get('ROOT').'/src';
|
||||
|
||||
case 'CFG':
|
||||
case 'CONF':
|
||||
case 'CONFIG';
|
||||
if(isset(static::$paths['CFG']))
|
||||
return static::$paths['CFG'];
|
||||
if(static::$strict == false)
|
||||
return static::get('SRC').'/Config';
|
||||
|
||||
case 'TPL':
|
||||
case 'TEMPLATE':
|
||||
if(isset(static::$paths['TPL']))
|
||||
return static::$paths['TPL'];
|
||||
if(static::$strict == false)
|
||||
return static::get('SRC').'/Template';
|
||||
|
||||
case 'TMP':
|
||||
case 'CACHE':
|
||||
if(isset(static::$paths['TPL']))
|
||||
return static::$paths['TPL'];
|
||||
if(static::$strict == false)
|
||||
return static::get('SRC').'/Cache';
|
||||
|
||||
default:
|
||||
trigger_error('Get Unknown key : '.$key);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
public static function isset(string $key): bool{
|
||||
$key = strtoupper($key);
|
||||
switch($key){
|
||||
case 'ROOT':
|
||||
return isset(static::$paths['ROOT']);
|
||||
|
||||
case 'WWW':
|
||||
case 'WEB':
|
||||
case 'PUBLIC':
|
||||
return isset(static::$paths['WWW']) ||
|
||||
(static::$strict == false && static::isset('ROOT'));
|
||||
|
||||
case 'SRC':
|
||||
return isset(static::$paths['SRC']) ||
|
||||
(static::$strict == false && static::isset('ROOT'));
|
||||
|
||||
case 'CFG':
|
||||
case 'CONF':
|
||||
case 'CONFIG';
|
||||
return isset(static::$paths['CFG']) ||
|
||||
(static::$strict == false && static::isset('SRC'));
|
||||
|
||||
case 'TPL':
|
||||
case 'TEMPLATE':
|
||||
return isset(static::$paths['TPL']) ||
|
||||
(static::$strict == false && static::isset('SRC'));
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function set(string $key, string $value): bool{
|
||||
$key = strtoupper($key);
|
||||
switch($key){
|
||||
case 'ROOT':
|
||||
static::$paths['ROOT'] = $value;
|
||||
return true;
|
||||
|
||||
case 'WWW':
|
||||
case 'WEB':
|
||||
case 'PUBLIC':
|
||||
static::$paths['WWW'] = $value;
|
||||
return true;
|
||||
|
||||
case 'SRC':
|
||||
static::$paths['SRC'] = $value;
|
||||
return true;
|
||||
|
||||
case 'CFG':
|
||||
case 'CONF':
|
||||
case 'CONFIG';
|
||||
static::$paths['CFG'] = $value;
|
||||
return true;
|
||||
|
||||
case 'TPL':
|
||||
case 'TEMPLATE':
|
||||
static::$paths['TPL'] = $value;
|
||||
return true;
|
||||
|
||||
default:
|
||||
trigger_error('Set Unknown key : '.$key);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function setStrict(bool $value = true){
|
||||
static::$strict = $value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
<?php
|
||||
|
||||
namespace Krutush;
|
||||
|
||||
/** Based on Grafikart Router */
|
||||
class Route{
|
||||
/**
|
||||
* Url
|
||||
* @var string
|
||||
*/
|
||||
private $path;
|
||||
|
||||
/**
|
||||
* Function to run or 'Controller#function'
|
||||
* @var callable|string
|
||||
*/
|
||||
private $callable;
|
||||
|
||||
/** @var string */
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* string[] Params in url
|
||||
* @var array
|
||||
*/
|
||||
private $matches = array();
|
||||
|
||||
/**
|
||||
* string[] regex Match for params
|
||||
* @var array
|
||||
*/
|
||||
private $params = array();
|
||||
|
||||
/**
|
||||
* Others things
|
||||
* @var array
|
||||
*/
|
||||
private $filters = array();
|
||||
|
||||
/**
|
||||
* Default value of $this->filters
|
||||
* @var array
|
||||
*/
|
||||
private static $defaultFilters = array();
|
||||
|
||||
/**
|
||||
* Register a new Route
|
||||
* @param string $path Url from Root
|
||||
* @param callable|string $callable Function to run or 'Controller#function'
|
||||
*/
|
||||
public function __construct(string $path, $callable){
|
||||
$this->path = trim($path, '/');
|
||||
$this->callable = $callable;
|
||||
$this->filters = static::$defaultFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* My name is [...]
|
||||
* @param string $name
|
||||
* @return Route
|
||||
*/
|
||||
public function name(string $name): Route{
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a filter
|
||||
* @param string $name
|
||||
* @param array $values
|
||||
* @return Route
|
||||
*/
|
||||
public function filter(string $name, array $values): Route{
|
||||
$this->filters[$name] = $values;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Params match regex
|
||||
* @param string $param
|
||||
* @param string $regex
|
||||
* @return Route
|
||||
*/
|
||||
public function with(string $param, string $regex): Route{
|
||||
$this->params[$param] = str_replace('(', '(?:', $regex);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check url
|
||||
* @param string $url
|
||||
* @param array $filters
|
||||
* @return bool
|
||||
*/
|
||||
public function match(string $url, array $filters = array()): bool{
|
||||
//Check filters
|
||||
foreach($filters as $key => $value){
|
||||
if(!isset($this->filters[$key]))
|
||||
return false;
|
||||
|
||||
if(!in_array($value, $this->filters[$key]))
|
||||
return false;
|
||||
}
|
||||
|
||||
//Check url
|
||||
$url = trim($url, '/');
|
||||
$path = preg_replace_callback('#:([\w]+)#', array($this, 'paramMatch'), $this->path);
|
||||
$regex = "#^$path$#i";
|
||||
if(!preg_match($regex, $url, $matches))
|
||||
return false;
|
||||
|
||||
array_shift($matches);
|
||||
$this->matches = $matches;
|
||||
return true;
|
||||
}
|
||||
|
||||
private function paramMatch($match){
|
||||
if(isset($this->params[$match[1]])){
|
||||
return '(' . $this->params[$match[1]] . ')';
|
||||
}
|
||||
return '([^/]+)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Url with params
|
||||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl(array $params = array()): string{
|
||||
$path = $this->path;
|
||||
foreach($params as $k => $v){
|
||||
$path = str_replace(":$k", $v, $path);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check name
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function matchName(string $name): bool{
|
||||
return $this->name == $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run Route
|
||||
* @param App $app
|
||||
* @param string $namespace
|
||||
* @param string $prefix
|
||||
*/
|
||||
public function call(App $app, string $namespace, string $prefix = "Controller"){
|
||||
//is a Controller
|
||||
if(is_string($this->callable)){
|
||||
$params = explode('#', $this->callable);
|
||||
$params[0] = ((isset($namespace) && strpos($params[0], '\\') === false) ? ($namespace.$params[0].$prefix) : $params[0]);
|
||||
if(!class_exists($params[0]))
|
||||
throw new HttpException(404, 'Class Not Found : '.$params[0]);
|
||||
$controller = new $params[0]($app);
|
||||
if(!method_exists($controller,$params[1]))
|
||||
throw new HttpException(404, 'Function Not Found : '.$params[0].'::'.$params[1]);
|
||||
return call_user_func_array(array($controller, $params[1]), $this->matches);
|
||||
} else {
|
||||
return call_user_func_array($this->callable, $this->matches);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default filters
|
||||
* @param array $array
|
||||
* @return void
|
||||
*/
|
||||
public static function filters(array $array = array()){
|
||||
static::$defaultFilters = $array;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace Krutush;
|
||||
|
||||
/**
|
||||
* Load Controller From Url
|
||||
*/
|
||||
class Router{
|
||||
/**
|
||||
* Route[]
|
||||
* @var array
|
||||
*/
|
||||
private $routes = array();
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* Path to a list of routes.
|
||||
* See exemple/src/Config/Routes.php
|
||||
*/
|
||||
public function __construct(string $path = null){
|
||||
if(isset($path)){
|
||||
$r = $this; //4 is too much
|
||||
include($path); //unsafe...
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new Route
|
||||
*
|
||||
* @param string $path Url from Root
|
||||
* @param callable|string $callable Function to run or 'Controller#function'
|
||||
* @return Route
|
||||
*/
|
||||
public function add(string $path, $callable):Route{
|
||||
$route = new Route($path, $callable);
|
||||
$this->routes[] = $route;
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get (first) Route matching url and filters
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $filters
|
||||
* @return Route|null
|
||||
*/
|
||||
public function run(string $url, array $filters):?Route{
|
||||
foreach($this->routes as $route){
|
||||
if($route->match($url, $filters))
|
||||
return $route;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get (first) Route by name
|
||||
*
|
||||
* @param string $name
|
||||
* @return Route|null
|
||||
*/
|
||||
public function get(string $name):?Route{
|
||||
foreach($this->routes as $route){
|
||||
if($route->matchName($name))
|
||||
return $route;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect helper
|
||||
*
|
||||
* @param string $url
|
||||
* @param bool $stop
|
||||
* @return void
|
||||
*/
|
||||
public static function redirect(string $url, bool $stop = true){
|
||||
header('Location: '.$url);
|
||||
if($stop)
|
||||
exit();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue