router.class.php 3.0 KB

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