ahwelp 7 lat temu
commit
61f90338dd
4 zmienionych plików z 665 dodań i 0 usunięć
  1. 17 0
      composer.json
  2. 133 0
      src/BBRouter/Response.php
  3. 237 0
      src/BBRouter/Route.php
  4. 278 0
      src/BBRouter/RouteCollection.php

+ 17 - 0
composer.json

@@ -0,0 +1,17 @@
+{
+    "name" : "ahwelp/bbrouter",
+    "description" : "Different Routes",
+    "type" : "library",
+    "authors" : [
+        {
+            "name" : "ahwelp",
+            "email" : "ahwelp@ahwelp.com"
+        }
+    ],
+    "autoload" : {
+        "psr-4" : {
+            "BBRouter\\" : "src/BBRouter/"
+        }
+    },
+    "require" : { }
+}

+ 133 - 0
src/BBRouter/Response.php

@@ -0,0 +1,133 @@
+<?php
+namespace BBRouter;
+
+/*
+ *
+ *
+ */
+class Response{
+
+    private static $_response;
+
+    /*
+     *
+     */
+    public $_headers = Array();
+
+    /*
+     *
+     */
+    public $_body = Array();
+
+    /*
+     *
+     */
+    public $_code = 200;
+
+    //SINGLETON==============================================
+
+    private function __construct(){
+    }
+
+    private static function newObj(){
+        if (!isset( self::$_response )) {
+            self::$_response = new Response();
+        }
+        return self::$_response;
+    }
+
+    public function getInstance(){
+        if (!isset(self::$_response)) {
+            return self::newObj();
+        }
+        return self::$_response;
+    }
+
+    //=======================================================
+
+    public static function header($key, $value){
+        $istance = self::getInstance();
+        $istance->_headers[$key] = $value;
+        return $istance;
+    }
+
+    public static function body_prepend($body = null){
+        $instance = self::getInstance();
+        if (null !== $body) {
+            $instance->_body = (string) $body . $instance->_body;
+            return $instance;
+        }
+        return $instance;
+    }
+
+    public static function body($body = null){
+        $instance = self::getInstance();
+        if (null !== $body) {
+            $instance->_body = (string) $body;
+            return $instance;
+        }
+        return $instance;
+    }
+
+    public static function body_append($body = null){
+        $instance = self::getInstance();
+        if (null !== $body) {
+            $instance->_body .= (string) $body;
+            return $instance;
+        }
+        return $instance;
+    }
+
+    private function send_headers(){
+        foreach ($this->_headers as $key => $value) {
+            header($key .': '. $value, false);
+        }
+        return $this;
+    }
+
+    private function send_body(){
+        echo (string) $this->_body;
+        return $this;
+    }
+
+    public static function send(){
+        $instance = self::getInstance();
+        $instance->send_headers();
+        $instance->send_body();
+        return $instance;
+    }
+
+    public static function json($object, $jsonp_prefix = null){
+        $instance = self::getInstance();
+
+        $instance->body('');
+
+        $json = json_encode($object);
+        if (null !== $jsonp_prefix) {
+            // Should ideally be application/json-p once adopted
+            $instance->header('Content-Type', 'text/javascript');
+            $instance->body("$jsonp_prefix($json);");
+        } else {
+            $instance->header('Content-Type', 'application/json');
+            $instance->body($json);
+        }
+        $instance->send();
+        return $instance;
+    }
+
+    public static function redirect($url, $code = 302){
+        $instance = self::getInstance();
+
+        $instance->_code = $code;
+        $instance->header('Location', $url);
+
+        $instance->body('');
+        $instance->send();
+
+        return $instance;
+    }
+
+    function done(){
+        die;
+    }
+}

+ 237 - 0
src/BBRouter/Route.php

