PageRenderTime 52ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/src/EpiRoute.php

https://github.com/williamswebworks/DraftApp
PHP | 224 lines | 121 code | 21 blank | 82 comment | 28 complexity | 5da471ef59d3bc12f1e48decc05de71c MD5 | raw file
  1. <?php
  2. /**
  3. * EpiRoute master file
  4. *
  5. * This contains the EpiRoute class as wel as the EpiException abstract class
  6. * @author Jaisen Mathai <jaisen@jmathai.com>
  7. * @version 1.0
  8. * @package EpiRoute
  9. */
  10. /**
  11. * This is the EpiRoute class.
  12. * @name EpiRoute
  13. * @author Jaisen Mathai <jaisen@jmathai.com>
  14. * @final
  15. */
  16. class EpiRoute
  17. {
  18. private static $instance;
  19. private $routes = array();
  20. private $regexes= array();
  21. private $route = null;
  22. const routeKey= '__route__';
  23. const httpGet = 'GET';
  24. const httpPost= 'POST';
  25. /**
  26. * get('/', 'function');
  27. * @name get
  28. * @author Jaisen Mathai <jaisen@jmathai.com>
  29. * @param string $route
  30. * @param mixed $callback
  31. */
  32. public function get($route, $callback, $isApi = false)
  33. {
  34. $this->addRoute($route, $callback, self::httpGet, $isApi);
  35. }
  36. /**
  37. * post('/', 'function');
  38. * @name post
  39. * @author Jaisen Mathai <jaisen@jmathai.com>
  40. * @param string $route
  41. * @param mixed $callback
  42. */
  43. public function post($route, $callback, $isApi = false)
  44. {
  45. $this->addRoute($route, $callback, self::httpPost, $isApi);
  46. }
  47. /**
  48. * NOT YET IMPLEMENTED
  49. * request('/', 'function', array(EpiRoute::httpGet, EpiRoute::httpPost));
  50. * @name request
  51. * @author Jaisen Mathai <jaisen@jmathai.com>
  52. * @param string $route
  53. * @param mixed $callback
  54. */
  55. /*public function request($route, $callback, $httpMethods = array(self::httpGet, self::httpPost))
  56. {
  57. }*/
  58. /**
  59. * load('/path/to/file');
  60. * @name load
  61. * @author Jaisen Mathai <jaisen@jmathai.com>
  62. * @param string $file
  63. */
  64. public function load($file)
  65. {
  66. $file = Epi::getPath('config') . "/{$file}";
  67. if(!file_exists($file))
  68. {
  69. EpiException::raise(new EpiException("Config file ({$file}) does not exist"));
  70. break; // need to simulate same behavior if exceptions are turned off
  71. }
  72. $parsed_array = parse_ini_file($file, true);
  73. foreach($parsed_array as $route)
  74. {
  75. $method = strtolower($route['method']);
  76. if(isset($route['class']) && isset($route['function']))
  77. $this->$method($route['path'], array($route['class'], $route['function']));
  78. elseif(isset($route['function']))
  79. $this->$method($route['path'], $route['function']);
  80. }
  81. }
  82. /**
  83. * EpiRoute::run($_GET['__route__'], $_['routes']);
  84. * @name run
  85. * @author Jaisen Mathai <jaisen@jmathai.com>
  86. * @param string $route
  87. * @param array $routes
  88. * @method run
  89. * @static method
  90. */
  91. public function run($route = false, $httpMethod = null)
  92. {
  93. if($route === false)
  94. $route = isset($_GET[self::routeKey]) ? $_GET[self::routeKey] : '/';
  95. if($httpMethod === null)
  96. $httpMethod = $_SERVER['REQUEST_METHOD'];
  97. $routeDef = $this->getRoute($route, $httpMethod);
  98. $response = call_user_func_array($routeDef['callback'], $routeDef['args']);
  99. if(!$routeDef['postprocess'])
  100. return $response;
  101. else
  102. echo json_encode($response);
  103. }
  104. /**
  105. * EpiRoute::getRoute($route);
  106. * @name getRoute
  107. * @author Jaisen Mathai <jaisen@jmathai.com>
  108. * @param string $route
  109. * @method getRoute
  110. * @static method
  111. */
  112. public function getRoute($route = false, $httpMethod = null)
  113. {
  114. if($route)
  115. $this->route = $route;
  116. else
  117. $this->route = isset($_GET[self::routeKey]) ? $_GET[self::routeKey] : '/';
  118. if($httpMethod === null)
  119. $httpMethod = $_SERVER['REQUEST_METHOD'];
  120. foreach($this->regexes as $ind => $regex)
  121. {
  122. if(preg_match($regex, $this->route, $arguments))
  123. {
  124. array_shift($arguments);
  125. $def = $this->routes[$ind];
  126. if($httpMethod != $def['httpMethod'])
  127. {
  128. continue;
  129. }
  130. else if(is_array($def['callback']) && method_exists($def['callback'][0], $def['callback'][1]))
  131. {
  132. if(Epi::getSetting('debug'))
  133. getDebug()->addMessage(__CLASS__, sprintf('Matched %s : %s : %s : %s', $httpMethod, $this->route, json_encode($def['callback']), json_encode($arguments)));
  134. return array('callback' => $def['callback'], 'args' => $arguments, 'postprocess' => $def['postprocess']);
  135. }
  136. else if(function_exists($def['callback']))
  137. {
  138. if(Epi::getSetting('debug'))
  139. getDebug()->addMessage(__CLASS__, sprintf('Matched %s : %s : %s : %s', $httpMethod, $this->route, json_encode($def['callback']), json_encode($arguments)));
  140. return array('callback' => $def['callback'], 'args' => $arguments, 'postprocess' => $def['postprocess']);
  141. }
  142. EpiException::raise(new EpiException('Could not call ' . json_encode($def) . " for route {$regex}"));
  143. }
  144. }
  145. EpiException::raise(new EpiException("Could not find route {$this->route} from {$_SERVER['REQUEST_URI']}"));
  146. }
  147. /**
  148. * EpiRoute::redirect($url);
  149. * @name redirect
  150. * @author Jaisen Mathai <jaisen@jmathai.com>
  151. * @param string $url
  152. * @method redirect
  153. * @static method
  154. */
  155. public function redirect($url, $code = null, $offDomain = false)
  156. {
  157. $continue = !empty($url);
  158. if($offDomain === false && preg_match('#^https?://#', $url))
  159. $continue = false;
  160. if($continue)
  161. {
  162. if($code != null && (int)$code == $code)
  163. header("Status: {$code}");
  164. header("Location: {$url}");
  165. die();
  166. }
  167. EpiException::raise(new EpiException("Redirect to {$url} failed"));
  168. }
  169. public function route()
  170. {
  171. return $this->route;
  172. }
  173. /*
  174. * EpiRoute::getInstance
  175. */
  176. public static function getInstance()
  177. {
  178. if(self::$instance)
  179. return self::$instance;
  180. self::$instance = new EpiRoute;
  181. return self::$instance;
  182. }
  183. /**
  184. * addRoute('/', 'function', 'GET');
  185. * @name addRoute
  186. * @author Jaisen Mathai <jaisen@jmathai.com>
  187. * @param string $route
  188. * @param mixed $callback
  189. * @param mixed $method
  190. * @param string $callback
  191. */
  192. private function addRoute($route, $callback, $method, $postprocess = false)
  193. {
  194. $this->routes[] = array('httpMethod' => $method, 'path' => $route, 'callback' => $callback, 'postprocess' => $postprocess);
  195. $this->regexes[]= "#^{$route}\$#";
  196. if(Epi::getSetting('debug'))
  197. getDebug()->addMessage(__CLASS__, sprintf('Found %s : %s : %s', $method, $route, json_encode($callback)));
  198. }
  199. }
  200. function getRoute()
  201. {
  202. return EpiRoute::getInstance();
  203. }