Files
routes/src/BBRouter/RouteCollection.php
T

305 lines
7.2 KiB
PHP
Executable File

<?php
namespace BBRouter;
class RouteCollection{
private static $_route_collection;
public $_uri = '/';
public $_routes = Array();
private $_verb = '';
private $_loaded_files = Array();
private $_errors = Array();
private $_default_middlewares = Array();
private static $_verbs_whitelist = Array('*', 'GET','POST','PUT','PATCH','DELETE', 'CLI');
private static $_verbs_web = Array('GET','POST','PUT','PATCH','DELETE');
//SINGLETON==============================================
private function __construct(){ }
private static function newObj(){
if (!isset(self::$_route_collection)) {
self::$_route_collection = new RouteCollection();
if(php_sapi_name() == "cli"){
self::$_route_collection->_uri = isset( $_SERVER['argv'][1] ) ? '/'. $_SERVER['argv'][1] : '/';
}else{
self::$_route_collection->_uri = isset( $_SERVER['REQUEST_URI'] ) ? explode('&', $_SERVER['REQUEST_URI'])[0] : '/';
}
self::$_route_collection->define_verb();
}
return self::$_route_collection;
}
public static function getInstance(){
if (!isset(self::$_route_collection)) {
return self::newObj();
}
return self::$_route_collection;
}
//HELPERS================================================
/*
* Find route files with names under pathname
*/
public function crawl($basepath = __DIR__, $filenames = Array('Routes.php', 'routes.php') ){
$instance = self::getInstance();
$rdi = new \RecursiveDirectoryIterator($basepath);
foreach(new \RecursiveIteratorIterator($rdi) as $file){
foreach ($filenames as $filename) {
if( strpos($file, $filename) ){
$instance->_loaded_files[] = $file;
}
}
}
return $instance;
}
/*
* Load the files with the routes
*/
function load_routes(){
$instance = self::getInstance();
foreach ($instance->_loaded_files as $loaded_file){
include $loaded_file;
}
return $instance;
}
/*
* GET | POST | PUT | PATCH | DELETE | CLI
*
*/
private function define_verb(){
$verb = '';
if(isset($_POST['_method'])){
$verb = strtoupper( $_POST['_method'] );
}else if(php_sapi_name() == "cli"){
$verb = "CLI";
}else{
$verb = strtoupper( $_SERVER['REQUEST_METHOD'] );
}
if(in_array($verb, self::$_verbs_whitelist)){
$this->_verb = $verb;
}else{
echo 'Invalid Verb';
}
}
/*
*
*/
private function sort_routes(){
usort($this->_routes, function($a, $b){
if ($a->_weight == $b->_weight) {
return 0;
}
return ($a->_weight < $b->_weight) ? -1 : 1;
});
}
/*
* Dispatch routes
*/
function submit(){
global $ROUTE;
self::$_route_collection->sort_routes();
$one_hit = false;
foreach (self::$_route_collection->_routes as $route){
if(!in_array( self::$_route_collection->_verb, $route->_verb) && !in_array( '*', $route->_verb) ){
//No it is not
continue;
}
//Request match a route
$match = $route->match(self::$_route_collection->_uri);
if($match){
//Yup. Execute the route
$ROUTE = $route;
$route->_before = $this->_default_middlewares;
$route->execute();
if(!$route->_ignore){
$one_hit = true;
}
if($route->_http_error){
$this->http_error($route->_http_error);
return;
}
//If Executed, interrupt route chain?
if($route->_block){
return;
}
}
}
if(!$one_hit){
$info = new \stdClass();
$info->code = 404;
$info->message = 'Not Found';
self::$_route_collection->http_error($info);
}
}
//DEFINITORS=============================================
static function get($uri, $callback, $weight = 0){
$route = new Route();
$route->_verb[] = 'GET';
$route->_uri = $uri;
$route->_callback[] = $callback;
$route->_weight = $weight;
$route->prepare();
self::getInstance()->_routes[] = $route;
return $route;
}
static function post($uri, $callback, $weight = 0){
$route = new Route();
$route->_verb[] = 'POST';
$route->_uri = $uri;
$route->_callback[] = $callback;
$route->_weight = $weight;
$route->prepare();
self::getInstance()->_routes[] = $route;
return $route;
}
static function put($uri, $callback, $weight = 0){
$route = new Route();
$route->_verb[] = 'PUT';
$route->_uri = $uri;
$route->_callback[] = $callback;
$route->_weight = $weight;
$route->prepare();
self::getInstance()->_routes[] = $route;
return $route;
}
static function patch($uri, $callback, $weight = 0){
$route = new Route();
$route->_verb[] = 'PATCH';
$route->_uri = $uri;
$route->_callback[] = $callback;
$route->_weight = $weight;
$route->prepare();
self::getInstance()->_routes[] = $route;
return $route;
}
static function delete($uri, $callback, $weight = 0){
$route = new Route();
$route->_verb[] = 'DELETE';
$route->_uri = $uri;
$route->_callback[] = $callback;
$route->_weight = $weight;
$route->prepare();
self::getInstance()->_routes[] = $route;
return $route;
}
static function resource($uri){
throw new Exception('Not implemented');
}
/*
*
*/
static function add($verb, $uri, $callback, $weight = 0){
$route = new Route();
if(is_array( $verb ) ){
$route->_verb = array_map('strtoupper', $verb);
}else if( strtoupper($verb) == 'WEB' ){
$route->_verb[] = self::_verbs_web;
}else{
$route->_verb[] = strtoupper( $verb );
}
$route->_uri = $uri;
$route->_callback[] = $callback;
$route->_weight = $weight;
$route->prepare();
self::getInstance()->_routes[] = $route;
return $route;
}
/*
*
*/
function addRoute(Route $route){
$this->_routes[] = $route;
}
/*
*
*/
static function addMiddleware($name = '', $function){
self::getInstance()->_default_middlewares[$name] = $function;
}
/*
*
*/
static function on_http_error($function){
$instance = self::getInstance();
$instance->_errors[] = $function;
}
/*
*
*/
private function http_error(\stdClass $info){
$info = (array) $info;
foreach ($this->_errors as $error) {
call_user_func_array($error, $info);
}
}
}