router.class.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. namespace Juju\App;
  3. require_once('path.class.php');
  4. $dir = dirname(__DIR__);
  5. require_once(realpath("{$dir}/events.trait.php"));
  6. $dir = "{$dir}/Http/";
  7. require_once(realpath("{$dir}/request.class.php"));
  8. require_once(realpath("{$dir}/response.class.php"));
  9. use \Juju\{Http\Request, Http\Response, Events};
  10. class Router {
  11. use Events;
  12. private $_paths = [];
  13. private $_routers = [];
  14. private $_base = '/';
  15. private $responses = [];
  16. private $_handled = false;
  17. public function __construct(string $base = null, array $paths = null){
  18. if($paths != null){
  19. $this->paths($paths);
  20. }
  21. if($base != null){
  22. $this->base($base);
  23. }
  24. }
  25. public function __get($name){
  26. switch($name){
  27. case 'base':
  28. return $this->_base;
  29. break;
  30. case 'handled':
  31. return $this->_handled;
  32. break;
  33. }
  34. }
  35. public function __clone(){
  36. // No cloning
  37. }
  38. public function __destruct(){
  39. $this->_paths = [];
  40. }
  41. public function __toString(){
  42. return "[Router]";
  43. }
  44. public function base(string $base){
  45. $this->_base = $base;
  46. }
  47. public function url(string $url){
  48. return preg_replace('/(\/+)/','/',$url);
  49. }
  50. public function prefix(string $prefix, callable $fn){
  51. $found = false;
  52. foreach($this->_routers as $k => $router){
  53. if($router->base == $prefix){
  54. $found = true;
  55. $fn($router);
  56. break;
  57. }
  58. }
  59. if(!$found){
  60. $router= new Router($prefix);
  61. $this->_routers[] = $router;
  62. $fn($router);
  63. }
  64. }
  65. // fn = function(response,args){}
  66. public function path(string $path, callable $fn){
  67. $obj = false;
  68. foreach($this->_paths as $k => $p){
  69. if($p->path == $path){
  70. $obj = $p;
  71. }
  72. }
  73. if(!$obj){
  74. $obj = new Path($path);
  75. array_push($this->_paths,$obj);
  76. }
  77. return $obj->handle($fn);
  78. }
  79. public function paths(array $paths){
  80. foreach($paths as $path => $fn){
  81. $this->path($path,$fn);
  82. }
  83. }
  84. public function clear(){
  85. $this->_paths = [];
  86. }
  87. public function handle(string $path, Request $req = null, Response $res = null, callable $fn = null, callable $onerror = null){
  88. if(strpos($path, $this->base) !== false){
  89. $path = substr($path,strpos($path,$this->base)+strlen($this->base));
  90. if($path[0] != '/'){
  91. $path = '/'.$path;
  92. }
  93. if(is_null($req)){
  94. $req = new Request();
  95. }
  96. if(is_null($res)){
  97. $res = new Response();
  98. }
  99. if(!in_array($res,$this->responses)){
  100. array_push($this->responses,$res);
  101. }
  102. $this->fire('handle', $req, $res);
  103. $handled = false;
  104. foreach($this->_routers as $prefix => $router){
  105. $router->handle($path, $req, $res);
  106. $handled = $handled ||$router->handled;
  107. }
  108. ob_start();
  109. foreach($this->_paths as $k => $p){
  110. if($p->matches($path)){
  111. $handled = true;
  112. try{
  113. $p($req, $res, $p->args($path));
  114. }catch(\Exception $e){
  115. if(!is_null($onerror)){
  116. $onerror($req, $res,$e);
  117. }else{
  118. throw $e;
  119. }
  120. }
  121. }
  122. }
  123. $this->_handled = $handled;
  124. if(!$handled && !is_null($fn)){
  125. $fn($req, $res);
  126. }
  127. $res->output .= ob_get_contents();
  128. ob_end_clean();
  129. $this->fire('afterhandle', $req, $res);
  130. }
  131. return $res;
  132. }
  133. }
  134. ?>