From 30dcb113ae1276c734ab3c4fa56b4ed445527201 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 7 Nov 2017 21:48:38 -0500 Subject: [PATCH] Modify link to handle servers with odd configurations --- api/Link.php | 384 ++++++++++++++++++++++++++------------------------- 1 file changed, 197 insertions(+), 187 deletions(-) diff --git a/api/Link.php b/api/Link.php index dff9c7cf..5a9ad7cd 100644 --- a/api/Link.php +++ b/api/Link.php @@ -4,118 +4,128 @@ require_once 'RequestMethod.php'; /** * @class Main class of the Link router that helps you create and deploy routes - */ -class Link + */ +class Link { - /** - * @var array A collection of the routes originally passed into all function. Used by static function route - */ - private static $routes = array(); + /** + * @var array A collection of the routes originally passed into all function. Used by static function route + */ + private static $routes = array(); - /** - * @var array A collection of functions that are executed before a route completion ( valid for all routes ), aka universal before functions - */ - private static $beforeFuncs = array(); + /** + * @var array A collection of functions that are executed before a route completion ( valid for all routes ), aka universal before functions + */ + private static $beforeFuncs = array(); - /** - * @var array A collection of function that are executed after a route completion ( valid for all routes ), aka universal after functions - */ - private static $afterFuncs = array(); + /** + * @var array A collection of function that are executed after a route completion ( valid for all routes ), aka universal after functions + */ + private static $afterFuncs = array(); - /** - * Static function of the class Link that deploys the route according to the passed handler and path - * - * @param array $routes An array of combination of the path and its handler, that are final deployed for a particular url - */ - public static function all( $routes ) - { + /** + * Static function of the class Link that deploys the route according to the passed handler and path + * + * @param array $routes An array of combination of the path and its handler, that are final deployed for a particular url + */ + public static function all( $routes ) + { - /* Call all functions that are to be executed before routing */ - foreach( self::$beforeFuncs as $beforeFunc ) { - if( $beforeFunc[1] ) { - call_user_func_array( $beforeFunc[0] , $beforeFunc[1] ); - } else { - call_user_func( $beforeFunc[0] ); - } - } + /* Call all functions that are to be executed before routing */ + foreach( self::$beforeFuncs as $beforeFunc ) { + if( $beforeFunc[1] ) { + call_user_func_array( $beforeFunc[0] , $beforeFunc[1] ); + } else { + call_user_func( $beforeFunc[0] ); + } + } - self::$routes = $routes; - $method = self::getRequestMethod(); - $acceptedMethods = RequestMethod::all(); - $path = '/'; - $handler = null; - $matched = array(); - $middleware = null; - if ( !empty ( $_SERVER['PATH_INFO'] ) ) { - $path = $_SERVER['PATH_INFO']; - } else if ( !empty ( $_SERVER['REQUEST_URI'] ) ) { - $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); - } + self::$routes = $routes; + $method = self::getRequestMethod(); + $acceptedMethods = RequestMethod::all(); + $path = '/'; + $handler = null; + $matched = array(); + $middleware = null; + if ( !empty ( $_SERVER['PATH_INFO'] ) ) { + $path = $_SERVER['PATH_INFO']; + } else if ( !empty ( $_SERVER['REQUEST_URI'] ) ) { + $parts = explode('/', $_SERVER['REQUEST_URI']); + $startingIndex = -1; + for ($i = count($parts) - 1; $i > -1 && $startingIndex === -1; $i--) { + if ($parts[$i] === 'index.php' || $parts[$i] === 'api') { + $startingIndex = $i + 1; + } + } + $path = ''; + for ($i = $startingIndex; $i < count($parts); $i++) { + $path .= "/{$parts[$i]}"; + } + } - if ( isset($routes[$path] ) ) { - if( is_array( $routes[$path] ) ) { - $handler = $routes[$path][0]; - $middleware = $routes[$path][2]; - $acceptedMethods = $routes[$path][3]; - } else { - $handler = $routes[$path]; - } - } else if ( $routes ) { - - $regex = array( - '/{i}/', - '/{s}/', - '/{a}/' - ); + if ( isset($routes[$path] ) ) { + if( is_array( $routes[$path] ) ) { + $handler = $routes[$path][0]; + $middleware = $routes[$path][2]; + $acceptedMethods = $routes[$path][3]; + } else { + $handler = $routes[$path]; + } + } else if ( $routes ) { - $replacements = array( - '([\d]+)' , - '([a-zA-Z]+)', - '([\w-]+)' - ); + $regex = array( + '/{i}/', + '/{s}/', + '/{a}/' + ); - foreach ( $routes as $routePath => $routeDesc ){ - $routePath = preg_replace( $regex, $replacements, $routePath ); - if( preg_match( '#^/?' . $routePath . '/?$#', $path, $matches ) ){ - if( is_array( $routeDesc ) ) { - $handler = $routeDesc[0]; - if( isset( $routeDesc[2] )) { - $middleware = $routeDesc[2]; - $acceptedMethods = $routeDesc[3]; - } - } - else - $handler = $routeDesc; - $matched = $matches; - break; - } - } - } - unset( $matched[0] ); + $replacements = array( + '([\d]+)' , + '([a-zA-Z]+)', + '([\w-]+)' + ); - if( isset($middleware) ){ - $newMatched = self::callFunction( $middleware, $matched, $method, $acceptedMethods ); - /* If new wildcard param are there pass them to main handler */ - if( $newMatched ) { - self::callFunction( $handler, $newMatched, $method, $acceptedMethods ); - } else { - self::callFunction( $handler, $matched, $method, $acceptedMethods ); - } - } else { - self::callFunction( $handler, $matched, $method, $acceptedMethods ); - } + foreach ( $routes as $routePath => $routeDesc ){ + $routePath = preg_replace( $regex, $replacements, $routePath ); + if( preg_match( '#^/?' . $routePath . '/?$#', $path, $matches ) ){ + if( is_array( $routeDesc ) ) { + $handler = $routeDesc[0]; + if( isset( $routeDesc[2] )) { + $middleware = $routeDesc[2]; + $acceptedMethods = $routeDesc[3]; + } + } + else + $handler = $routeDesc; + $matched = $matches; + break; + } + } + } + unset( $matched[0] ); - /* Call all the function that are to be executed after routing */ - foreach( self::$afterFuncs as $afterFunc ) - if( $afterFunc[1] ) { - call_user_func_array( $afterFunc[0] , $afterFunc[1] ); - } else { - call_user_func( $afterFunc[0] ); - } - } + if( isset($middleware) ){ + $newMatched = self::callFunction( $middleware, $matched, $method, $acceptedMethods ); + /* If new wildcard param are there pass them to main handler */ + if( $newMatched ) { + self::callFunction( $handler, $newMatched, $method, $acceptedMethods ); + } else { + self::callFunction( $handler, $matched, $method, $acceptedMethods ); + } + } else { + self::callFunction( $handler, $matched, $method, $acceptedMethods ); + } - private static function getRequestMethod() { + /* Call all the function that are to be executed after routing */ + foreach( self::$afterFuncs as $afterFunc ) + if( $afterFunc[1] ) { + call_user_func_array( $afterFunc[0] , $afterFunc[1] ); + } else { + call_user_func( $afterFunc[0] ); + } + } + + private static function getRequestMethod() { $headers = getallheaders(); $uppercaseHeaders = array(); @@ -130,42 +140,42 @@ class Link return $_SERVER['REQUEST_METHOD']; } - /** - * Static function that helps you generate links effortlessly and pass parameters to them, thus enabling to generate dynamic links - * - * @param string $name name of the route for which the link has to be generated - * @param array $params An array of parameters that are replaced in the route if it contains wildcards - * For e.g. if route is /name/{i}/{a} and parameters passed are 1, aps then link generated will be /name/1/aps - */ - public static function route( $name, $params = array() ) - { - $href = null; - foreach ( self::$routes as $routePath => $routeDesc ) { - if( is_array( $routeDesc ) ){ - if( $name == $routeDesc[1] ){ - $href = $routePath; - for( $i = 0; $i < count($params); $i++){ - $href = preg_replace('#{(.*?)}#', $params[$i], $href, 1); - } - } - } - } - return $href; - } + /** + * Static function that helps you generate links effortlessly and pass parameters to them, thus enabling to generate dynamic links + * + * @param string $name name of the route for which the link has to be generated + * @param array $params An array of parameters that are replaced in the route if it contains wildcards + * For e.g. if route is /name/{i}/{a} and parameters passed are 1, aps then link generated will be /name/1/aps + */ + public static function route( $name, $params = array() ) + { + $href = null; + foreach ( self::$routes as $routePath => $routeDesc ) { + if( is_array( $routeDesc ) ){ + if( $name == $routeDesc[1] ){ + $href = $routePath; + for( $i = 0; $i < count($params); $i++){ + $href = preg_replace('#{(.*?)}#', $params[$i], $href, 1); + } + } + } + } + return $href; + } - /** - * Static function to handle cases when route is not found, call handler of 404 if defined else - * sends a 404 header - */ - public static function handle404() - { - /* Call '404' route if it exists */ - if( isset ( self::$routes['404'] ) ) { - call_user_func( self::$routes['404'] ); - } else { - header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); - } - } + /** + * Static function to handle cases when route is not found, call handler of 404 if defined else + * sends a 404 header + */ + public static function handle404() + { + /* Call '404' route if it exists */ + if( isset ( self::$routes['404'] ) ) { + call_user_func( self::$routes['404'] ); + } else { + header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); + } + } /** * Static function to handle both middlewares' call and main handler's call. @@ -178,64 +188,64 @@ class Link * the wildcards that were originally passed, this newParams will * be next passed to main handler */ - public static function callFunction( $handler , $matched, $method, $acceptedMethods ) - { - if (!in_array($method, $acceptedMethods)) { - print_r('Request method ' . $method . ' not allowed'); - header($_SERVER['SERVER_PROTOCOL'] . ' 405 Method Not Allowed', true, 405); + public static function callFunction( $handler , $matched, $method, $acceptedMethods ) + { + if (!in_array($method, $acceptedMethods)) { + print_r('Request method ' . $method . ' not allowed'); + header($_SERVER['SERVER_PROTOCOL'] . ' 405 Method Not Allowed', true, 405); die(); } - if ( $handler ) { - if ( is_callable( $handler ) ) { - $newParams = call_user_func_array( $handler, $matched ) ; - } else { - - /* Check if class exists in the case user is using RESTful pattern */ - - if( class_exists( $handler ) ) { - $instanceOfHandler = new $handler(); // Won't work in case of middleware since we aren't using RESTful in that - } else { - print_r('Class or function ' . $handler . ' not found'); - header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500); - die(); - } - } - } else { - self::handle404(); - } + if ( $handler ) { + if ( is_callable( $handler ) ) { + $newParams = call_user_func_array( $handler, $matched ) ; + } else { - if( isset( $instanceOfHandler ) ) { - if( method_exists( $instanceOfHandler, $method ) ) { + /* Check if class exists in the case user is using RESTful pattern */ + + if( class_exists( $handler ) ) { + $instanceOfHandler = new $handler(); // Won't work in case of middleware since we aren't using RESTful in that + } else { + print_r('Class or function ' . $handler . ' not found'); + header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500); + die(); + } + } + } else { + self::handle404(); + } + + if( isset( $instanceOfHandler ) ) { + if( method_exists( $instanceOfHandler, $method ) ) { $newParams = call_user_func_array( array( $instanceOfHandler, $method ), $matched ); - } - } - if( isset( $newParams ) && $newParams ) { - return $newParams; - } - } + } + } + if( isset( $newParams ) && $newParams ) { + return $newParams; + } + } - /** - * Static function to add functions that are to be excuted before each routing, must be called before Link::all - * - * @param string $funcName Name of the funtion to be called upon before - * @param array $params Array of parameters that are to be passed to before function, can be null but if not - * it must be an array - */ - public static function before( $funcName, $params = null ) - { - array_push( self::$beforeFuncs, array($funcName, $params)); - } + /** + * Static function to add functions that are to be excuted before each routing, must be called before Link::all + * + * @param string $funcName Name of the funtion to be called upon before + * @param array $params Array of parameters that are to be passed to before function, can be null but if not + * it must be an array + */ + public static function before( $funcName, $params = null ) + { + array_push( self::$beforeFuncs, array($funcName, $params)); + } - /** - * Static function to add functions that are to be excuted after each routing, must be called before Link::all - * - * @param string $funcName Name of the funtion to be called upon after - * @param array $params Array of parameters that are to be passed to after function, can be null but if not - * it must be an array - */ - public static function after( $funcName, $params = null ) - { - array_push( self::$afterFuncs, array($funcName, $params)); - } + /** + * Static function to add functions that are to be excuted after each routing, must be called before Link::all + * + * @param string $funcName Name of the funtion to be called upon after + * @param array $params Array of parameters that are to be passed to after function, can be null but if not + * it must be an array + */ + public static function after( $funcName, $params = null ) + { + array_push( self::$afterFuncs, array($funcName, $params)); + } } \ No newline at end of file