|
|
@@ -0,0 +1,278 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace BBRouter;
|
|
|
+
|
|
|
+class RouteCollection{
|
|
|
+
|
|
|
+ private static $_route_collection;
|
|
|
+
|
|
|
+ public $_uri = '/';
|
|
|
+ public $_routes = Array();
|
|
|
+ private $_verb = '';
|
|
|
+
|
|
|
+ private $_loaded_files = Array();
|
|
|
+
|
|
|
+ private $_errors = Array();
|
|
|
+
|
|
|
+
|
|
|
+ //SINGLETON==============================================
|
|
|
+
|
|
|
+ private function __construct(){ }
|
|
|
+
|
|
|
+ private static function newObj(){
|
|
|
+ if (!isset(self::$_route_collection)) {
|
|
|
+ self::$_route_collection = new RouteCollection();
|
|
|
+ self::$_route_collection->_uri = isset( $_GET['uri'] ) ? '/'. $_GET['uri'] : '/';
|
|
|
+ self::$_route_collection->define_verb();
|
|
|
+ }
|
|
|
+ return self::$_route_collection;
|
|
|
+ }
|
|
|
+
|
|
|
+ public 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
|
|
|
+ *
|
|
|
+ */
|
|
|
+ private function define_verb(){
|
|
|
+
|
|
|
+ $verbs_whitelist = Array('*', 'GET','POST','PUT','PATCH','DELETE', 'CLI');
|
|
|
+ $verb = '';
|
|
|
+
|
|
|
+ if(isset($_POST['_method'])){
|
|
|
+ $verb = $_POST['_method'];
|
|
|
+ }else if(php_sapi_name() == "cli"){
|
|
|
+ $verb = "CLI";
|
|
|
+ }else{
|
|
|
+ $verb = $_SERVER['REQUEST_METHOD'];
|
|
|
+ }
|
|
|
+
|
|
|
+ if(in_array($verb, $verbs_whitelist)){
|
|
|
+ $this->_verb = $verb;
|
|
|
+ }else{
|
|
|
+ echo 'Invalid HTTP 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->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 = $verb;
|
|
|
+ }else{
|
|
|
+ $route->_verb[] = $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 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);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+}
|