@@ -0,0 +1,237 @@
+<?php
+namespace BBRouter;
+
+/*
+ *
+ */
+class Route{
+
+    /*
+     * HTTP VERB
+     */
+    public $_verb = Array();
+    /*
+     * Execution Source
+     * HTTP | Cli | SOAP |
+     */
+    public $_source;
+
+    /*
+     * URI String
+     */
+    public $_uri;
+
+    /*
+     * Routes dispatch priority
+     */
+    public $_weight = 0;
+
+    /*
+     * URI Segments
+     */
+    public $_uri_segments = Array();
+
+    /*
+     * Extracted params
+     */
+    public $_segments = Array();
+
+    /*
+     * Prepared params
+     */
+    public $_params = Array();
+
+    /*
+     * Execute before dispatch route
+     */
+    public $_before = Array();
+
+    /*
+     * Route callback
+     */
+    public $_callback = Array();
+
+    /*
+     * Execute after route dispatched
+     */
+    public $_after = Array();
+
+    /*
+     * Prepared RegEx
+     */
+    public $_regex = '';
+
+    /*
+     * Can execute other route after this one?
+     */
+    public $_block = false;
+
+    /*
+     * Is there a problem witch one?
+     */
+    public $_http_error = false;
+
+    /*
+     * This rout should be counted?
+     */
+    public $_ignore = false;
+
+    /*
+     * From Klein
+     * HTTP status List
+     */
+    protected static $http_messages = array(
+        // Informational 1xx
+        100 => 'Continue',
+        101 => 'Switching Protocols',
+
+        // Successful 2xx
+        200 => 'OK',
+        201 => 'Created',
+        202 => 'Accepted',
+        203 => 'Non-Authoritative Information',
+        204 => 'No Content',
+        205 => 'Reset Content',
+        206 => 'Partial Content',
+
+        // Redirection 3xx
+        300 => 'Multiple Choices',
+        301 => 'Moved Permanently',
+        302 => 'Found',
+        303 => 'See Other',
+        304 => 'Not Modified',
+        305 => 'Use Proxy',
+        306 => '(Unused)',
+        307 => 'Temporary Redirect',
+
+        // Client Error 4xx
+        400 => 'Bad Request',
+        401 => 'Unauthorized',
+        402 => 'Payment Required',
+        403 => 'Forbidden',
+        404 => 'Not Found',
+        405 => 'Method Not Allowed',
+        406 => 'Not Acceptable',
+        407 => 'Proxy Authentication Required',
+        408 => 'Request Timeout',
+        409 => 'Conflict',
+        410 => 'Gone',
+        411 => 'Length Required',
+        412 => 'Precondition Failed',
+        413 => 'Request Entity Too Large',
+        414 => 'Request-URI Too Long',
+        415 => 'Unsupported Media Type',
+        416 => 'Requested Range Not Satisfiable',
+        417 => 'Expectation Failed',
+
+        // Server Error 5xx
+        500 => 'Internal Server Error',
+        501 => 'Not Implemented',
+        502 => 'Bad Gateway',
+        503 => 'Service Unavailable',
+        504 => 'Gateway Timeout',
+        505 => 'HTTP Version Not Supported',
+    );
+
+    //=======================================================
+    function execute(){
+        foreach ($this->_before as $before){
+            call_user_func($before);
+        }
+        foreach ($this->_callback as $callback){
+            call_user_func_array($callback, $this->_params);
+        }
+        foreach ($this->_after as $after){
+            call_user_func($after);
+        }
+    }
+
+    function prepare(){
+        $this->_segments = explode('/', $this->_uri);
+
+        foreach ($this->_segments as $segment){
+            if( strpos($segment, 'i:') > -1 ){
+                $this->_regex .= "\/[0-9]+";
+            }else if( strpos($segment, 'h:') > -1 ){
+                $this->_regex .= "\/[A-z]+";
+            }else if( strpos($segment, ':') > -1 ){
+                $this->_regex .= "\/[A-z0-9]+";
+            }else{
+                $this->_regex .= "\/".$segment;
+            }
+        }
+        $this->_regex = ltrim($this->_regex, '\/');
+        $this->_regex = "/\/" . $this->_regex . "$/";
+    }
+
+    function create_indexes(){
+        foreach ($this->_segments as $key => $segment){
+            if(preg_match('/\[.*?\]$/', $segment)){
+                $segment = trim( trim( $segment, '[' ), ']');
+                $param = explode(':', $segment);
+                $this->_params[ $param[1] ] = $this->_uri_segments[$key];
+            }
+        }
+    }
+
+    function set_uri($uri){
+        $this->_uri = $uri;
+    }
+
+    function get_segments(){
+        return $this->_segments;
+    }
+
+    function do_block(){
+        $this->_block = true;
+        return $this;
+    }
+    function not_block(){
+        $this->_block = false;
+        return $this;
+    }
+
+    function do_ignore(){
+        $this->_ignore = true;
+        return $this;
+    }
+    function not_ignore(){
+        $this->_ignore = false;
+        return $this;
+    }
+    function set_weight($weigth = 0){
+        $this->_weight = $weigth;
+        return $this;
+    }
+
+    function set_http_error($code = 400, $message = null){
+        if($message == null){
+            $message = self::$http_messages[$code];
+        }
+
+        $info = new \stdClass();
+        $info->code = $code;
+        $info->message = $message;
+
+        $this->_http_error = $info;
+        return $this;
+    }
+
+    function match($uri){
+        //Wildcards allways match
+        if(in_array('*', $this->_verb) || $this->_uri == '*'){
+            return true;
+        }
+
+        if( preg_match($this->_regex, $uri) ){
+            $this->_uri_segments = explode('/', $uri);
+            $this->create_indexes();
+            return true;
+        }
+
+        return false;
+    }
+}
+
+
+

+ 278 - 0
src/BBRouter/RouteCollection.php

@@ -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);
+        }
+
+
+    }
+}